1 |
280 |
jeremybenn |
/* Output Dwarf2 format symbol table information from GCC.
|
2 |
|
|
Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
3 |
|
|
2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
4 |
|
|
Free Software Foundation, Inc.
|
5 |
|
|
Contributed by Gary Funck (gary@intrepid.com).
|
6 |
|
|
Derived from DWARF 1 implementation of Ron Guilmette (rfg@monkeys.com).
|
7 |
|
|
Extensively modified by Jason Merrill (jason@cygnus.com).
|
8 |
|
|
|
9 |
|
|
This file is part of GCC.
|
10 |
|
|
|
11 |
|
|
GCC is free software; you can redistribute it and/or modify it under
|
12 |
|
|
the terms of the GNU General Public License as published by the Free
|
13 |
|
|
Software Foundation; either version 3, or (at your option) any later
|
14 |
|
|
version.
|
15 |
|
|
|
16 |
|
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
17 |
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
18 |
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
19 |
|
|
for more details.
|
20 |
|
|
|
21 |
|
|
You should have received a copy of the GNU General Public License
|
22 |
|
|
along with GCC; see the file COPYING3. If not see
|
23 |
|
|
<http://www.gnu.org/licenses/>. */
|
24 |
|
|
|
25 |
|
|
/* TODO: Emit .debug_line header even when there are no functions, since
|
26 |
|
|
the file numbers are used by .debug_info. Alternately, leave
|
27 |
|
|
out locations for types and decls.
|
28 |
|
|
Avoid talking about ctors and op= for PODs.
|
29 |
|
|
Factor out common prologue sequences into multiple CIEs. */
|
30 |
|
|
|
31 |
|
|
/* The first part of this file deals with the DWARF 2 frame unwind
|
32 |
|
|
information, which is also used by the GCC efficient exception handling
|
33 |
|
|
mechanism. The second part, controlled only by an #ifdef
|
34 |
|
|
DWARF2_DEBUGGING_INFO, deals with the other DWARF 2 debugging
|
35 |
|
|
information. */
|
36 |
|
|
|
37 |
|
|
/* DWARF2 Abbreviation Glossary:
|
38 |
|
|
|
39 |
|
|
CFA = Canonical Frame Address
|
40 |
|
|
a fixed address on the stack which identifies a call frame.
|
41 |
|
|
We define it to be the value of SP just before the call insn.
|
42 |
|
|
The CFA register and offset, which may change during the course
|
43 |
|
|
of the function, are used to calculate its value at runtime.
|
44 |
|
|
|
45 |
|
|
CFI = Call Frame Instruction
|
46 |
|
|
an instruction for the DWARF2 abstract machine
|
47 |
|
|
|
48 |
|
|
CIE = Common Information Entry
|
49 |
|
|
information describing information common to one or more FDEs
|
50 |
|
|
|
51 |
|
|
DIE = Debugging Information Entry
|
52 |
|
|
|
53 |
|
|
FDE = Frame Description Entry
|
54 |
|
|
information describing the stack call frame, in particular,
|
55 |
|
|
how to restore registers
|
56 |
|
|
|
57 |
|
|
DW_CFA_... = DWARF2 CFA call frame instruction
|
58 |
|
|
DW_TAG_... = DWARF2 DIE tag */
|
59 |
|
|
|
60 |
|
|
#include "config.h"
|
61 |
|
|
#include "system.h"
|
62 |
|
|
#include "coretypes.h"
|
63 |
|
|
#include "tm.h"
|
64 |
|
|
#include "tree.h"
|
65 |
|
|
#include "version.h"
|
66 |
|
|
#include "flags.h"
|
67 |
|
|
#include "real.h"
|
68 |
|
|
#include "rtl.h"
|
69 |
|
|
#include "hard-reg-set.h"
|
70 |
|
|
#include "regs.h"
|
71 |
|
|
#include "insn-config.h"
|
72 |
|
|
#include "reload.h"
|
73 |
|
|
#include "function.h"
|
74 |
|
|
#include "output.h"
|
75 |
|
|
#include "expr.h"
|
76 |
|
|
#include "libfuncs.h"
|
77 |
|
|
#include "except.h"
|
78 |
|
|
#include "dwarf2.h"
|
79 |
|
|
#include "dwarf2out.h"
|
80 |
|
|
#include "dwarf2asm.h"
|
81 |
|
|
#include "toplev.h"
|
82 |
|
|
#include "varray.h"
|
83 |
|
|
#include "ggc.h"
|
84 |
|
|
#include "md5.h"
|
85 |
|
|
#include "tm_p.h"
|
86 |
|
|
#include "diagnostic.h"
|
87 |
|
|
#include "debug.h"
|
88 |
|
|
#include "target.h"
|
89 |
|
|
#include "langhooks.h"
|
90 |
|
|
#include "hashtab.h"
|
91 |
|
|
#include "cgraph.h"
|
92 |
|
|
#include "input.h"
|
93 |
|
|
#include "gimple.h"
|
94 |
|
|
#include "tree-pass.h"
|
95 |
|
|
|
96 |
|
|
#ifdef DWARF2_DEBUGGING_INFO
|
97 |
|
|
static void dwarf2out_source_line (unsigned int, const char *, int, bool);
|
98 |
|
|
|
99 |
|
|
static rtx last_var_location_insn;
|
100 |
|
|
#endif
|
101 |
|
|
|
102 |
|
|
#ifdef VMS_DEBUGGING_INFO
|
103 |
|
|
int vms_file_stats_name (const char *, long long *, long *, char *, int *);
|
104 |
|
|
|
105 |
|
|
/* Define this macro to be a nonzero value if the directory specifications
|
106 |
|
|
which are output in the debug info should end with a separator. */
|
107 |
|
|
#define DWARF2_DIR_SHOULD_END_WITH_SEPARATOR 1
|
108 |
|
|
/* Define this macro to evaluate to a nonzero value if GCC should refrain
|
109 |
|
|
from generating indirect strings in DWARF2 debug information, for instance
|
110 |
|
|
if your target is stuck with an old version of GDB that is unable to
|
111 |
|
|
process them properly or uses VMS Debug. */
|
112 |
|
|
#define DWARF2_INDIRECT_STRING_SUPPORT_MISSING_ON_TARGET 1
|
113 |
|
|
#else
|
114 |
|
|
#define DWARF2_DIR_SHOULD_END_WITH_SEPARATOR 0
|
115 |
|
|
#define DWARF2_INDIRECT_STRING_SUPPORT_MISSING_ON_TARGET 0
|
116 |
|
|
#endif
|
117 |
|
|
|
118 |
|
|
#ifndef DWARF2_FRAME_INFO
|
119 |
|
|
# ifdef DWARF2_DEBUGGING_INFO
|
120 |
|
|
# define DWARF2_FRAME_INFO \
|
121 |
|
|
(write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG)
|
122 |
|
|
# else
|
123 |
|
|
# define DWARF2_FRAME_INFO 0
|
124 |
|
|
# endif
|
125 |
|
|
#endif
|
126 |
|
|
|
127 |
|
|
/* Map register numbers held in the call frame info that gcc has
|
128 |
|
|
collected using DWARF_FRAME_REGNUM to those that should be output in
|
129 |
|
|
.debug_frame and .eh_frame. */
|
130 |
|
|
#ifndef DWARF2_FRAME_REG_OUT
|
131 |
|
|
#define DWARF2_FRAME_REG_OUT(REGNO, FOR_EH) (REGNO)
|
132 |
|
|
#endif
|
133 |
|
|
|
134 |
|
|
/* Save the result of dwarf2out_do_frame across PCH. */
|
135 |
|
|
static GTY(()) bool saved_do_cfi_asm = 0;
|
136 |
|
|
|
137 |
|
|
/* Decide whether we want to emit frame unwind information for the current
|
138 |
|
|
translation unit. */
|
139 |
|
|
|
140 |
|
|
int
|
141 |
|
|
dwarf2out_do_frame (void)
|
142 |
|
|
{
|
143 |
|
|
/* We want to emit correct CFA location expressions or lists, so we
|
144 |
|
|
have to return true if we're going to output debug info, even if
|
145 |
|
|
we're not going to output frame or unwind info. */
|
146 |
|
|
return (write_symbols == DWARF2_DEBUG
|
147 |
|
|
|| write_symbols == VMS_AND_DWARF2_DEBUG
|
148 |
|
|
|| DWARF2_FRAME_INFO || saved_do_cfi_asm
|
149 |
|
|
#ifdef DWARF2_UNWIND_INFO
|
150 |
|
|
|| (DWARF2_UNWIND_INFO
|
151 |
|
|
&& (flag_unwind_tables
|
152 |
|
|
|| (flag_exceptions && ! USING_SJLJ_EXCEPTIONS)))
|
153 |
|
|
#endif
|
154 |
|
|
);
|
155 |
|
|
}
|
156 |
|
|
|
157 |
|
|
/* Decide whether to emit frame unwind via assembler directives. */
|
158 |
|
|
|
159 |
|
|
int
|
160 |
|
|
dwarf2out_do_cfi_asm (void)
|
161 |
|
|
{
|
162 |
|
|
int enc;
|
163 |
|
|
|
164 |
|
|
#ifdef MIPS_DEBUGGING_INFO
|
165 |
|
|
return false;
|
166 |
|
|
#endif
|
167 |
|
|
if (!flag_dwarf2_cfi_asm || !dwarf2out_do_frame ())
|
168 |
|
|
return false;
|
169 |
|
|
if (saved_do_cfi_asm)
|
170 |
|
|
return true;
|
171 |
|
|
if (!HAVE_GAS_CFI_PERSONALITY_DIRECTIVE)
|
172 |
|
|
return false;
|
173 |
|
|
|
174 |
|
|
/* Make sure the personality encoding is one the assembler can support.
|
175 |
|
|
In particular, aligned addresses can't be handled. */
|
176 |
|
|
enc = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2,/*global=*/1);
|
177 |
|
|
if ((enc & 0x70) != 0 && (enc & 0x70) != DW_EH_PE_pcrel)
|
178 |
|
|
return false;
|
179 |
|
|
enc = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0,/*global=*/0);
|
180 |
|
|
if ((enc & 0x70) != 0 && (enc & 0x70) != DW_EH_PE_pcrel)
|
181 |
|
|
return false;
|
182 |
|
|
|
183 |
|
|
if (!HAVE_GAS_CFI_SECTIONS_DIRECTIVE)
|
184 |
|
|
{
|
185 |
|
|
#ifdef TARGET_UNWIND_INFO
|
186 |
|
|
return false;
|
187 |
|
|
#else
|
188 |
|
|
if (USING_SJLJ_EXCEPTIONS || (!flag_unwind_tables && !flag_exceptions))
|
189 |
|
|
return false;
|
190 |
|
|
#endif
|
191 |
|
|
}
|
192 |
|
|
|
193 |
|
|
saved_do_cfi_asm = true;
|
194 |
|
|
return true;
|
195 |
|
|
}
|
196 |
|
|
|
197 |
|
|
/* The size of the target's pointer type. */
|
198 |
|
|
#ifndef PTR_SIZE
|
199 |
|
|
#define PTR_SIZE (POINTER_SIZE / BITS_PER_UNIT)
|
200 |
|
|
#endif
|
201 |
|
|
|
202 |
|
|
/* Array of RTXes referenced by the debugging information, which therefore
|
203 |
|
|
must be kept around forever. */
|
204 |
|
|
static GTY(()) VEC(rtx,gc) *used_rtx_array;
|
205 |
|
|
|
206 |
|
|
/* A pointer to the base of a list of incomplete types which might be
|
207 |
|
|
completed at some later time. incomplete_types_list needs to be a
|
208 |
|
|
VEC(tree,gc) because we want to tell the garbage collector about
|
209 |
|
|
it. */
|
210 |
|
|
static GTY(()) VEC(tree,gc) *incomplete_types;
|
211 |
|
|
|
212 |
|
|
/* A pointer to the base of a table of references to declaration
|
213 |
|
|
scopes. This table is a display which tracks the nesting
|
214 |
|
|
of declaration scopes at the current scope and containing
|
215 |
|
|
scopes. This table is used to find the proper place to
|
216 |
|
|
define type declaration DIE's. */
|
217 |
|
|
static GTY(()) VEC(tree,gc) *decl_scope_table;
|
218 |
|
|
|
219 |
|
|
/* Pointers to various DWARF2 sections. */
|
220 |
|
|
static GTY(()) section *debug_info_section;
|
221 |
|
|
static GTY(()) section *debug_abbrev_section;
|
222 |
|
|
static GTY(()) section *debug_aranges_section;
|
223 |
|
|
static GTY(()) section *debug_macinfo_section;
|
224 |
|
|
static GTY(()) section *debug_line_section;
|
225 |
|
|
static GTY(()) section *debug_loc_section;
|
226 |
|
|
static GTY(()) section *debug_pubnames_section;
|
227 |
|
|
static GTY(()) section *debug_pubtypes_section;
|
228 |
|
|
static GTY(()) section *debug_dcall_section;
|
229 |
|
|
static GTY(()) section *debug_vcall_section;
|
230 |
|
|
static GTY(()) section *debug_str_section;
|
231 |
|
|
static GTY(()) section *debug_ranges_section;
|
232 |
|
|
static GTY(()) section *debug_frame_section;
|
233 |
|
|
|
234 |
|
|
/* Personality decl of current unit. Used only when assembler does not support
|
235 |
|
|
personality CFI. */
|
236 |
|
|
static GTY(()) rtx current_unit_personality;
|
237 |
|
|
|
238 |
|
|
/* How to start an assembler comment. */
|
239 |
|
|
#ifndef ASM_COMMENT_START
|
240 |
|
|
#define ASM_COMMENT_START ";#"
|
241 |
|
|
#endif
|
242 |
|
|
|
243 |
|
|
typedef struct dw_cfi_struct *dw_cfi_ref;
|
244 |
|
|
typedef struct dw_fde_struct *dw_fde_ref;
|
245 |
|
|
typedef union dw_cfi_oprnd_struct *dw_cfi_oprnd_ref;
|
246 |
|
|
|
247 |
|
|
/* Call frames are described using a sequence of Call Frame
|
248 |
|
|
Information instructions. The register number, offset
|
249 |
|
|
and address fields are provided as possible operands;
|
250 |
|
|
their use is selected by the opcode field. */
|
251 |
|
|
|
252 |
|
|
enum dw_cfi_oprnd_type {
|
253 |
|
|
dw_cfi_oprnd_unused,
|
254 |
|
|
dw_cfi_oprnd_reg_num,
|
255 |
|
|
dw_cfi_oprnd_offset,
|
256 |
|
|
dw_cfi_oprnd_addr,
|
257 |
|
|
dw_cfi_oprnd_loc
|
258 |
|
|
};
|
259 |
|
|
|
260 |
|
|
typedef union GTY(()) dw_cfi_oprnd_struct {
|
261 |
|
|
unsigned int GTY ((tag ("dw_cfi_oprnd_reg_num"))) dw_cfi_reg_num;
|
262 |
|
|
HOST_WIDE_INT GTY ((tag ("dw_cfi_oprnd_offset"))) dw_cfi_offset;
|
263 |
|
|
const char * GTY ((tag ("dw_cfi_oprnd_addr"))) dw_cfi_addr;
|
264 |
|
|
struct dw_loc_descr_struct * GTY ((tag ("dw_cfi_oprnd_loc"))) dw_cfi_loc;
|
265 |
|
|
}
|
266 |
|
|
dw_cfi_oprnd;
|
267 |
|
|
|
268 |
|
|
typedef struct GTY(()) dw_cfi_struct {
|
269 |
|
|
dw_cfi_ref dw_cfi_next;
|
270 |
|
|
enum dwarf_call_frame_info dw_cfi_opc;
|
271 |
|
|
dw_cfi_oprnd GTY ((desc ("dw_cfi_oprnd1_desc (%1.dw_cfi_opc)")))
|
272 |
|
|
dw_cfi_oprnd1;
|
273 |
|
|
dw_cfi_oprnd GTY ((desc ("dw_cfi_oprnd2_desc (%1.dw_cfi_opc)")))
|
274 |
|
|
dw_cfi_oprnd2;
|
275 |
|
|
}
|
276 |
|
|
dw_cfi_node;
|
277 |
|
|
|
278 |
|
|
/* This is how we define the location of the CFA. We use to handle it
|
279 |
|
|
as REG + OFFSET all the time, but now it can be more complex.
|
280 |
|
|
It can now be either REG + CFA_OFFSET or *(REG + BASE_OFFSET) + CFA_OFFSET.
|
281 |
|
|
Instead of passing around REG and OFFSET, we pass a copy
|
282 |
|
|
of this structure. */
|
283 |
|
|
typedef struct GTY(()) cfa_loc {
|
284 |
|
|
HOST_WIDE_INT offset;
|
285 |
|
|
HOST_WIDE_INT base_offset;
|
286 |
|
|
unsigned int reg;
|
287 |
|
|
BOOL_BITFIELD indirect : 1; /* 1 if CFA is accessed via a dereference. */
|
288 |
|
|
BOOL_BITFIELD in_use : 1; /* 1 if a saved cfa is stored here. */
|
289 |
|
|
} dw_cfa_location;
|
290 |
|
|
|
291 |
|
|
/* All call frame descriptions (FDE's) in the GCC generated DWARF
|
292 |
|
|
refer to a single Common Information Entry (CIE), defined at
|
293 |
|
|
the beginning of the .debug_frame section. This use of a single
|
294 |
|
|
CIE obviates the need to keep track of multiple CIE's
|
295 |
|
|
in the DWARF generation routines below. */
|
296 |
|
|
|
297 |
|
|
typedef struct GTY(()) dw_fde_struct {
|
298 |
|
|
tree decl;
|
299 |
|
|
const char *dw_fde_begin;
|
300 |
|
|
const char *dw_fde_current_label;
|
301 |
|
|
const char *dw_fde_end;
|
302 |
|
|
const char *dw_fde_hot_section_label;
|
303 |
|
|
const char *dw_fde_hot_section_end_label;
|
304 |
|
|
const char *dw_fde_unlikely_section_label;
|
305 |
|
|
const char *dw_fde_unlikely_section_end_label;
|
306 |
|
|
dw_cfi_ref dw_fde_cfi;
|
307 |
|
|
dw_cfi_ref dw_fde_switch_cfi; /* Last CFI before switching sections. */
|
308 |
|
|
unsigned funcdef_number;
|
309 |
|
|
HOST_WIDE_INT stack_realignment;
|
310 |
|
|
/* Dynamic realign argument pointer register. */
|
311 |
|
|
unsigned int drap_reg;
|
312 |
|
|
/* Virtual dynamic realign argument pointer register. */
|
313 |
|
|
unsigned int vdrap_reg;
|
314 |
|
|
unsigned all_throwers_are_sibcalls : 1;
|
315 |
|
|
unsigned nothrow : 1;
|
316 |
|
|
unsigned uses_eh_lsda : 1;
|
317 |
|
|
/* Whether we did stack realign in this call frame. */
|
318 |
|
|
unsigned stack_realign : 1;
|
319 |
|
|
/* Whether dynamic realign argument pointer register has been saved. */
|
320 |
|
|
unsigned drap_reg_saved: 1;
|
321 |
|
|
/* True iff dw_fde_begin label is in text_section or cold_text_section. */
|
322 |
|
|
unsigned in_std_section : 1;
|
323 |
|
|
/* True iff dw_fde_unlikely_section_label is in text_section or
|
324 |
|
|
cold_text_section. */
|
325 |
|
|
unsigned cold_in_std_section : 1;
|
326 |
|
|
/* True iff switched sections. */
|
327 |
|
|
unsigned dw_fde_switched_sections : 1;
|
328 |
|
|
/* True iff switching from cold to hot section. */
|
329 |
|
|
unsigned dw_fde_switched_cold_to_hot : 1;
|
330 |
|
|
}
|
331 |
|
|
dw_fde_node;
|
332 |
|
|
|
333 |
|
|
/* Maximum size (in bytes) of an artificially generated label. */
|
334 |
|
|
#define MAX_ARTIFICIAL_LABEL_BYTES 30
|
335 |
|
|
|
336 |
|
|
/* The size of addresses as they appear in the Dwarf 2 data.
|
337 |
|
|
Some architectures use word addresses to refer to code locations,
|
338 |
|
|
but Dwarf 2 info always uses byte addresses. On such machines,
|
339 |
|
|
Dwarf 2 addresses need to be larger than the architecture's
|
340 |
|
|
pointers. */
|
341 |
|
|
#ifndef DWARF2_ADDR_SIZE
|
342 |
|
|
#define DWARF2_ADDR_SIZE (POINTER_SIZE / BITS_PER_UNIT)
|
343 |
|
|
#endif
|
344 |
|
|
|
345 |
|
|
/* The size in bytes of a DWARF field indicating an offset or length
|
346 |
|
|
relative to a debug info section, specified to be 4 bytes in the
|
347 |
|
|
DWARF-2 specification. The SGI/MIPS ABI defines it to be the same
|
348 |
|
|
as PTR_SIZE. */
|
349 |
|
|
|
350 |
|
|
#ifndef DWARF_OFFSET_SIZE
|
351 |
|
|
#define DWARF_OFFSET_SIZE 4
|
352 |
|
|
#endif
|
353 |
|
|
|
354 |
|
|
/* The size in bytes of a DWARF 4 type signature. */
|
355 |
|
|
|
356 |
|
|
#ifndef DWARF_TYPE_SIGNATURE_SIZE
|
357 |
|
|
#define DWARF_TYPE_SIGNATURE_SIZE 8
|
358 |
|
|
#endif
|
359 |
|
|
|
360 |
|
|
/* According to the (draft) DWARF 3 specification, the initial length
|
361 |
|
|
should either be 4 or 12 bytes. When it's 12 bytes, the first 4
|
362 |
|
|
bytes are 0xffffffff, followed by the length stored in the next 8
|
363 |
|
|
bytes.
|
364 |
|
|
|
365 |
|
|
However, the SGI/MIPS ABI uses an initial length which is equal to
|
366 |
|
|
DWARF_OFFSET_SIZE. It is defined (elsewhere) accordingly. */
|
367 |
|
|
|
368 |
|
|
#ifndef DWARF_INITIAL_LENGTH_SIZE
|
369 |
|
|
#define DWARF_INITIAL_LENGTH_SIZE (DWARF_OFFSET_SIZE == 4 ? 4 : 12)
|
370 |
|
|
#endif
|
371 |
|
|
|
372 |
|
|
/* Round SIZE up to the nearest BOUNDARY. */
|
373 |
|
|
#define DWARF_ROUND(SIZE,BOUNDARY) \
|
374 |
|
|
((((SIZE) + (BOUNDARY) - 1) / (BOUNDARY)) * (BOUNDARY))
|
375 |
|
|
|
376 |
|
|
/* Offsets recorded in opcodes are a multiple of this alignment factor. */
|
377 |
|
|
#ifndef DWARF_CIE_DATA_ALIGNMENT
|
378 |
|
|
#ifdef STACK_GROWS_DOWNWARD
|
379 |
|
|
#define DWARF_CIE_DATA_ALIGNMENT (-((int) UNITS_PER_WORD))
|
380 |
|
|
#else
|
381 |
|
|
#define DWARF_CIE_DATA_ALIGNMENT ((int) UNITS_PER_WORD)
|
382 |
|
|
#endif
|
383 |
|
|
#endif
|
384 |
|
|
|
385 |
|
|
/* CIE identifier. */
|
386 |
|
|
#if HOST_BITS_PER_WIDE_INT >= 64
|
387 |
|
|
#define DWARF_CIE_ID \
|
388 |
|
|
(unsigned HOST_WIDE_INT) (DWARF_OFFSET_SIZE == 4 ? DW_CIE_ID : DW64_CIE_ID)
|
389 |
|
|
#else
|
390 |
|
|
#define DWARF_CIE_ID DW_CIE_ID
|
391 |
|
|
#endif
|
392 |
|
|
|
393 |
|
|
/* A pointer to the base of a table that contains frame description
|
394 |
|
|
information for each routine. */
|
395 |
|
|
static GTY((length ("fde_table_allocated"))) dw_fde_ref fde_table;
|
396 |
|
|
|
397 |
|
|
/* Number of elements currently allocated for fde_table. */
|
398 |
|
|
static GTY(()) unsigned fde_table_allocated;
|
399 |
|
|
|
400 |
|
|
/* Number of elements in fde_table currently in use. */
|
401 |
|
|
static GTY(()) unsigned fde_table_in_use;
|
402 |
|
|
|
403 |
|
|
/* Size (in elements) of increments by which we may expand the
|
404 |
|
|
fde_table. */
|
405 |
|
|
#define FDE_TABLE_INCREMENT 256
|
406 |
|
|
|
407 |
|
|
/* Get the current fde_table entry we should use. */
|
408 |
|
|
|
409 |
|
|
static inline dw_fde_ref
|
410 |
|
|
current_fde (void)
|
411 |
|
|
{
|
412 |
|
|
return fde_table_in_use ? &fde_table[fde_table_in_use - 1] : NULL;
|
413 |
|
|
}
|
414 |
|
|
|
415 |
|
|
/* A list of call frame insns for the CIE. */
|
416 |
|
|
static GTY(()) dw_cfi_ref cie_cfi_head;
|
417 |
|
|
|
418 |
|
|
#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
|
419 |
|
|
/* Some DWARF extensions (e.g., MIPS/SGI) implement a subprogram
|
420 |
|
|
attribute that accelerates the lookup of the FDE associated
|
421 |
|
|
with the subprogram. This variable holds the table index of the FDE
|
422 |
|
|
associated with the current function (body) definition. */
|
423 |
|
|
static unsigned current_funcdef_fde;
|
424 |
|
|
#endif
|
425 |
|
|
|
426 |
|
|
struct GTY(()) indirect_string_node {
|
427 |
|
|
const char *str;
|
428 |
|
|
unsigned int refcount;
|
429 |
|
|
enum dwarf_form form;
|
430 |
|
|
char *label;
|
431 |
|
|
};
|
432 |
|
|
|
433 |
|
|
static GTY ((param_is (struct indirect_string_node))) htab_t debug_str_hash;
|
434 |
|
|
|
435 |
|
|
/* True if the compilation unit has location entries that reference
|
436 |
|
|
debug strings. */
|
437 |
|
|
static GTY(()) bool debug_str_hash_forced = false;
|
438 |
|
|
|
439 |
|
|
static GTY(()) int dw2_string_counter;
|
440 |
|
|
static GTY(()) unsigned long dwarf2out_cfi_label_num;
|
441 |
|
|
|
442 |
|
|
/* True if the compilation unit places functions in more than one section. */
|
443 |
|
|
static GTY(()) bool have_multiple_function_sections = false;
|
444 |
|
|
|
445 |
|
|
/* Whether the default text and cold text sections have been used at all. */
|
446 |
|
|
|
447 |
|
|
static GTY(()) bool text_section_used = false;
|
448 |
|
|
static GTY(()) bool cold_text_section_used = false;
|
449 |
|
|
|
450 |
|
|
/* The default cold text section. */
|
451 |
|
|
static GTY(()) section *cold_text_section;
|
452 |
|
|
|
453 |
|
|
#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
|
454 |
|
|
|
455 |
|
|
/* Forward declarations for functions defined in this file. */
|
456 |
|
|
|
457 |
|
|
static char *stripattributes (const char *);
|
458 |
|
|
static const char *dwarf_cfi_name (unsigned);
|
459 |
|
|
static dw_cfi_ref new_cfi (void);
|
460 |
|
|
static void add_cfi (dw_cfi_ref *, dw_cfi_ref);
|
461 |
|
|
static void add_fde_cfi (const char *, dw_cfi_ref);
|
462 |
|
|
static void lookup_cfa_1 (dw_cfi_ref, dw_cfa_location *, dw_cfa_location *);
|
463 |
|
|
static void lookup_cfa (dw_cfa_location *);
|
464 |
|
|
static void reg_save (const char *, unsigned, unsigned, HOST_WIDE_INT);
|
465 |
|
|
#ifdef DWARF2_UNWIND_INFO
|
466 |
|
|
static void initial_return_save (rtx);
|
467 |
|
|
#endif
|
468 |
|
|
static HOST_WIDE_INT stack_adjust_offset (const_rtx, HOST_WIDE_INT,
|
469 |
|
|
HOST_WIDE_INT);
|
470 |
|
|
static void output_cfi (dw_cfi_ref, dw_fde_ref, int);
|
471 |
|
|
static void output_cfi_directive (dw_cfi_ref);
|
472 |
|
|
static void output_call_frame_info (int);
|
473 |
|
|
static void dwarf2out_note_section_used (void);
|
474 |
|
|
static void flush_queued_reg_saves (void);
|
475 |
|
|
static bool clobbers_queued_reg_save (const_rtx);
|
476 |
|
|
static void dwarf2out_frame_debug_expr (rtx, const char *);
|
477 |
|
|
|
478 |
|
|
/* Support for complex CFA locations. */
|
479 |
|
|
static void output_cfa_loc (dw_cfi_ref);
|
480 |
|
|
static void output_cfa_loc_raw (dw_cfi_ref);
|
481 |
|
|
static void get_cfa_from_loc_descr (dw_cfa_location *,
|
482 |
|
|
struct dw_loc_descr_struct *);
|
483 |
|
|
static struct dw_loc_descr_struct *build_cfa_loc
|
484 |
|
|
(dw_cfa_location *, HOST_WIDE_INT);
|
485 |
|
|
static struct dw_loc_descr_struct *build_cfa_aligned_loc
|
486 |
|
|
(HOST_WIDE_INT, HOST_WIDE_INT);
|
487 |
|
|
static void def_cfa_1 (const char *, dw_cfa_location *);
|
488 |
|
|
|
489 |
|
|
/* How to start an assembler comment. */
|
490 |
|
|
#ifndef ASM_COMMENT_START
|
491 |
|
|
#define ASM_COMMENT_START ";#"
|
492 |
|
|
#endif
|
493 |
|
|
|
494 |
|
|
/* Data and reference forms for relocatable data. */
|
495 |
|
|
#define DW_FORM_data (DWARF_OFFSET_SIZE == 8 ? DW_FORM_data8 : DW_FORM_data4)
|
496 |
|
|
#define DW_FORM_ref (DWARF_OFFSET_SIZE == 8 ? DW_FORM_ref8 : DW_FORM_ref4)
|
497 |
|
|
|
498 |
|
|
#ifndef DEBUG_FRAME_SECTION
|
499 |
|
|
#define DEBUG_FRAME_SECTION ".debug_frame"
|
500 |
|
|
#endif
|
501 |
|
|
|
502 |
|
|
#ifndef FUNC_BEGIN_LABEL
|
503 |
|
|
#define FUNC_BEGIN_LABEL "LFB"
|
504 |
|
|
#endif
|
505 |
|
|
|
506 |
|
|
#ifndef FUNC_END_LABEL
|
507 |
|
|
#define FUNC_END_LABEL "LFE"
|
508 |
|
|
#endif
|
509 |
|
|
|
510 |
|
|
#ifndef FRAME_BEGIN_LABEL
|
511 |
|
|
#define FRAME_BEGIN_LABEL "Lframe"
|
512 |
|
|
#endif
|
513 |
|
|
#define CIE_AFTER_SIZE_LABEL "LSCIE"
|
514 |
|
|
#define CIE_END_LABEL "LECIE"
|
515 |
|
|
#define FDE_LABEL "LSFDE"
|
516 |
|
|
#define FDE_AFTER_SIZE_LABEL "LASFDE"
|
517 |
|
|
#define FDE_END_LABEL "LEFDE"
|
518 |
|
|
#define LINE_NUMBER_BEGIN_LABEL "LSLT"
|
519 |
|
|
#define LINE_NUMBER_END_LABEL "LELT"
|
520 |
|
|
#define LN_PROLOG_AS_LABEL "LASLTP"
|
521 |
|
|
#define LN_PROLOG_END_LABEL "LELTP"
|
522 |
|
|
#define DIE_LABEL_PREFIX "DW"
|
523 |
|
|
|
524 |
|
|
/* The DWARF 2 CFA column which tracks the return address. Normally this
|
525 |
|
|
is the column for PC, or the first column after all of the hard
|
526 |
|
|
registers. */
|
527 |
|
|
#ifndef DWARF_FRAME_RETURN_COLUMN
|
528 |
|
|
#ifdef PC_REGNUM
|
529 |
|
|
#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (PC_REGNUM)
|
530 |
|
|
#else
|
531 |
|
|
#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGISTERS
|
532 |
|
|
#endif
|
533 |
|
|
#endif
|
534 |
|
|
|
535 |
|
|
/* The mapping from gcc register number to DWARF 2 CFA column number. By
|
536 |
|
|
default, we just provide columns for all registers. */
|
537 |
|
|
#ifndef DWARF_FRAME_REGNUM
|
538 |
|
|
#define DWARF_FRAME_REGNUM(REG) DBX_REGISTER_NUMBER (REG)
|
539 |
|
|
#endif
|
540 |
|
|
|
541 |
|
|
/* Hook used by __throw. */
|
542 |
|
|
|
543 |
|
|
rtx
|
544 |
|
|
expand_builtin_dwarf_sp_column (void)
|
545 |
|
|
{
|
546 |
|
|
unsigned int dwarf_regnum = DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM);
|
547 |
|
|
return GEN_INT (DWARF2_FRAME_REG_OUT (dwarf_regnum, 1));
|
548 |
|
|
}
|
549 |
|
|
|
550 |
|
|
/* Return a pointer to a copy of the section string name S with all
|
551 |
|
|
attributes stripped off, and an asterisk prepended (for assemble_name). */
|
552 |
|
|
|
553 |
|
|
static inline char *
|
554 |
|
|
stripattributes (const char *s)
|
555 |
|
|
{
|
556 |
|
|
char *stripped = XNEWVEC (char, strlen (s) + 2);
|
557 |
|
|
char *p = stripped;
|
558 |
|
|
|
559 |
|
|
*p++ = '*';
|
560 |
|
|
|
561 |
|
|
while (*s && *s != ',')
|
562 |
|
|
*p++ = *s++;
|
563 |
|
|
|
564 |
|
|
*p = '\0';
|
565 |
|
|
return stripped;
|
566 |
|
|
}
|
567 |
|
|
|
568 |
|
|
/* MEM is a memory reference for the register size table, each element of
|
569 |
|
|
which has mode MODE. Initialize column C as a return address column. */
|
570 |
|
|
|
571 |
|
|
static void
|
572 |
|
|
init_return_column_size (enum machine_mode mode, rtx mem, unsigned int c)
|
573 |
|
|
{
|
574 |
|
|
HOST_WIDE_INT offset = c * GET_MODE_SIZE (mode);
|
575 |
|
|
HOST_WIDE_INT size = GET_MODE_SIZE (Pmode);
|
576 |
|
|
emit_move_insn (adjust_address (mem, mode, offset), GEN_INT (size));
|
577 |
|
|
}
|
578 |
|
|
|
579 |
|
|
/* Divide OFF by DWARF_CIE_DATA_ALIGNMENT, asserting no remainder. */
|
580 |
|
|
|
581 |
|
|
static inline HOST_WIDE_INT
|
582 |
|
|
div_data_align (HOST_WIDE_INT off)
|
583 |
|
|
{
|
584 |
|
|
HOST_WIDE_INT r = off / DWARF_CIE_DATA_ALIGNMENT;
|
585 |
|
|
gcc_assert (r * DWARF_CIE_DATA_ALIGNMENT == off);
|
586 |
|
|
return r;
|
587 |
|
|
}
|
588 |
|
|
|
589 |
|
|
/* Return true if we need a signed version of a given opcode
|
590 |
|
|
(e.g. DW_CFA_offset_extended_sf vs DW_CFA_offset_extended). */
|
591 |
|
|
|
592 |
|
|
static inline bool
|
593 |
|
|
need_data_align_sf_opcode (HOST_WIDE_INT off)
|
594 |
|
|
{
|
595 |
|
|
return DWARF_CIE_DATA_ALIGNMENT < 0 ? off > 0 : off < 0;
|
596 |
|
|
}
|
597 |
|
|
|
598 |
|
|
/* Generate code to initialize the register size table. */
|
599 |
|
|
|
600 |
|
|
void
|
601 |
|
|
expand_builtin_init_dwarf_reg_sizes (tree address)
|
602 |
|
|
{
|
603 |
|
|
unsigned int i;
|
604 |
|
|
enum machine_mode mode = TYPE_MODE (char_type_node);
|
605 |
|
|
rtx addr = expand_normal (address);
|
606 |
|
|
rtx mem = gen_rtx_MEM (BLKmode, addr);
|
607 |
|
|
bool wrote_return_column = false;
|
608 |
|
|
|
609 |
|
|
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
610 |
|
|
{
|
611 |
|
|
int rnum = DWARF2_FRAME_REG_OUT (DWARF_FRAME_REGNUM (i), 1);
|
612 |
|
|
|
613 |
|
|
if (rnum < DWARF_FRAME_REGISTERS)
|
614 |
|
|
{
|
615 |
|
|
HOST_WIDE_INT offset = rnum * GET_MODE_SIZE (mode);
|
616 |
|
|
enum machine_mode save_mode = reg_raw_mode[i];
|
617 |
|
|
HOST_WIDE_INT size;
|
618 |
|
|
|
619 |
|
|
if (HARD_REGNO_CALL_PART_CLOBBERED (i, save_mode))
|
620 |
|
|
save_mode = choose_hard_reg_mode (i, 1, true);
|
621 |
|
|
if (DWARF_FRAME_REGNUM (i) == DWARF_FRAME_RETURN_COLUMN)
|
622 |
|
|
{
|
623 |
|
|
if (save_mode == VOIDmode)
|
624 |
|
|
continue;
|
625 |
|
|
wrote_return_column = true;
|
626 |
|
|
}
|
627 |
|
|
size = GET_MODE_SIZE (save_mode);
|
628 |
|
|
if (offset < 0)
|
629 |
|
|
continue;
|
630 |
|
|
|
631 |
|
|
emit_move_insn (adjust_address (mem, mode, offset),
|
632 |
|
|
gen_int_mode (size, mode));
|
633 |
|
|
}
|
634 |
|
|
}
|
635 |
|
|
|
636 |
|
|
if (!wrote_return_column)
|
637 |
|
|
init_return_column_size (mode, mem, DWARF_FRAME_RETURN_COLUMN);
|
638 |
|
|
|
639 |
|
|
#ifdef DWARF_ALT_FRAME_RETURN_COLUMN
|
640 |
|
|
init_return_column_size (mode, mem, DWARF_ALT_FRAME_RETURN_COLUMN);
|
641 |
|
|
#endif
|
642 |
|
|
|
643 |
|
|
targetm.init_dwarf_reg_sizes_extra (address);
|
644 |
|
|
}
|
645 |
|
|
|
646 |
|
|
/* Convert a DWARF call frame info. operation to its string name */
|
647 |
|
|
|
648 |
|
|
static const char *
|
649 |
|
|
dwarf_cfi_name (unsigned int cfi_opc)
|
650 |
|
|
{
|
651 |
|
|
switch (cfi_opc)
|
652 |
|
|
{
|
653 |
|
|
case DW_CFA_advance_loc:
|
654 |
|
|
return "DW_CFA_advance_loc";
|
655 |
|
|
case DW_CFA_offset:
|
656 |
|
|
return "DW_CFA_offset";
|
657 |
|
|
case DW_CFA_restore:
|
658 |
|
|
return "DW_CFA_restore";
|
659 |
|
|
case DW_CFA_nop:
|
660 |
|
|
return "DW_CFA_nop";
|
661 |
|
|
case DW_CFA_set_loc:
|
662 |
|
|
return "DW_CFA_set_loc";
|
663 |
|
|
case DW_CFA_advance_loc1:
|
664 |
|
|
return "DW_CFA_advance_loc1";
|
665 |
|
|
case DW_CFA_advance_loc2:
|
666 |
|
|
return "DW_CFA_advance_loc2";
|
667 |
|
|
case DW_CFA_advance_loc4:
|
668 |
|
|
return "DW_CFA_advance_loc4";
|
669 |
|
|
case DW_CFA_offset_extended:
|
670 |
|
|
return "DW_CFA_offset_extended";
|
671 |
|
|
case DW_CFA_restore_extended:
|
672 |
|
|
return "DW_CFA_restore_extended";
|
673 |
|
|
case DW_CFA_undefined:
|
674 |
|
|
return "DW_CFA_undefined";
|
675 |
|
|
case DW_CFA_same_value:
|
676 |
|
|
return "DW_CFA_same_value";
|
677 |
|
|
case DW_CFA_register:
|
678 |
|
|
return "DW_CFA_register";
|
679 |
|
|
case DW_CFA_remember_state:
|
680 |
|
|
return "DW_CFA_remember_state";
|
681 |
|
|
case DW_CFA_restore_state:
|
682 |
|
|
return "DW_CFA_restore_state";
|
683 |
|
|
case DW_CFA_def_cfa:
|
684 |
|
|
return "DW_CFA_def_cfa";
|
685 |
|
|
case DW_CFA_def_cfa_register:
|
686 |
|
|
return "DW_CFA_def_cfa_register";
|
687 |
|
|
case DW_CFA_def_cfa_offset:
|
688 |
|
|
return "DW_CFA_def_cfa_offset";
|
689 |
|
|
|
690 |
|
|
/* DWARF 3 */
|
691 |
|
|
case DW_CFA_def_cfa_expression:
|
692 |
|
|
return "DW_CFA_def_cfa_expression";
|
693 |
|
|
case DW_CFA_expression:
|
694 |
|
|
return "DW_CFA_expression";
|
695 |
|
|
case DW_CFA_offset_extended_sf:
|
696 |
|
|
return "DW_CFA_offset_extended_sf";
|
697 |
|
|
case DW_CFA_def_cfa_sf:
|
698 |
|
|
return "DW_CFA_def_cfa_sf";
|
699 |
|
|
case DW_CFA_def_cfa_offset_sf:
|
700 |
|
|
return "DW_CFA_def_cfa_offset_sf";
|
701 |
|
|
|
702 |
|
|
/* SGI/MIPS specific */
|
703 |
|
|
case DW_CFA_MIPS_advance_loc8:
|
704 |
|
|
return "DW_CFA_MIPS_advance_loc8";
|
705 |
|
|
|
706 |
|
|
/* GNU extensions */
|
707 |
|
|
case DW_CFA_GNU_window_save:
|
708 |
|
|
return "DW_CFA_GNU_window_save";
|
709 |
|
|
case DW_CFA_GNU_args_size:
|
710 |
|
|
return "DW_CFA_GNU_args_size";
|
711 |
|
|
case DW_CFA_GNU_negative_offset_extended:
|
712 |
|
|
return "DW_CFA_GNU_negative_offset_extended";
|
713 |
|
|
|
714 |
|
|
default:
|
715 |
|
|
return "DW_CFA_<unknown>";
|
716 |
|
|
}
|
717 |
|
|
}
|
718 |
|
|
|
719 |
|
|
/* Return a pointer to a newly allocated Call Frame Instruction. */
|
720 |
|
|
|
721 |
|
|
static inline dw_cfi_ref
|
722 |
|
|
new_cfi (void)
|
723 |
|
|
{
|
724 |
|
|
dw_cfi_ref cfi = GGC_NEW (dw_cfi_node);
|
725 |
|
|
|
726 |
|
|
cfi->dw_cfi_next = NULL;
|
727 |
|
|
cfi->dw_cfi_oprnd1.dw_cfi_reg_num = 0;
|
728 |
|
|
cfi->dw_cfi_oprnd2.dw_cfi_reg_num = 0;
|
729 |
|
|
|
730 |
|
|
return cfi;
|
731 |
|
|
}
|
732 |
|
|
|
733 |
|
|
/* Add a Call Frame Instruction to list of instructions. */
|
734 |
|
|
|
735 |
|
|
static inline void
|
736 |
|
|
add_cfi (dw_cfi_ref *list_head, dw_cfi_ref cfi)
|
737 |
|
|
{
|
738 |
|
|
dw_cfi_ref *p;
|
739 |
|
|
dw_fde_ref fde = current_fde ();
|
740 |
|
|
|
741 |
|
|
/* When DRAP is used, CFA is defined with an expression. Redefine
|
742 |
|
|
CFA may lead to a different CFA value. */
|
743 |
|
|
/* ??? Of course, this heuristic fails when we're annotating epilogues,
|
744 |
|
|
because of course we'll always want to redefine the CFA back to the
|
745 |
|
|
stack pointer on the way out. Where should we move this check? */
|
746 |
|
|
if (0 && fde && fde->drap_reg != INVALID_REGNUM)
|
747 |
|
|
switch (cfi->dw_cfi_opc)
|
748 |
|
|
{
|
749 |
|
|
case DW_CFA_def_cfa_register:
|
750 |
|
|
case DW_CFA_def_cfa_offset:
|
751 |
|
|
case DW_CFA_def_cfa_offset_sf:
|
752 |
|
|
case DW_CFA_def_cfa:
|
753 |
|
|
case DW_CFA_def_cfa_sf:
|
754 |
|
|
gcc_unreachable ();
|
755 |
|
|
|
756 |
|
|
default:
|
757 |
|
|
break;
|
758 |
|
|
}
|
759 |
|
|
|
760 |
|
|
/* Find the end of the chain. */
|
761 |
|
|
for (p = list_head; (*p) != NULL; p = &(*p)->dw_cfi_next)
|
762 |
|
|
;
|
763 |
|
|
|
764 |
|
|
*p = cfi;
|
765 |
|
|
}
|
766 |
|
|
|
767 |
|
|
/* Generate a new label for the CFI info to refer to. FORCE is true
|
768 |
|
|
if a label needs to be output even when using .cfi_* directives. */
|
769 |
|
|
|
770 |
|
|
char *
|
771 |
|
|
dwarf2out_cfi_label (bool force)
|
772 |
|
|
{
|
773 |
|
|
static char label[20];
|
774 |
|
|
|
775 |
|
|
if (!force && dwarf2out_do_cfi_asm ())
|
776 |
|
|
{
|
777 |
|
|
/* In this case, we will be emitting the asm directive instead of
|
778 |
|
|
the label, so just return a placeholder to keep the rest of the
|
779 |
|
|
interfaces happy. */
|
780 |
|
|
strcpy (label, "<do not output>");
|
781 |
|
|
}
|
782 |
|
|
else
|
783 |
|
|
{
|
784 |
|
|
ASM_GENERATE_INTERNAL_LABEL (label, "LCFI", dwarf2out_cfi_label_num++);
|
785 |
|
|
ASM_OUTPUT_LABEL (asm_out_file, label);
|
786 |
|
|
}
|
787 |
|
|
|
788 |
|
|
return label;
|
789 |
|
|
}
|
790 |
|
|
|
791 |
|
|
/* True if remember_state should be emitted before following CFI directive. */
|
792 |
|
|
static bool emit_cfa_remember;
|
793 |
|
|
|
794 |
|
|
/* Add CFI to the current fde at the PC value indicated by LABEL if specified,
|
795 |
|
|
or to the CIE if LABEL is NULL. */
|
796 |
|
|
|
797 |
|
|
static void
|
798 |
|
|
add_fde_cfi (const char *label, dw_cfi_ref cfi)
|
799 |
|
|
{
|
800 |
|
|
dw_cfi_ref *list_head;
|
801 |
|
|
|
802 |
|
|
if (emit_cfa_remember)
|
803 |
|
|
{
|
804 |
|
|
dw_cfi_ref cfi_remember;
|
805 |
|
|
|
806 |
|
|
/* Emit the state save. */
|
807 |
|
|
emit_cfa_remember = false;
|
808 |
|
|
cfi_remember = new_cfi ();
|
809 |
|
|
cfi_remember->dw_cfi_opc = DW_CFA_remember_state;
|
810 |
|
|
add_fde_cfi (label, cfi_remember);
|
811 |
|
|
}
|
812 |
|
|
|
813 |
|
|
list_head = &cie_cfi_head;
|
814 |
|
|
|
815 |
|
|
if (dwarf2out_do_cfi_asm ())
|
816 |
|
|
{
|
817 |
|
|
if (label)
|
818 |
|
|
{
|
819 |
|
|
dw_fde_ref fde = current_fde ();
|
820 |
|
|
|
821 |
|
|
gcc_assert (fde != NULL);
|
822 |
|
|
|
823 |
|
|
/* We still have to add the cfi to the list so that lookup_cfa
|
824 |
|
|
works later on. When -g2 and above we even need to force
|
825 |
|
|
emitting of CFI labels and add to list a DW_CFA_set_loc for
|
826 |
|
|
convert_cfa_to_fb_loc_list purposes. If we're generating
|
827 |
|
|
DWARF3 output we use DW_OP_call_frame_cfa and so don't use
|
828 |
|
|
convert_cfa_to_fb_loc_list. */
|
829 |
|
|
if (dwarf_version == 2
|
830 |
|
|
&& debug_info_level > DINFO_LEVEL_TERSE
|
831 |
|
|
&& (write_symbols == DWARF2_DEBUG
|
832 |
|
|
|| write_symbols == VMS_AND_DWARF2_DEBUG))
|
833 |
|
|
{
|
834 |
|
|
switch (cfi->dw_cfi_opc)
|
835 |
|
|
{
|
836 |
|
|
case DW_CFA_def_cfa_offset:
|
837 |
|
|
case DW_CFA_def_cfa_offset_sf:
|
838 |
|
|
case DW_CFA_def_cfa_register:
|
839 |
|
|
case DW_CFA_def_cfa:
|
840 |
|
|
case DW_CFA_def_cfa_sf:
|
841 |
|
|
case DW_CFA_def_cfa_expression:
|
842 |
|
|
case DW_CFA_restore_state:
|
843 |
|
|
if (*label == 0 || strcmp (label, "<do not output>") == 0)
|
844 |
|
|
label = dwarf2out_cfi_label (true);
|
845 |
|
|
|
846 |
|
|
if (fde->dw_fde_current_label == NULL
|
847 |
|
|
|| strcmp (label, fde->dw_fde_current_label) != 0)
|
848 |
|
|
{
|
849 |
|
|
dw_cfi_ref xcfi;
|
850 |
|
|
|
851 |
|
|
label = xstrdup (label);
|
852 |
|
|
|
853 |
|
|
/* Set the location counter to the new label. */
|
854 |
|
|
xcfi = new_cfi ();
|
855 |
|
|
/* It doesn't metter whether DW_CFA_set_loc
|
856 |
|
|
or DW_CFA_advance_loc4 is added here, those aren't
|
857 |
|
|
emitted into assembly, only looked up by
|
858 |
|
|
convert_cfa_to_fb_loc_list. */
|
859 |
|
|
xcfi->dw_cfi_opc = DW_CFA_set_loc;
|
860 |
|
|
xcfi->dw_cfi_oprnd1.dw_cfi_addr = label;
|
861 |
|
|
add_cfi (&fde->dw_fde_cfi, xcfi);
|
862 |
|
|
fde->dw_fde_current_label = label;
|
863 |
|
|
}
|
864 |
|
|
break;
|
865 |
|
|
default:
|
866 |
|
|
break;
|
867 |
|
|
}
|
868 |
|
|
}
|
869 |
|
|
|
870 |
|
|
output_cfi_directive (cfi);
|
871 |
|
|
|
872 |
|
|
list_head = &fde->dw_fde_cfi;
|
873 |
|
|
}
|
874 |
|
|
/* ??? If this is a CFI for the CIE, we don't emit. This
|
875 |
|
|
assumes that the standard CIE contents that the assembler
|
876 |
|
|
uses matches the standard CIE contents that the compiler
|
877 |
|
|
uses. This is probably a bad assumption. I'm not quite
|
878 |
|
|
sure how to address this for now. */
|
879 |
|
|
}
|
880 |
|
|
else if (label)
|
881 |
|
|
{
|
882 |
|
|
dw_fde_ref fde = current_fde ();
|
883 |
|
|
|
884 |
|
|
gcc_assert (fde != NULL);
|
885 |
|
|
|
886 |
|
|
if (*label == 0)
|
887 |
|
|
label = dwarf2out_cfi_label (false);
|
888 |
|
|
|
889 |
|
|
if (fde->dw_fde_current_label == NULL
|
890 |
|
|
|| strcmp (label, fde->dw_fde_current_label) != 0)
|
891 |
|
|
{
|
892 |
|
|
dw_cfi_ref xcfi;
|
893 |
|
|
|
894 |
|
|
label = xstrdup (label);
|
895 |
|
|
|
896 |
|
|
/* Set the location counter to the new label. */
|
897 |
|
|
xcfi = new_cfi ();
|
898 |
|
|
/* If we have a current label, advance from there, otherwise
|
899 |
|
|
set the location directly using set_loc. */
|
900 |
|
|
xcfi->dw_cfi_opc = fde->dw_fde_current_label
|
901 |
|
|
? DW_CFA_advance_loc4
|
902 |
|
|
: DW_CFA_set_loc;
|
903 |
|
|
xcfi->dw_cfi_oprnd1.dw_cfi_addr = label;
|
904 |
|
|
add_cfi (&fde->dw_fde_cfi, xcfi);
|
905 |
|
|
|
906 |
|
|
fde->dw_fde_current_label = label;
|
907 |
|
|
}
|
908 |
|
|
|
909 |
|
|
list_head = &fde->dw_fde_cfi;
|
910 |
|
|
}
|
911 |
|
|
|
912 |
|
|
add_cfi (list_head, cfi);
|
913 |
|
|
}
|
914 |
|
|
|
915 |
|
|
/* Subroutine of lookup_cfa. */
|
916 |
|
|
|
917 |
|
|
static void
|
918 |
|
|
lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_location *loc, dw_cfa_location *remember)
|
919 |
|
|
{
|
920 |
|
|
switch (cfi->dw_cfi_opc)
|
921 |
|
|
{
|
922 |
|
|
case DW_CFA_def_cfa_offset:
|
923 |
|
|
case DW_CFA_def_cfa_offset_sf:
|
924 |
|
|
loc->offset = cfi->dw_cfi_oprnd1.dw_cfi_offset;
|
925 |
|
|
break;
|
926 |
|
|
case DW_CFA_def_cfa_register:
|
927 |
|
|
loc->reg = cfi->dw_cfi_oprnd1.dw_cfi_reg_num;
|
928 |
|
|
break;
|
929 |
|
|
case DW_CFA_def_cfa:
|
930 |
|
|
case DW_CFA_def_cfa_sf:
|
931 |
|
|
loc->reg = cfi->dw_cfi_oprnd1.dw_cfi_reg_num;
|
932 |
|
|
loc->offset = cfi->dw_cfi_oprnd2.dw_cfi_offset;
|
933 |
|
|
break;
|
934 |
|
|
case DW_CFA_def_cfa_expression:
|
935 |
|
|
get_cfa_from_loc_descr (loc, cfi->dw_cfi_oprnd1.dw_cfi_loc);
|
936 |
|
|
break;
|
937 |
|
|
|
938 |
|
|
case DW_CFA_remember_state:
|
939 |
|
|
gcc_assert (!remember->in_use);
|
940 |
|
|
*remember = *loc;
|
941 |
|
|
remember->in_use = 1;
|
942 |
|
|
break;
|
943 |
|
|
case DW_CFA_restore_state:
|
944 |
|
|
gcc_assert (remember->in_use);
|
945 |
|
|
*loc = *remember;
|
946 |
|
|
remember->in_use = 0;
|
947 |
|
|
break;
|
948 |
|
|
|
949 |
|
|
default:
|
950 |
|
|
break;
|
951 |
|
|
}
|
952 |
|
|
}
|
953 |
|
|
|
954 |
|
|
/* Find the previous value for the CFA. */
|
955 |
|
|
|
956 |
|
|
static void
|
957 |
|
|
lookup_cfa (dw_cfa_location *loc)
|
958 |
|
|
{
|
959 |
|
|
dw_cfi_ref cfi;
|
960 |
|
|
dw_fde_ref fde;
|
961 |
|
|
dw_cfa_location remember;
|
962 |
|
|
|
963 |
|
|
memset (loc, 0, sizeof (*loc));
|
964 |
|
|
loc->reg = INVALID_REGNUM;
|
965 |
|
|
remember = *loc;
|
966 |
|
|
|
967 |
|
|
for (cfi = cie_cfi_head; cfi; cfi = cfi->dw_cfi_next)
|
968 |
|
|
lookup_cfa_1 (cfi, loc, &remember);
|
969 |
|
|
|
970 |
|
|
fde = current_fde ();
|
971 |
|
|
if (fde)
|
972 |
|
|
for (cfi = fde->dw_fde_cfi; cfi; cfi = cfi->dw_cfi_next)
|
973 |
|
|
lookup_cfa_1 (cfi, loc, &remember);
|
974 |
|
|
}
|
975 |
|
|
|
976 |
|
|
/* The current rule for calculating the DWARF2 canonical frame address. */
|
977 |
|
|
static dw_cfa_location cfa;
|
978 |
|
|
|
979 |
|
|
/* The register used for saving registers to the stack, and its offset
|
980 |
|
|
from the CFA. */
|
981 |
|
|
static dw_cfa_location cfa_store;
|
982 |
|
|
|
983 |
|
|
/* The current save location around an epilogue. */
|
984 |
|
|
static dw_cfa_location cfa_remember;
|
985 |
|
|
|
986 |
|
|
/* The running total of the size of arguments pushed onto the stack. */
|
987 |
|
|
static HOST_WIDE_INT args_size;
|
988 |
|
|
|
989 |
|
|
/* The last args_size we actually output. */
|
990 |
|
|
static HOST_WIDE_INT old_args_size;
|
991 |
|
|
|
992 |
|
|
/* Entry point to update the canonical frame address (CFA).
|
993 |
|
|
LABEL is passed to add_fde_cfi. The value of CFA is now to be
|
994 |
|
|
calculated from REG+OFFSET. */
|
995 |
|
|
|
996 |
|
|
void
|
997 |
|
|
dwarf2out_def_cfa (const char *label, unsigned int reg, HOST_WIDE_INT offset)
|
998 |
|
|
{
|
999 |
|
|
dw_cfa_location loc;
|
1000 |
|
|
loc.indirect = 0;
|
1001 |
|
|
loc.base_offset = 0;
|
1002 |
|
|
loc.reg = reg;
|
1003 |
|
|
loc.offset = offset;
|
1004 |
|
|
def_cfa_1 (label, &loc);
|
1005 |
|
|
}
|
1006 |
|
|
|
1007 |
|
|
/* Determine if two dw_cfa_location structures define the same data. */
|
1008 |
|
|
|
1009 |
|
|
static bool
|
1010 |
|
|
cfa_equal_p (const dw_cfa_location *loc1, const dw_cfa_location *loc2)
|
1011 |
|
|
{
|
1012 |
|
|
return (loc1->reg == loc2->reg
|
1013 |
|
|
&& loc1->offset == loc2->offset
|
1014 |
|
|
&& loc1->indirect == loc2->indirect
|
1015 |
|
|
&& (loc1->indirect == 0
|
1016 |
|
|
|| loc1->base_offset == loc2->base_offset));
|
1017 |
|
|
}
|
1018 |
|
|
|
1019 |
|
|
/* This routine does the actual work. The CFA is now calculated from
|
1020 |
|
|
the dw_cfa_location structure. */
|
1021 |
|
|
|
1022 |
|
|
static void
|
1023 |
|
|
def_cfa_1 (const char *label, dw_cfa_location *loc_p)
|
1024 |
|
|
{
|
1025 |
|
|
dw_cfi_ref cfi;
|
1026 |
|
|
dw_cfa_location old_cfa, loc;
|
1027 |
|
|
|
1028 |
|
|
cfa = *loc_p;
|
1029 |
|
|
loc = *loc_p;
|
1030 |
|
|
|
1031 |
|
|
if (cfa_store.reg == loc.reg && loc.indirect == 0)
|
1032 |
|
|
cfa_store.offset = loc.offset;
|
1033 |
|
|
|
1034 |
|
|
loc.reg = DWARF_FRAME_REGNUM (loc.reg);
|
1035 |
|
|
lookup_cfa (&old_cfa);
|
1036 |
|
|
|
1037 |
|
|
/* If nothing changed, no need to issue any call frame instructions. */
|
1038 |
|
|
if (cfa_equal_p (&loc, &old_cfa))
|
1039 |
|
|
return;
|
1040 |
|
|
|
1041 |
|
|
cfi = new_cfi ();
|
1042 |
|
|
|
1043 |
|
|
if (loc.reg == old_cfa.reg && !loc.indirect && !old_cfa.indirect)
|
1044 |
|
|
{
|
1045 |
|
|
/* Construct a "DW_CFA_def_cfa_offset <offset>" instruction, indicating
|
1046 |
|
|
the CFA register did not change but the offset did. The data
|
1047 |
|
|
factoring for DW_CFA_def_cfa_offset_sf happens in output_cfi, or
|
1048 |
|
|
in the assembler via the .cfi_def_cfa_offset directive. */
|
1049 |
|
|
if (loc.offset < 0)
|
1050 |
|
|
cfi->dw_cfi_opc = DW_CFA_def_cfa_offset_sf;
|
1051 |
|
|
else
|
1052 |
|
|
cfi->dw_cfi_opc = DW_CFA_def_cfa_offset;
|
1053 |
|
|
cfi->dw_cfi_oprnd1.dw_cfi_offset = loc.offset;
|
1054 |
|
|
}
|
1055 |
|
|
|
1056 |
|
|
#ifndef MIPS_DEBUGGING_INFO /* SGI dbx thinks this means no offset. */
|
1057 |
|
|
else if (loc.offset == old_cfa.offset
|
1058 |
|
|
&& old_cfa.reg != INVALID_REGNUM
|
1059 |
|
|
&& !loc.indirect
|
1060 |
|
|
&& !old_cfa.indirect)
|
1061 |
|
|
{
|
1062 |
|
|
/* Construct a "DW_CFA_def_cfa_register <register>" instruction,
|
1063 |
|
|
indicating the CFA register has changed to <register> but the
|
1064 |
|
|
offset has not changed. */
|
1065 |
|
|
cfi->dw_cfi_opc = DW_CFA_def_cfa_register;
|
1066 |
|
|
cfi->dw_cfi_oprnd1.dw_cfi_reg_num = loc.reg;
|
1067 |
|
|
}
|
1068 |
|
|
#endif
|
1069 |
|
|
|
1070 |
|
|
else if (loc.indirect == 0)
|
1071 |
|
|
{
|
1072 |
|
|
/* Construct a "DW_CFA_def_cfa <register> <offset>" instruction,
|
1073 |
|
|
indicating the CFA register has changed to <register> with
|
1074 |
|
|
the specified offset. The data factoring for DW_CFA_def_cfa_sf
|
1075 |
|
|
happens in output_cfi, or in the assembler via the .cfi_def_cfa
|
1076 |
|
|
directive. */
|
1077 |
|
|
if (loc.offset < 0)
|
1078 |
|
|
cfi->dw_cfi_opc = DW_CFA_def_cfa_sf;
|
1079 |
|
|
else
|
1080 |
|
|
cfi->dw_cfi_opc = DW_CFA_def_cfa;
|
1081 |
|
|
cfi->dw_cfi_oprnd1.dw_cfi_reg_num = loc.reg;
|
1082 |
|
|
cfi->dw_cfi_oprnd2.dw_cfi_offset = loc.offset;
|
1083 |
|
|
}
|
1084 |
|
|
else
|
1085 |
|
|
{
|
1086 |
|
|
/* Construct a DW_CFA_def_cfa_expression instruction to
|
1087 |
|
|
calculate the CFA using a full location expression since no
|
1088 |
|
|
register-offset pair is available. */
|
1089 |
|
|
struct dw_loc_descr_struct *loc_list;
|
1090 |
|
|
|
1091 |
|
|
cfi->dw_cfi_opc = DW_CFA_def_cfa_expression;
|
1092 |
|
|
loc_list = build_cfa_loc (&loc, 0);
|
1093 |
|
|
cfi->dw_cfi_oprnd1.dw_cfi_loc = loc_list;
|
1094 |
|
|
}
|
1095 |
|
|
|
1096 |
|
|
add_fde_cfi (label, cfi);
|
1097 |
|
|
}
|
1098 |
|
|
|
1099 |
|
|
/* Add the CFI for saving a register. REG is the CFA column number.
|
1100 |
|
|
LABEL is passed to add_fde_cfi.
|
1101 |
|
|
If SREG is -1, the register is saved at OFFSET from the CFA;
|
1102 |
|
|
otherwise it is saved in SREG. */
|
1103 |
|
|
|
1104 |
|
|
static void
|
1105 |
|
|
reg_save (const char *label, unsigned int reg, unsigned int sreg, HOST_WIDE_INT offset)
|
1106 |
|
|
{
|
1107 |
|
|
dw_cfi_ref cfi = new_cfi ();
|
1108 |
|
|
dw_fde_ref fde = current_fde ();
|
1109 |
|
|
|
1110 |
|
|
cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
|
1111 |
|
|
|
1112 |
|
|
/* When stack is aligned, store REG using DW_CFA_expression with
|
1113 |
|
|
FP. */
|
1114 |
|
|
if (fde
|
1115 |
|
|
&& fde->stack_realign
|
1116 |
|
|
&& sreg == INVALID_REGNUM)
|
1117 |
|
|
{
|
1118 |
|
|
cfi->dw_cfi_opc = DW_CFA_expression;
|
1119 |
|
|
cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
|
1120 |
|
|
cfi->dw_cfi_oprnd2.dw_cfi_loc
|
1121 |
|
|
= build_cfa_aligned_loc (offset, fde->stack_realignment);
|
1122 |
|
|
}
|
1123 |
|
|
else if (sreg == INVALID_REGNUM)
|
1124 |
|
|
{
|
1125 |
|
|
if (need_data_align_sf_opcode (offset))
|
1126 |
|
|
cfi->dw_cfi_opc = DW_CFA_offset_extended_sf;
|
1127 |
|
|
else if (reg & ~0x3f)
|
1128 |
|
|
cfi->dw_cfi_opc = DW_CFA_offset_extended;
|
1129 |
|
|
else
|
1130 |
|
|
cfi->dw_cfi_opc = DW_CFA_offset;
|
1131 |
|
|
cfi->dw_cfi_oprnd2.dw_cfi_offset = offset;
|
1132 |
|
|
}
|
1133 |
|
|
else if (sreg == reg)
|
1134 |
|
|
cfi->dw_cfi_opc = DW_CFA_same_value;
|
1135 |
|
|
else
|
1136 |
|
|
{
|
1137 |
|
|
cfi->dw_cfi_opc = DW_CFA_register;
|
1138 |
|
|
cfi->dw_cfi_oprnd2.dw_cfi_reg_num = sreg;
|
1139 |
|
|
}
|
1140 |
|
|
|
1141 |
|
|
add_fde_cfi (label, cfi);
|
1142 |
|
|
}
|
1143 |
|
|
|
1144 |
|
|
/* Add the CFI for saving a register window. LABEL is passed to reg_save.
|
1145 |
|
|
This CFI tells the unwinder that it needs to restore the window registers
|
1146 |
|
|
from the previous frame's window save area.
|
1147 |
|
|
|
1148 |
|
|
??? Perhaps we should note in the CIE where windows are saved (instead of
|
1149 |
|
|
assuming 0(cfa)) and what registers are in the window. */
|
1150 |
|
|
|
1151 |
|
|
void
|
1152 |
|
|
dwarf2out_window_save (const char *label)
|
1153 |
|
|
{
|
1154 |
|
|
dw_cfi_ref cfi = new_cfi ();
|
1155 |
|
|
|
1156 |
|
|
cfi->dw_cfi_opc = DW_CFA_GNU_window_save;
|
1157 |
|
|
add_fde_cfi (label, cfi);
|
1158 |
|
|
}
|
1159 |
|
|
|
1160 |
|
|
/* Entry point for saving a register to the stack. REG is the GCC register
|
1161 |
|
|
number. LABEL and OFFSET are passed to reg_save. */
|
1162 |
|
|
|
1163 |
|
|
void
|
1164 |
|
|
dwarf2out_reg_save (const char *label, unsigned int reg, HOST_WIDE_INT offset)
|
1165 |
|
|
{
|
1166 |
|
|
reg_save (label, DWARF_FRAME_REGNUM (reg), INVALID_REGNUM, offset);
|
1167 |
|
|
}
|
1168 |
|
|
|
1169 |
|
|
/* Entry point for saving the return address in the stack.
|
1170 |
|
|
LABEL and OFFSET are passed to reg_save. */
|
1171 |
|
|
|
1172 |
|
|
void
|
1173 |
|
|
dwarf2out_return_save (const char *label, HOST_WIDE_INT offset)
|
1174 |
|
|
{
|
1175 |
|
|
reg_save (label, DWARF_FRAME_RETURN_COLUMN, INVALID_REGNUM, offset);
|
1176 |
|
|
}
|
1177 |
|
|
|
1178 |
|
|
/* Entry point for saving the return address in a register.
|
1179 |
|
|
LABEL and SREG are passed to reg_save. */
|
1180 |
|
|
|
1181 |
|
|
void
|
1182 |
|
|
dwarf2out_return_reg (const char *label, unsigned int sreg)
|
1183 |
|
|
{
|
1184 |
|
|
reg_save (label, DWARF_FRAME_RETURN_COLUMN, DWARF_FRAME_REGNUM (sreg), 0);
|
1185 |
|
|
}
|
1186 |
|
|
|
1187 |
|
|
#ifdef DWARF2_UNWIND_INFO
|
1188 |
|
|
/* Record the initial position of the return address. RTL is
|
1189 |
|
|
INCOMING_RETURN_ADDR_RTX. */
|
1190 |
|
|
|
1191 |
|
|
static void
|
1192 |
|
|
initial_return_save (rtx rtl)
|
1193 |
|
|
{
|
1194 |
|
|
unsigned int reg = INVALID_REGNUM;
|
1195 |
|
|
HOST_WIDE_INT offset = 0;
|
1196 |
|
|
|
1197 |
|
|
switch (GET_CODE (rtl))
|
1198 |
|
|
{
|
1199 |
|
|
case REG:
|
1200 |
|
|
/* RA is in a register. */
|
1201 |
|
|
reg = DWARF_FRAME_REGNUM (REGNO (rtl));
|
1202 |
|
|
break;
|
1203 |
|
|
|
1204 |
|
|
case MEM:
|
1205 |
|
|
/* RA is on the stack. */
|
1206 |
|
|
rtl = XEXP (rtl, 0);
|
1207 |
|
|
switch (GET_CODE (rtl))
|
1208 |
|
|
{
|
1209 |
|
|
case REG:
|
1210 |
|
|
gcc_assert (REGNO (rtl) == STACK_POINTER_REGNUM);
|
1211 |
|
|
offset = 0;
|
1212 |
|
|
break;
|
1213 |
|
|
|
1214 |
|
|
case PLUS:
|
1215 |
|
|
gcc_assert (REGNO (XEXP (rtl, 0)) == STACK_POINTER_REGNUM);
|
1216 |
|
|
offset = INTVAL (XEXP (rtl, 1));
|
1217 |
|
|
break;
|
1218 |
|
|
|
1219 |
|
|
case MINUS:
|
1220 |
|
|
gcc_assert (REGNO (XEXP (rtl, 0)) == STACK_POINTER_REGNUM);
|
1221 |
|
|
offset = -INTVAL (XEXP (rtl, 1));
|
1222 |
|
|
break;
|
1223 |
|
|
|
1224 |
|
|
default:
|
1225 |
|
|
gcc_unreachable ();
|
1226 |
|
|
}
|
1227 |
|
|
|
1228 |
|
|
break;
|
1229 |
|
|
|
1230 |
|
|
case PLUS:
|
1231 |
|
|
/* The return address is at some offset from any value we can
|
1232 |
|
|
actually load. For instance, on the SPARC it is in %i7+8. Just
|
1233 |
|
|
ignore the offset for now; it doesn't matter for unwinding frames. */
|
1234 |
|
|
gcc_assert (CONST_INT_P (XEXP (rtl, 1)));
|
1235 |
|
|
initial_return_save (XEXP (rtl, 0));
|
1236 |
|
|
return;
|
1237 |
|
|
|
1238 |
|
|
default:
|
1239 |
|
|
gcc_unreachable ();
|
1240 |
|
|
}
|
1241 |
|
|
|
1242 |
|
|
if (reg != DWARF_FRAME_RETURN_COLUMN)
|
1243 |
|
|
reg_save (NULL, DWARF_FRAME_RETURN_COLUMN, reg, offset - cfa.offset);
|
1244 |
|
|
}
|
1245 |
|
|
#endif
|
1246 |
|
|
|
1247 |
|
|
/* Given a SET, calculate the amount of stack adjustment it
|
1248 |
|
|
contains. */
|
1249 |
|
|
|
1250 |
|
|
static HOST_WIDE_INT
|
1251 |
|
|
stack_adjust_offset (const_rtx pattern, HOST_WIDE_INT cur_args_size,
|
1252 |
|
|
HOST_WIDE_INT cur_offset)
|
1253 |
|
|
{
|
1254 |
|
|
const_rtx src = SET_SRC (pattern);
|
1255 |
|
|
const_rtx dest = SET_DEST (pattern);
|
1256 |
|
|
HOST_WIDE_INT offset = 0;
|
1257 |
|
|
enum rtx_code code;
|
1258 |
|
|
|
1259 |
|
|
if (dest == stack_pointer_rtx)
|
1260 |
|
|
{
|
1261 |
|
|
code = GET_CODE (src);
|
1262 |
|
|
|
1263 |
|
|
/* Assume (set (reg sp) (reg whatever)) sets args_size
|
1264 |
|
|
level to 0. */
|
1265 |
|
|
if (code == REG && src != stack_pointer_rtx)
|
1266 |
|
|
{
|
1267 |
|
|
offset = -cur_args_size;
|
1268 |
|
|
#ifndef STACK_GROWS_DOWNWARD
|
1269 |
|
|
offset = -offset;
|
1270 |
|
|
#endif
|
1271 |
|
|
return offset - cur_offset;
|
1272 |
|
|
}
|
1273 |
|
|
|
1274 |
|
|
if (! (code == PLUS || code == MINUS)
|
1275 |
|
|
|| XEXP (src, 0) != stack_pointer_rtx
|
1276 |
|
|
|| !CONST_INT_P (XEXP (src, 1)))
|
1277 |
|
|
return 0;
|
1278 |
|
|
|
1279 |
|
|
/* (set (reg sp) (plus (reg sp) (const_int))) */
|
1280 |
|
|
offset = INTVAL (XEXP (src, 1));
|
1281 |
|
|
if (code == PLUS)
|
1282 |
|
|
offset = -offset;
|
1283 |
|
|
return offset;
|
1284 |
|
|
}
|
1285 |
|
|
|
1286 |
|
|
if (MEM_P (src) && !MEM_P (dest))
|
1287 |
|
|
dest = src;
|
1288 |
|
|
if (MEM_P (dest))
|
1289 |
|
|
{
|
1290 |
|
|
/* (set (mem (pre_dec (reg sp))) (foo)) */
|
1291 |
|
|
src = XEXP (dest, 0);
|
1292 |
|
|
code = GET_CODE (src);
|
1293 |
|
|
|
1294 |
|
|
switch (code)
|
1295 |
|
|
{
|
1296 |
|
|
case PRE_MODIFY:
|
1297 |
|
|
case POST_MODIFY:
|
1298 |
|
|
if (XEXP (src, 0) == stack_pointer_rtx)
|
1299 |
|
|
{
|
1300 |
|
|
rtx val = XEXP (XEXP (src, 1), 1);
|
1301 |
|
|
/* We handle only adjustments by constant amount. */
|
1302 |
|
|
gcc_assert (GET_CODE (XEXP (src, 1)) == PLUS
|
1303 |
|
|
&& CONST_INT_P (val));
|
1304 |
|
|
offset = -INTVAL (val);
|
1305 |
|
|
break;
|
1306 |
|
|
}
|
1307 |
|
|
return 0;
|
1308 |
|
|
|
1309 |
|
|
case PRE_DEC:
|
1310 |
|
|
case POST_DEC:
|
1311 |
|
|
if (XEXP (src, 0) == stack_pointer_rtx)
|
1312 |
|
|
{
|
1313 |
|
|
offset = GET_MODE_SIZE (GET_MODE (dest));
|
1314 |
|
|
break;
|
1315 |
|
|
}
|
1316 |
|
|
return 0;
|
1317 |
|
|
|
1318 |
|
|
case PRE_INC:
|
1319 |
|
|
case POST_INC:
|
1320 |
|
|
if (XEXP (src, 0) == stack_pointer_rtx)
|
1321 |
|
|
{
|
1322 |
|
|
offset = -GET_MODE_SIZE (GET_MODE (dest));
|
1323 |
|
|
break;
|
1324 |
|
|
}
|
1325 |
|
|
return 0;
|
1326 |
|
|
|
1327 |
|
|
default:
|
1328 |
|
|
return 0;
|
1329 |
|
|
}
|
1330 |
|
|
}
|
1331 |
|
|
else
|
1332 |
|
|
return 0;
|
1333 |
|
|
|
1334 |
|
|
return offset;
|
1335 |
|
|
}
|
1336 |
|
|
|
1337 |
|
|
/* Precomputed args_size for CODE_LABELs and BARRIERs preceeding them,
|
1338 |
|
|
indexed by INSN_UID. */
|
1339 |
|
|
|
1340 |
|
|
static HOST_WIDE_INT *barrier_args_size;
|
1341 |
|
|
|
1342 |
|
|
/* Helper function for compute_barrier_args_size. Handle one insn. */
|
1343 |
|
|
|
1344 |
|
|
static HOST_WIDE_INT
|
1345 |
|
|
compute_barrier_args_size_1 (rtx insn, HOST_WIDE_INT cur_args_size,
|
1346 |
|
|
VEC (rtx, heap) **next)
|
1347 |
|
|
{
|
1348 |
|
|
HOST_WIDE_INT offset = 0;
|
1349 |
|
|
int i;
|
1350 |
|
|
|
1351 |
|
|
if (! RTX_FRAME_RELATED_P (insn))
|
1352 |
|
|
{
|
1353 |
|
|
if (prologue_epilogue_contains (insn))
|
1354 |
|
|
/* Nothing */;
|
1355 |
|
|
else if (GET_CODE (PATTERN (insn)) == SET)
|
1356 |
|
|
offset = stack_adjust_offset (PATTERN (insn), cur_args_size, 0);
|
1357 |
|
|
else if (GET_CODE (PATTERN (insn)) == PARALLEL
|
1358 |
|
|
|| GET_CODE (PATTERN (insn)) == SEQUENCE)
|
1359 |
|
|
{
|
1360 |
|
|
/* There may be stack adjustments inside compound insns. Search
|
1361 |
|
|
for them. */
|
1362 |
|
|
for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
|
1363 |
|
|
if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET)
|
1364 |
|
|
offset += stack_adjust_offset (XVECEXP (PATTERN (insn), 0, i),
|
1365 |
|
|
cur_args_size, offset);
|
1366 |
|
|
}
|
1367 |
|
|
}
|
1368 |
|
|
else
|
1369 |
|
|
{
|
1370 |
|
|
rtx expr = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
|
1371 |
|
|
|
1372 |
|
|
if (expr)
|
1373 |
|
|
{
|
1374 |
|
|
expr = XEXP (expr, 0);
|
1375 |
|
|
if (GET_CODE (expr) == PARALLEL
|
1376 |
|
|
|| GET_CODE (expr) == SEQUENCE)
|
1377 |
|
|
for (i = 1; i < XVECLEN (expr, 0); i++)
|
1378 |
|
|
{
|
1379 |
|
|
rtx elem = XVECEXP (expr, 0, i);
|
1380 |
|
|
|
1381 |
|
|
if (GET_CODE (elem) == SET && !RTX_FRAME_RELATED_P (elem))
|
1382 |
|
|
offset += stack_adjust_offset (elem, cur_args_size, offset);
|
1383 |
|
|
}
|
1384 |
|
|
}
|
1385 |
|
|
}
|
1386 |
|
|
|
1387 |
|
|
#ifndef STACK_GROWS_DOWNWARD
|
1388 |
|
|
offset = -offset;
|
1389 |
|
|
#endif
|
1390 |
|
|
|
1391 |
|
|
cur_args_size += offset;
|
1392 |
|
|
if (cur_args_size < 0)
|
1393 |
|
|
cur_args_size = 0;
|
1394 |
|
|
|
1395 |
|
|
if (JUMP_P (insn))
|
1396 |
|
|
{
|
1397 |
|
|
rtx dest = JUMP_LABEL (insn);
|
1398 |
|
|
|
1399 |
|
|
if (dest)
|
1400 |
|
|
{
|
1401 |
|
|
if (barrier_args_size [INSN_UID (dest)] < 0)
|
1402 |
|
|
{
|
1403 |
|
|
barrier_args_size [INSN_UID (dest)] = cur_args_size;
|
1404 |
|
|
VEC_safe_push (rtx, heap, *next, dest);
|
1405 |
|
|
}
|
1406 |
|
|
}
|
1407 |
|
|
}
|
1408 |
|
|
|
1409 |
|
|
return cur_args_size;
|
1410 |
|
|
}
|
1411 |
|
|
|
1412 |
|
|
/* Walk the whole function and compute args_size on BARRIERs. */
|
1413 |
|
|
|
1414 |
|
|
static void
|
1415 |
|
|
compute_barrier_args_size (void)
|
1416 |
|
|
{
|
1417 |
|
|
int max_uid = get_max_uid (), i;
|
1418 |
|
|
rtx insn;
|
1419 |
|
|
VEC (rtx, heap) *worklist, *next, *tmp;
|
1420 |
|
|
|
1421 |
|
|
barrier_args_size = XNEWVEC (HOST_WIDE_INT, max_uid);
|
1422 |
|
|
for (i = 0; i < max_uid; i++)
|
1423 |
|
|
barrier_args_size[i] = -1;
|
1424 |
|
|
|
1425 |
|
|
worklist = VEC_alloc (rtx, heap, 20);
|
1426 |
|
|
next = VEC_alloc (rtx, heap, 20);
|
1427 |
|
|
insn = get_insns ();
|
1428 |
|
|
barrier_args_size[INSN_UID (insn)] = 0;
|
1429 |
|
|
VEC_quick_push (rtx, worklist, insn);
|
1430 |
|
|
for (;;)
|
1431 |
|
|
{
|
1432 |
|
|
while (!VEC_empty (rtx, worklist))
|
1433 |
|
|
{
|
1434 |
|
|
rtx prev, body, first_insn;
|
1435 |
|
|
HOST_WIDE_INT cur_args_size;
|
1436 |
|
|
|
1437 |
|
|
first_insn = insn = VEC_pop (rtx, worklist);
|
1438 |
|
|
cur_args_size = barrier_args_size[INSN_UID (insn)];
|
1439 |
|
|
prev = prev_nonnote_insn (insn);
|
1440 |
|
|
if (prev && BARRIER_P (prev))
|
1441 |
|
|
barrier_args_size[INSN_UID (prev)] = cur_args_size;
|
1442 |
|
|
|
1443 |
|
|
for (; insn; insn = NEXT_INSN (insn))
|
1444 |
|
|
{
|
1445 |
|
|
if (INSN_DELETED_P (insn) || NOTE_P (insn))
|
1446 |
|
|
continue;
|
1447 |
|
|
if (BARRIER_P (insn))
|
1448 |
|
|
break;
|
1449 |
|
|
|
1450 |
|
|
if (LABEL_P (insn))
|
1451 |
|
|
{
|
1452 |
|
|
if (insn == first_insn)
|
1453 |
|
|
continue;
|
1454 |
|
|
else if (barrier_args_size[INSN_UID (insn)] < 0)
|
1455 |
|
|
{
|
1456 |
|
|
barrier_args_size[INSN_UID (insn)] = cur_args_size;
|
1457 |
|
|
continue;
|
1458 |
|
|
}
|
1459 |
|
|
else
|
1460 |
|
|
{
|
1461 |
|
|
/* The insns starting with this label have been
|
1462 |
|
|
already scanned or are in the worklist. */
|
1463 |
|
|
break;
|
1464 |
|
|
}
|
1465 |
|
|
}
|
1466 |
|
|
|
1467 |
|
|
body = PATTERN (insn);
|
1468 |
|
|
if (GET_CODE (body) == SEQUENCE)
|
1469 |
|
|
{
|
1470 |
|
|
HOST_WIDE_INT dest_args_size = cur_args_size;
|
1471 |
|
|
for (i = 1; i < XVECLEN (body, 0); i++)
|
1472 |
|
|
if (INSN_ANNULLED_BRANCH_P (XVECEXP (body, 0, 0))
|
1473 |
|
|
&& INSN_FROM_TARGET_P (XVECEXP (body, 0, i)))
|
1474 |
|
|
dest_args_size
|
1475 |
|
|
= compute_barrier_args_size_1 (XVECEXP (body, 0, i),
|
1476 |
|
|
dest_args_size, &next);
|
1477 |
|
|
else
|
1478 |
|
|
cur_args_size
|
1479 |
|
|
= compute_barrier_args_size_1 (XVECEXP (body, 0, i),
|
1480 |
|
|
cur_args_size, &next);
|
1481 |
|
|
|
1482 |
|
|
if (INSN_ANNULLED_BRANCH_P (XVECEXP (body, 0, 0)))
|
1483 |
|
|
compute_barrier_args_size_1 (XVECEXP (body, 0, 0),
|
1484 |
|
|
dest_args_size, &next);
|
1485 |
|
|
else
|
1486 |
|
|
cur_args_size
|
1487 |
|
|
= compute_barrier_args_size_1 (XVECEXP (body, 0, 0),
|
1488 |
|
|
cur_args_size, &next);
|
1489 |
|
|
}
|
1490 |
|
|
else
|
1491 |
|
|
cur_args_size
|
1492 |
|
|
= compute_barrier_args_size_1 (insn, cur_args_size, &next);
|
1493 |
|
|
}
|
1494 |
|
|
}
|
1495 |
|
|
|
1496 |
|
|
if (VEC_empty (rtx, next))
|
1497 |
|
|
break;
|
1498 |
|
|
|
1499 |
|
|
/* Swap WORKLIST with NEXT and truncate NEXT for next iteration. */
|
1500 |
|
|
tmp = next;
|
1501 |
|
|
next = worklist;
|
1502 |
|
|
worklist = tmp;
|
1503 |
|
|
VEC_truncate (rtx, next, 0);
|
1504 |
|
|
}
|
1505 |
|
|
|
1506 |
|
|
VEC_free (rtx, heap, worklist);
|
1507 |
|
|
VEC_free (rtx, heap, next);
|
1508 |
|
|
}
|
1509 |
|
|
|
1510 |
|
|
/* Add a CFI to update the running total of the size of arguments
|
1511 |
|
|
pushed onto the stack. */
|
1512 |
|
|
|
1513 |
|
|
static void
|
1514 |
|
|
dwarf2out_args_size (const char *label, HOST_WIDE_INT size)
|
1515 |
|
|
{
|
1516 |
|
|
dw_cfi_ref cfi;
|
1517 |
|
|
|
1518 |
|
|
if (size == old_args_size)
|
1519 |
|
|
return;
|
1520 |
|
|
|
1521 |
|
|
old_args_size = size;
|
1522 |
|
|
|
1523 |
|
|
cfi = new_cfi ();
|
1524 |
|
|
cfi->dw_cfi_opc = DW_CFA_GNU_args_size;
|
1525 |
|
|
cfi->dw_cfi_oprnd1.dw_cfi_offset = size;
|
1526 |
|
|
add_fde_cfi (label, cfi);
|
1527 |
|
|
}
|
1528 |
|
|
|
1529 |
|
|
/* Record a stack adjustment of OFFSET bytes. */
|
1530 |
|
|
|
1531 |
|
|
static void
|
1532 |
|
|
dwarf2out_stack_adjust (HOST_WIDE_INT offset, const char *label)
|
1533 |
|
|
{
|
1534 |
|
|
if (cfa.reg == STACK_POINTER_REGNUM)
|
1535 |
|
|
cfa.offset += offset;
|
1536 |
|
|
|
1537 |
|
|
if (cfa_store.reg == STACK_POINTER_REGNUM)
|
1538 |
|
|
cfa_store.offset += offset;
|
1539 |
|
|
|
1540 |
|
|
if (ACCUMULATE_OUTGOING_ARGS)
|
1541 |
|
|
return;
|
1542 |
|
|
|
1543 |
|
|
#ifndef STACK_GROWS_DOWNWARD
|
1544 |
|
|
offset = -offset;
|
1545 |
|
|
#endif
|
1546 |
|
|
|
1547 |
|
|
args_size += offset;
|
1548 |
|
|
if (args_size < 0)
|
1549 |
|
|
args_size = 0;
|
1550 |
|
|
|
1551 |
|
|
def_cfa_1 (label, &cfa);
|
1552 |
|
|
if (flag_asynchronous_unwind_tables)
|
1553 |
|
|
dwarf2out_args_size (label, args_size);
|
1554 |
|
|
}
|
1555 |
|
|
|
1556 |
|
|
/* Check INSN to see if it looks like a push or a stack adjustment, and
|
1557 |
|
|
make a note of it if it does. EH uses this information to find out
|
1558 |
|
|
how much extra space it needs to pop off the stack. */
|
1559 |
|
|
|
1560 |
|
|
static void
|
1561 |
|
|
dwarf2out_notice_stack_adjust (rtx insn, bool after_p)
|
1562 |
|
|
{
|
1563 |
|
|
HOST_WIDE_INT offset;
|
1564 |
|
|
const char *label;
|
1565 |
|
|
int i;
|
1566 |
|
|
|
1567 |
|
|
/* Don't handle epilogues at all. Certainly it would be wrong to do so
|
1568 |
|
|
with this function. Proper support would require all frame-related
|
1569 |
|
|
insns to be marked, and to be able to handle saving state around
|
1570 |
|
|
epilogues textually in the middle of the function. */
|
1571 |
|
|
if (prologue_epilogue_contains (insn))
|
1572 |
|
|
return;
|
1573 |
|
|
|
1574 |
|
|
/* If INSN is an instruction from target of an annulled branch, the
|
1575 |
|
|
effects are for the target only and so current argument size
|
1576 |
|
|
shouldn't change at all. */
|
1577 |
|
|
if (final_sequence
|
1578 |
|
|
&& INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))
|
1579 |
|
|
&& INSN_FROM_TARGET_P (insn))
|
1580 |
|
|
return;
|
1581 |
|
|
|
1582 |
|
|
/* If only calls can throw, and we have a frame pointer,
|
1583 |
|
|
save up adjustments until we see the CALL_INSN. */
|
1584 |
|
|
if (!flag_asynchronous_unwind_tables && cfa.reg != STACK_POINTER_REGNUM)
|
1585 |
|
|
{
|
1586 |
|
|
if (CALL_P (insn) && !after_p)
|
1587 |
|
|
{
|
1588 |
|
|
/* Extract the size of the args from the CALL rtx itself. */
|
1589 |
|
|
insn = PATTERN (insn);
|
1590 |
|
|
if (GET_CODE (insn) == PARALLEL)
|
1591 |
|
|
insn = XVECEXP (insn, 0, 0);
|
1592 |
|
|
if (GET_CODE (insn) == SET)
|
1593 |
|
|
insn = SET_SRC (insn);
|
1594 |
|
|
gcc_assert (GET_CODE (insn) == CALL);
|
1595 |
|
|
dwarf2out_args_size ("", INTVAL (XEXP (insn, 1)));
|
1596 |
|
|
}
|
1597 |
|
|
return;
|
1598 |
|
|
}
|
1599 |
|
|
|
1600 |
|
|
if (CALL_P (insn) && !after_p)
|
1601 |
|
|
{
|
1602 |
|
|
if (!flag_asynchronous_unwind_tables)
|
1603 |
|
|
dwarf2out_args_size ("", args_size);
|
1604 |
|
|
return;
|
1605 |
|
|
}
|
1606 |
|
|
else if (BARRIER_P (insn))
|
1607 |
|
|
{
|
1608 |
|
|
/* Don't call compute_barrier_args_size () if the only
|
1609 |
|
|
BARRIER is at the end of function. */
|
1610 |
|
|
if (barrier_args_size == NULL && next_nonnote_insn (insn))
|
1611 |
|
|
compute_barrier_args_size ();
|
1612 |
|
|
if (barrier_args_size == NULL)
|
1613 |
|
|
offset = 0;
|
1614 |
|
|
else
|
1615 |
|
|
{
|
1616 |
|
|
offset = barrier_args_size[INSN_UID (insn)];
|
1617 |
|
|
if (offset < 0)
|
1618 |
|
|
offset = 0;
|
1619 |
|
|
}
|
1620 |
|
|
|
1621 |
|
|
offset -= args_size;
|
1622 |
|
|
#ifndef STACK_GROWS_DOWNWARD
|
1623 |
|
|
offset = -offset;
|
1624 |
|
|
#endif
|
1625 |
|
|
}
|
1626 |
|
|
else if (GET_CODE (PATTERN (insn)) == SET)
|
1627 |
|
|
offset = stack_adjust_offset (PATTERN (insn), args_size, 0);
|
1628 |
|
|
else if (GET_CODE (PATTERN (insn)) == PARALLEL
|
1629 |
|
|
|| GET_CODE (PATTERN (insn)) == SEQUENCE)
|
1630 |
|
|
{
|
1631 |
|
|
/* There may be stack adjustments inside compound insns. Search
|
1632 |
|
|
for them. */
|
1633 |
|
|
for (offset = 0, i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
|
1634 |
|
|
if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET)
|
1635 |
|
|
offset += stack_adjust_offset (XVECEXP (PATTERN (insn), 0, i),
|
1636 |
|
|
args_size, offset);
|
1637 |
|
|
}
|
1638 |
|
|
else
|
1639 |
|
|
return;
|
1640 |
|
|
|
1641 |
|
|
if (offset == 0)
|
1642 |
|
|
return;
|
1643 |
|
|
|
1644 |
|
|
label = dwarf2out_cfi_label (false);
|
1645 |
|
|
dwarf2out_stack_adjust (offset, label);
|
1646 |
|
|
}
|
1647 |
|
|
|
1648 |
|
|
#endif
|
1649 |
|
|
|
1650 |
|
|
/* We delay emitting a register save until either (a) we reach the end
|
1651 |
|
|
of the prologue or (b) the register is clobbered. This clusters
|
1652 |
|
|
register saves so that there are fewer pc advances. */
|
1653 |
|
|
|
1654 |
|
|
struct GTY(()) queued_reg_save {
|
1655 |
|
|
struct queued_reg_save *next;
|
1656 |
|
|
rtx reg;
|
1657 |
|
|
HOST_WIDE_INT cfa_offset;
|
1658 |
|
|
rtx saved_reg;
|
1659 |
|
|
};
|
1660 |
|
|
|
1661 |
|
|
static GTY(()) struct queued_reg_save *queued_reg_saves;
|
1662 |
|
|
|
1663 |
|
|
/* The caller's ORIG_REG is saved in SAVED_IN_REG. */
|
1664 |
|
|
struct GTY(()) reg_saved_in_data {
|
1665 |
|
|
rtx orig_reg;
|
1666 |
|
|
rtx saved_in_reg;
|
1667 |
|
|
};
|
1668 |
|
|
|
1669 |
|
|
/* A list of registers saved in other registers.
|
1670 |
|
|
The list intentionally has a small maximum capacity of 4; if your
|
1671 |
|
|
port needs more than that, you might consider implementing a
|
1672 |
|
|
more efficient data structure. */
|
1673 |
|
|
static GTY(()) struct reg_saved_in_data regs_saved_in_regs[4];
|
1674 |
|
|
static GTY(()) size_t num_regs_saved_in_regs;
|
1675 |
|
|
|
1676 |
|
|
#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
|
1677 |
|
|
static const char *last_reg_save_label;
|
1678 |
|
|
|
1679 |
|
|
/* Add an entry to QUEUED_REG_SAVES saying that REG is now saved at
|
1680 |
|
|
SREG, or if SREG is NULL then it is saved at OFFSET to the CFA. */
|
1681 |
|
|
|
1682 |
|
|
static void
|
1683 |
|
|
queue_reg_save (const char *label, rtx reg, rtx sreg, HOST_WIDE_INT offset)
|
1684 |
|
|
{
|
1685 |
|
|
struct queued_reg_save *q;
|
1686 |
|
|
|
1687 |
|
|
/* Duplicates waste space, but it's also necessary to remove them
|
1688 |
|
|
for correctness, since the queue gets output in reverse
|
1689 |
|
|
order. */
|
1690 |
|
|
for (q = queued_reg_saves; q != NULL; q = q->next)
|
1691 |
|
|
if (REGNO (q->reg) == REGNO (reg))
|
1692 |
|
|
break;
|
1693 |
|
|
|
1694 |
|
|
if (q == NULL)
|
1695 |
|
|
{
|
1696 |
|
|
q = GGC_NEW (struct queued_reg_save);
|
1697 |
|
|
q->next = queued_reg_saves;
|
1698 |
|
|
queued_reg_saves = q;
|
1699 |
|
|
}
|
1700 |
|
|
|
1701 |
|
|
q->reg = reg;
|
1702 |
|
|
q->cfa_offset = offset;
|
1703 |
|
|
q->saved_reg = sreg;
|
1704 |
|
|
|
1705 |
|
|
last_reg_save_label = label;
|
1706 |
|
|
}
|
1707 |
|
|
|
1708 |
|
|
/* Output all the entries in QUEUED_REG_SAVES. */
|
1709 |
|
|
|
1710 |
|
|
static void
|
1711 |
|
|
flush_queued_reg_saves (void)
|
1712 |
|
|
{
|
1713 |
|
|
struct queued_reg_save *q;
|
1714 |
|
|
|
1715 |
|
|
for (q = queued_reg_saves; q; q = q->next)
|
1716 |
|
|
{
|
1717 |
|
|
size_t i;
|
1718 |
|
|
unsigned int reg, sreg;
|
1719 |
|
|
|
1720 |
|
|
for (i = 0; i < num_regs_saved_in_regs; i++)
|
1721 |
|
|
if (REGNO (regs_saved_in_regs[i].orig_reg) == REGNO (q->reg))
|
1722 |
|
|
break;
|
1723 |
|
|
if (q->saved_reg && i == num_regs_saved_in_regs)
|
1724 |
|
|
{
|
1725 |
|
|
gcc_assert (i != ARRAY_SIZE (regs_saved_in_regs));
|
1726 |
|
|
num_regs_saved_in_regs++;
|
1727 |
|
|
}
|
1728 |
|
|
if (i != num_regs_saved_in_regs)
|
1729 |
|
|
{
|
1730 |
|
|
regs_saved_in_regs[i].orig_reg = q->reg;
|
1731 |
|
|
regs_saved_in_regs[i].saved_in_reg = q->saved_reg;
|
1732 |
|
|
}
|
1733 |
|
|
|
1734 |
|
|
reg = DWARF_FRAME_REGNUM (REGNO (q->reg));
|
1735 |
|
|
if (q->saved_reg)
|
1736 |
|
|
sreg = DWARF_FRAME_REGNUM (REGNO (q->saved_reg));
|
1737 |
|
|
else
|
1738 |
|
|
sreg = INVALID_REGNUM;
|
1739 |
|
|
reg_save (last_reg_save_label, reg, sreg, q->cfa_offset);
|
1740 |
|
|
}
|
1741 |
|
|
|
1742 |
|
|
queued_reg_saves = NULL;
|
1743 |
|
|
last_reg_save_label = NULL;
|
1744 |
|
|
}
|
1745 |
|
|
|
1746 |
|
|
/* Does INSN clobber any register which QUEUED_REG_SAVES lists a saved
|
1747 |
|
|
location for? Or, does it clobber a register which we've previously
|
1748 |
|
|
said that some other register is saved in, and for which we now
|
1749 |
|
|
have a new location for? */
|
1750 |
|
|
|
1751 |
|
|
static bool
|
1752 |
|
|
clobbers_queued_reg_save (const_rtx insn)
|
1753 |
|
|
{
|
1754 |
|
|
struct queued_reg_save *q;
|
1755 |
|
|
|
1756 |
|
|
for (q = queued_reg_saves; q; q = q->next)
|
1757 |
|
|
{
|
1758 |
|
|
size_t i;
|
1759 |
|
|
if (modified_in_p (q->reg, insn))
|
1760 |
|
|
return true;
|
1761 |
|
|
for (i = 0; i < num_regs_saved_in_regs; i++)
|
1762 |
|
|
if (REGNO (q->reg) == REGNO (regs_saved_in_regs[i].orig_reg)
|
1763 |
|
|
&& modified_in_p (regs_saved_in_regs[i].saved_in_reg, insn))
|
1764 |
|
|
return true;
|
1765 |
|
|
}
|
1766 |
|
|
|
1767 |
|
|
return false;
|
1768 |
|
|
}
|
1769 |
|
|
|
1770 |
|
|
/* Entry point for saving the first register into the second. */
|
1771 |
|
|
|
1772 |
|
|
void
|
1773 |
|
|
dwarf2out_reg_save_reg (const char *label, rtx reg, rtx sreg)
|
1774 |
|
|
{
|
1775 |
|
|
size_t i;
|
1776 |
|
|
unsigned int regno, sregno;
|
1777 |
|
|
|
1778 |
|
|
for (i = 0; i < num_regs_saved_in_regs; i++)
|
1779 |
|
|
if (REGNO (regs_saved_in_regs[i].orig_reg) == REGNO (reg))
|
1780 |
|
|
break;
|
1781 |
|
|
if (i == num_regs_saved_in_regs)
|
1782 |
|
|
{
|
1783 |
|
|
gcc_assert (i != ARRAY_SIZE (regs_saved_in_regs));
|
1784 |
|
|
num_regs_saved_in_regs++;
|
1785 |
|
|
}
|
1786 |
|
|
regs_saved_in_regs[i].orig_reg = reg;
|
1787 |
|
|
regs_saved_in_regs[i].saved_in_reg = sreg;
|
1788 |
|
|
|
1789 |
|
|
regno = DWARF_FRAME_REGNUM (REGNO (reg));
|
1790 |
|
|
sregno = DWARF_FRAME_REGNUM (REGNO (sreg));
|
1791 |
|
|
reg_save (label, regno, sregno, 0);
|
1792 |
|
|
}
|
1793 |
|
|
|
1794 |
|
|
/* What register, if any, is currently saved in REG? */
|
1795 |
|
|
|
1796 |
|
|
static rtx
|
1797 |
|
|
reg_saved_in (rtx reg)
|
1798 |
|
|
{
|
1799 |
|
|
unsigned int regn = REGNO (reg);
|
1800 |
|
|
size_t i;
|
1801 |
|
|
struct queued_reg_save *q;
|
1802 |
|
|
|
1803 |
|
|
for (q = queued_reg_saves; q; q = q->next)
|
1804 |
|
|
if (q->saved_reg && regn == REGNO (q->saved_reg))
|
1805 |
|
|
return q->reg;
|
1806 |
|
|
|
1807 |
|
|
for (i = 0; i < num_regs_saved_in_regs; i++)
|
1808 |
|
|
if (regs_saved_in_regs[i].saved_in_reg
|
1809 |
|
|
&& regn == REGNO (regs_saved_in_regs[i].saved_in_reg))
|
1810 |
|
|
return regs_saved_in_regs[i].orig_reg;
|
1811 |
|
|
|
1812 |
|
|
return NULL_RTX;
|
1813 |
|
|
}
|
1814 |
|
|
|
1815 |
|
|
|
1816 |
|
|
/* A temporary register holding an integral value used in adjusting SP
|
1817 |
|
|
or setting up the store_reg. The "offset" field holds the integer
|
1818 |
|
|
value, not an offset. */
|
1819 |
|
|
static dw_cfa_location cfa_temp;
|
1820 |
|
|
|
1821 |
|
|
/* A subroutine of dwarf2out_frame_debug, process a REG_DEF_CFA note. */
|
1822 |
|
|
|
1823 |
|
|
static void
|
1824 |
|
|
dwarf2out_frame_debug_def_cfa (rtx pat, const char *label)
|
1825 |
|
|
{
|
1826 |
|
|
memset (&cfa, 0, sizeof (cfa));
|
1827 |
|
|
|
1828 |
|
|
switch (GET_CODE (pat))
|
1829 |
|
|
{
|
1830 |
|
|
case PLUS:
|
1831 |
|
|
cfa.reg = REGNO (XEXP (pat, 0));
|
1832 |
|
|
cfa.offset = INTVAL (XEXP (pat, 1));
|
1833 |
|
|
break;
|
1834 |
|
|
|
1835 |
|
|
case REG:
|
1836 |
|
|
cfa.reg = REGNO (pat);
|
1837 |
|
|
break;
|
1838 |
|
|
|
1839 |
|
|
default:
|
1840 |
|
|
/* Recurse and define an expression. */
|
1841 |
|
|
gcc_unreachable ();
|
1842 |
|
|
}
|
1843 |
|
|
|
1844 |
|
|
def_cfa_1 (label, &cfa);
|
1845 |
|
|
}
|
1846 |
|
|
|
1847 |
|
|
/* A subroutine of dwarf2out_frame_debug, process a REG_ADJUST_CFA note. */
|
1848 |
|
|
|
1849 |
|
|
static void
|
1850 |
|
|
dwarf2out_frame_debug_adjust_cfa (rtx pat, const char *label)
|
1851 |
|
|
{
|
1852 |
|
|
rtx src, dest;
|
1853 |
|
|
|
1854 |
|
|
gcc_assert (GET_CODE (pat) == SET);
|
1855 |
|
|
dest = XEXP (pat, 0);
|
1856 |
|
|
src = XEXP (pat, 1);
|
1857 |
|
|
|
1858 |
|
|
switch (GET_CODE (src))
|
1859 |
|
|
{
|
1860 |
|
|
case PLUS:
|
1861 |
|
|
gcc_assert (REGNO (XEXP (src, 0)) == cfa.reg);
|
1862 |
|
|
cfa.offset -= INTVAL (XEXP (src, 1));
|
1863 |
|
|
break;
|
1864 |
|
|
|
1865 |
|
|
case REG:
|
1866 |
|
|
break;
|
1867 |
|
|
|
1868 |
|
|
default:
|
1869 |
|
|
gcc_unreachable ();
|
1870 |
|
|
}
|
1871 |
|
|
|
1872 |
|
|
cfa.reg = REGNO (dest);
|
1873 |
|
|
gcc_assert (cfa.indirect == 0);
|
1874 |
|
|
|
1875 |
|
|
def_cfa_1 (label, &cfa);
|
1876 |
|
|
}
|
1877 |
|
|
|
1878 |
|
|
/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_OFFSET note. */
|
1879 |
|
|
|
1880 |
|
|
static void
|
1881 |
|
|
dwarf2out_frame_debug_cfa_offset (rtx set, const char *label)
|
1882 |
|
|
{
|
1883 |
|
|
HOST_WIDE_INT offset;
|
1884 |
|
|
rtx src, addr, span;
|
1885 |
|
|
|
1886 |
|
|
src = XEXP (set, 1);
|
1887 |
|
|
addr = XEXP (set, 0);
|
1888 |
|
|
gcc_assert (MEM_P (addr));
|
1889 |
|
|
addr = XEXP (addr, 0);
|
1890 |
|
|
|
1891 |
|
|
/* As documented, only consider extremely simple addresses. */
|
1892 |
|
|
switch (GET_CODE (addr))
|
1893 |
|
|
{
|
1894 |
|
|
case REG:
|
1895 |
|
|
gcc_assert (REGNO (addr) == cfa.reg);
|
1896 |
|
|
offset = -cfa.offset;
|
1897 |
|
|
break;
|
1898 |
|
|
case PLUS:
|
1899 |
|
|
gcc_assert (REGNO (XEXP (addr, 0)) == cfa.reg);
|
1900 |
|
|
offset = INTVAL (XEXP (addr, 1)) - cfa.offset;
|
1901 |
|
|
break;
|
1902 |
|
|
default:
|
1903 |
|
|
gcc_unreachable ();
|
1904 |
|
|
}
|
1905 |
|
|
|
1906 |
|
|
span = targetm.dwarf_register_span (src);
|
1907 |
|
|
|
1908 |
|
|
/* ??? We'd like to use queue_reg_save, but we need to come up with
|
1909 |
|
|
a different flushing heuristic for epilogues. */
|
1910 |
|
|
if (!span)
|
1911 |
|
|
reg_save (label, DWARF_FRAME_REGNUM (REGNO (src)), INVALID_REGNUM, offset);
|
1912 |
|
|
else
|
1913 |
|
|
{
|
1914 |
|
|
/* We have a PARALLEL describing where the contents of SRC live.
|
1915 |
|
|
Queue register saves for each piece of the PARALLEL. */
|
1916 |
|
|
int par_index;
|
1917 |
|
|
int limit;
|
1918 |
|
|
HOST_WIDE_INT span_offset = offset;
|
1919 |
|
|
|
1920 |
|
|
gcc_assert (GET_CODE (span) == PARALLEL);
|
1921 |
|
|
|
1922 |
|
|
limit = XVECLEN (span, 0);
|
1923 |
|
|
for (par_index = 0; par_index < limit; par_index++)
|
1924 |
|
|
{
|
1925 |
|
|
rtx elem = XVECEXP (span, 0, par_index);
|
1926 |
|
|
|
1927 |
|
|
reg_save (label, DWARF_FRAME_REGNUM (REGNO (elem)),
|
1928 |
|
|
INVALID_REGNUM, span_offset);
|
1929 |
|
|
span_offset += GET_MODE_SIZE (GET_MODE (elem));
|
1930 |
|
|
}
|
1931 |
|
|
}
|
1932 |
|
|
}
|
1933 |
|
|
|
1934 |
|
|
/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_REGISTER note. */
|
1935 |
|
|
|
1936 |
|
|
static void
|
1937 |
|
|
dwarf2out_frame_debug_cfa_register (rtx set, const char *label)
|
1938 |
|
|
{
|
1939 |
|
|
rtx src, dest;
|
1940 |
|
|
unsigned sregno, dregno;
|
1941 |
|
|
|
1942 |
|
|
src = XEXP (set, 1);
|
1943 |
|
|
dest = XEXP (set, 0);
|
1944 |
|
|
|
1945 |
|
|
if (src == pc_rtx)
|
1946 |
|
|
sregno = DWARF_FRAME_RETURN_COLUMN;
|
1947 |
|
|
else
|
1948 |
|
|
sregno = DWARF_FRAME_REGNUM (REGNO (src));
|
1949 |
|
|
|
1950 |
|
|
dregno = DWARF_FRAME_REGNUM (REGNO (dest));
|
1951 |
|
|
|
1952 |
|
|
/* ??? We'd like to use queue_reg_save, but we need to come up with
|
1953 |
|
|
a different flushing heuristic for epilogues. */
|
1954 |
|
|
reg_save (label, sregno, dregno, 0);
|
1955 |
|
|
}
|
1956 |
|
|
|
1957 |
|
|
/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_RESTORE note. */
|
1958 |
|
|
|
1959 |
|
|
static void
|
1960 |
|
|
dwarf2out_frame_debug_cfa_restore (rtx reg, const char *label)
|
1961 |
|
|
{
|
1962 |
|
|
dw_cfi_ref cfi = new_cfi ();
|
1963 |
|
|
unsigned int regno = DWARF_FRAME_REGNUM (REGNO (reg));
|
1964 |
|
|
|
1965 |
|
|
cfi->dw_cfi_opc = (regno & ~0x3f ? DW_CFA_restore_extended : DW_CFA_restore);
|
1966 |
|
|
cfi->dw_cfi_oprnd1.dw_cfi_reg_num = regno;
|
1967 |
|
|
|
1968 |
|
|
add_fde_cfi (label, cfi);
|
1969 |
|
|
}
|
1970 |
|
|
|
1971 |
|
|
/* Record call frame debugging information for an expression EXPR,
|
1972 |
|
|
which either sets SP or FP (adjusting how we calculate the frame
|
1973 |
|
|
address) or saves a register to the stack or another register.
|
1974 |
|
|
LABEL indicates the address of EXPR.
|
1975 |
|
|
|
1976 |
|
|
This function encodes a state machine mapping rtxes to actions on
|
1977 |
|
|
cfa, cfa_store, and cfa_temp.reg. We describe these rules so
|
1978 |
|
|
users need not read the source code.
|
1979 |
|
|
|
1980 |
|
|
The High-Level Picture
|
1981 |
|
|
|
1982 |
|
|
Changes in the register we use to calculate the CFA: Currently we
|
1983 |
|
|
assume that if you copy the CFA register into another register, we
|
1984 |
|
|
should take the other one as the new CFA register; this seems to
|
1985 |
|
|
work pretty well. If it's wrong for some target, it's simple
|
1986 |
|
|
enough not to set RTX_FRAME_RELATED_P on the insn in question.
|
1987 |
|
|
|
1988 |
|
|
Changes in the register we use for saving registers to the stack:
|
1989 |
|
|
This is usually SP, but not always. Again, we deduce that if you
|
1990 |
|
|
copy SP into another register (and SP is not the CFA register),
|
1991 |
|
|
then the new register is the one we will be using for register
|
1992 |
|
|
saves. This also seems to work.
|
1993 |
|
|
|
1994 |
|
|
Register saves: There's not much guesswork about this one; if
|
1995 |
|
|
RTX_FRAME_RELATED_P is set on an insn which modifies memory, it's a
|
1996 |
|
|
register save, and the register used to calculate the destination
|
1997 |
|
|
had better be the one we think we're using for this purpose.
|
1998 |
|
|
It's also assumed that a copy from a call-saved register to another
|
1999 |
|
|
register is saving that register if RTX_FRAME_RELATED_P is set on
|
2000 |
|
|
that instruction. If the copy is from a call-saved register to
|
2001 |
|
|
the *same* register, that means that the register is now the same
|
2002 |
|
|
value as in the caller.
|
2003 |
|
|
|
2004 |
|
|
Except: If the register being saved is the CFA register, and the
|
2005 |
|
|
offset is nonzero, we are saving the CFA, so we assume we have to
|
2006 |
|
|
use DW_CFA_def_cfa_expression. If the offset is 0, we assume that
|
2007 |
|
|
the intent is to save the value of SP from the previous frame.
|
2008 |
|
|
|
2009 |
|
|
In addition, if a register has previously been saved to a different
|
2010 |
|
|
register,
|
2011 |
|
|
|
2012 |
|
|
Invariants / Summaries of Rules
|
2013 |
|
|
|
2014 |
|
|
cfa current rule for calculating the CFA. It usually
|
2015 |
|
|
consists of a register and an offset.
|
2016 |
|
|
cfa_store register used by prologue code to save things to the stack
|
2017 |
|
|
cfa_store.offset is the offset from the value of
|
2018 |
|
|
cfa_store.reg to the actual CFA
|
2019 |
|
|
cfa_temp register holding an integral value. cfa_temp.offset
|
2020 |
|
|
stores the value, which will be used to adjust the
|
2021 |
|
|
stack pointer. cfa_temp is also used like cfa_store,
|
2022 |
|
|
to track stores to the stack via fp or a temp reg.
|
2023 |
|
|
|
2024 |
|
|
Rules 1- 4: Setting a register's value to cfa.reg or an expression
|
2025 |
|
|
with cfa.reg as the first operand changes the cfa.reg and its
|
2026 |
|
|
cfa.offset. Rule 1 and 4 also set cfa_temp.reg and
|
2027 |
|
|
cfa_temp.offset.
|
2028 |
|
|
|
2029 |
|
|
Rules 6- 9: Set a non-cfa.reg register value to a constant or an
|
2030 |
|
|
expression yielding a constant. This sets cfa_temp.reg
|
2031 |
|
|
and cfa_temp.offset.
|
2032 |
|
|
|
2033 |
|
|
Rule 5: Create a new register cfa_store used to save items to the
|
2034 |
|
|
stack.
|
2035 |
|
|
|
2036 |
|
|
Rules 10-14: Save a register to the stack. Define offset as the
|
2037 |
|
|
difference of the original location and cfa_store's
|
2038 |
|
|
location (or cfa_temp's location if cfa_temp is used).
|
2039 |
|
|
|
2040 |
|
|
Rules 16-20: If AND operation happens on sp in prologue, we assume
|
2041 |
|
|
stack is realigned. We will use a group of DW_OP_XXX
|
2042 |
|
|
expressions to represent the location of the stored
|
2043 |
|
|
register instead of CFA+offset.
|
2044 |
|
|
|
2045 |
|
|
The Rules
|
2046 |
|
|
|
2047 |
|
|
"{a,b}" indicates a choice of a xor b.
|
2048 |
|
|
"<reg>:cfa.reg" indicates that <reg> must equal cfa.reg.
|
2049 |
|
|
|
2050 |
|
|
Rule 1:
|
2051 |
|
|
(set <reg1> <reg2>:cfa.reg)
|
2052 |
|
|
effects: cfa.reg = <reg1>
|
2053 |
|
|
cfa.offset unchanged
|
2054 |
|
|
cfa_temp.reg = <reg1>
|
2055 |
|
|
cfa_temp.offset = cfa.offset
|
2056 |
|
|
|
2057 |
|
|
Rule 2:
|
2058 |
|
|
(set sp ({minus,plus,losum} {sp,fp}:cfa.reg
|
2059 |
|
|
{<const_int>,<reg>:cfa_temp.reg}))
|
2060 |
|
|
effects: cfa.reg = sp if fp used
|
2061 |
|
|
cfa.offset += {+/- <const_int>, cfa_temp.offset} if cfa.reg==sp
|
2062 |
|
|
cfa_store.offset += {+/- <const_int>, cfa_temp.offset}
|
2063 |
|
|
if cfa_store.reg==sp
|
2064 |
|
|
|
2065 |
|
|
Rule 3:
|
2066 |
|
|
(set fp ({minus,plus,losum} <reg>:cfa.reg <const_int>))
|
2067 |
|
|
effects: cfa.reg = fp
|
2068 |
|
|
cfa_offset += +/- <const_int>
|
2069 |
|
|
|
2070 |
|
|
Rule 4:
|
2071 |
|
|
(set <reg1> ({plus,losum} <reg2>:cfa.reg <const_int>))
|
2072 |
|
|
constraints: <reg1> != fp
|
2073 |
|
|
<reg1> != sp
|
2074 |
|
|
effects: cfa.reg = <reg1>
|
2075 |
|
|
cfa_temp.reg = <reg1>
|
2076 |
|
|
cfa_temp.offset = cfa.offset
|
2077 |
|
|
|
2078 |
|
|
Rule 5:
|
2079 |
|
|
(set <reg1> (plus <reg2>:cfa_temp.reg sp:cfa.reg))
|
2080 |
|
|
constraints: <reg1> != fp
|
2081 |
|
|
<reg1> != sp
|
2082 |
|
|
effects: cfa_store.reg = <reg1>
|
2083 |
|
|
cfa_store.offset = cfa.offset - cfa_temp.offset
|
2084 |
|
|
|
2085 |
|
|
Rule 6:
|
2086 |
|
|
(set <reg> <const_int>)
|
2087 |
|
|
effects: cfa_temp.reg = <reg>
|
2088 |
|
|
cfa_temp.offset = <const_int>
|
2089 |
|
|
|
2090 |
|
|
Rule 7:
|
2091 |
|
|
(set <reg1>:cfa_temp.reg (ior <reg2>:cfa_temp.reg <const_int>))
|
2092 |
|
|
effects: cfa_temp.reg = <reg1>
|
2093 |
|
|
cfa_temp.offset |= <const_int>
|
2094 |
|
|
|
2095 |
|
|
Rule 8:
|
2096 |
|
|
(set <reg> (high <exp>))
|
2097 |
|
|
effects: none
|
2098 |
|
|
|
2099 |
|
|
Rule 9:
|
2100 |
|
|
(set <reg> (lo_sum <exp> <const_int>))
|
2101 |
|
|
effects: cfa_temp.reg = <reg>
|
2102 |
|
|
cfa_temp.offset = <const_int>
|
2103 |
|
|
|
2104 |
|
|
Rule 10:
|
2105 |
|
|
(set (mem (pre_modify sp:cfa_store (???? <reg1> <const_int>))) <reg2>)
|
2106 |
|
|
effects: cfa_store.offset -= <const_int>
|
2107 |
|
|
cfa.offset = cfa_store.offset if cfa.reg == sp
|
2108 |
|
|
cfa.reg = sp
|
2109 |
|
|
cfa.base_offset = -cfa_store.offset
|
2110 |
|
|
|
2111 |
|
|
Rule 11:
|
2112 |
|
|
(set (mem ({pre_inc,pre_dec} sp:cfa_store.reg)) <reg>)
|
2113 |
|
|
effects: cfa_store.offset += -/+ mode_size(mem)
|
2114 |
|
|
cfa.offset = cfa_store.offset if cfa.reg == sp
|
2115 |
|
|
cfa.reg = sp
|
2116 |
|
|
cfa.base_offset = -cfa_store.offset
|
2117 |
|
|
|
2118 |
|
|
Rule 12:
|
2119 |
|
|
(set (mem ({minus,plus,losum} <reg1>:{cfa_store,cfa_temp} <const_int>))
|
2120 |
|
|
|
2121 |
|
|
<reg2>)
|
2122 |
|
|
effects: cfa.reg = <reg1>
|
2123 |
|
|
cfa.base_offset = -/+ <const_int> - {cfa_store,cfa_temp}.offset
|
2124 |
|
|
|
2125 |
|
|
Rule 13:
|
2126 |
|
|
(set (mem <reg1>:{cfa_store,cfa_temp}) <reg2>)
|
2127 |
|
|
effects: cfa.reg = <reg1>
|
2128 |
|
|
cfa.base_offset = -{cfa_store,cfa_temp}.offset
|
2129 |
|
|
|
2130 |
|
|
Rule 14:
|
2131 |
|
|
(set (mem (postinc <reg1>:cfa_temp <const_int>)) <reg2>)
|
2132 |
|
|
effects: cfa.reg = <reg1>
|
2133 |
|
|
cfa.base_offset = -cfa_temp.offset
|
2134 |
|
|
cfa_temp.offset -= mode_size(mem)
|
2135 |
|
|
|
2136 |
|
|
Rule 15:
|
2137 |
|
|
(set <reg> {unspec, unspec_volatile})
|
2138 |
|
|
effects: target-dependent
|
2139 |
|
|
|
2140 |
|
|
Rule 16:
|
2141 |
|
|
(set sp (and: sp <const_int>))
|
2142 |
|
|
constraints: cfa_store.reg == sp
|
2143 |
|
|
effects: current_fde.stack_realign = 1
|
2144 |
|
|
cfa_store.offset = 0
|
2145 |
|
|
fde->drap_reg = cfa.reg if cfa.reg != sp and cfa.reg != fp
|
2146 |
|
|
|
2147 |
|
|
Rule 17:
|
2148 |
|
|
(set (mem ({pre_inc, pre_dec} sp)) (mem (plus (cfa.reg) (const_int))))
|
2149 |
|
|
effects: cfa_store.offset += -/+ mode_size(mem)
|
2150 |
|
|
|
2151 |
|
|
Rule 18:
|
2152 |
|
|
(set (mem ({pre_inc, pre_dec} sp)) fp)
|
2153 |
|
|
constraints: fde->stack_realign == 1
|
2154 |
|
|
effects: cfa_store.offset = 0
|
2155 |
|
|
cfa.reg != HARD_FRAME_POINTER_REGNUM
|
2156 |
|
|
|
2157 |
|
|
Rule 19:
|
2158 |
|
|
(set (mem ({pre_inc, pre_dec} sp)) cfa.reg)
|
2159 |
|
|
constraints: fde->stack_realign == 1
|
2160 |
|
|
&& cfa.offset == 0
|
2161 |
|
|
&& cfa.indirect == 0
|
2162 |
|
|
&& cfa.reg != HARD_FRAME_POINTER_REGNUM
|
2163 |
|
|
effects: Use DW_CFA_def_cfa_expression to define cfa
|
2164 |
|
|
cfa.reg == fde->drap_reg */
|
2165 |
|
|
|
2166 |
|
|
static void
|
2167 |
|
|
dwarf2out_frame_debug_expr (rtx expr, const char *label)
|
2168 |
|
|
{
|
2169 |
|
|
rtx src, dest, span;
|
2170 |
|
|
HOST_WIDE_INT offset;
|
2171 |
|
|
dw_fde_ref fde;
|
2172 |
|
|
|
2173 |
|
|
/* If RTX_FRAME_RELATED_P is set on a PARALLEL, process each member of
|
2174 |
|
|
the PARALLEL independently. The first element is always processed if
|
2175 |
|
|
it is a SET. This is for backward compatibility. Other elements
|
2176 |
|
|
are processed only if they are SETs and the RTX_FRAME_RELATED_P
|
2177 |
|
|
flag is set in them. */
|
2178 |
|
|
if (GET_CODE (expr) == PARALLEL || GET_CODE (expr) == SEQUENCE)
|
2179 |
|
|
{
|
2180 |
|
|
int par_index;
|
2181 |
|
|
int limit = XVECLEN (expr, 0);
|
2182 |
|
|
rtx elem;
|
2183 |
|
|
|
2184 |
|
|
/* PARALLELs have strict read-modify-write semantics, so we
|
2185 |
|
|
ought to evaluate every rvalue before changing any lvalue.
|
2186 |
|
|
It's cumbersome to do that in general, but there's an
|
2187 |
|
|
easy approximation that is enough for all current users:
|
2188 |
|
|
handle register saves before register assignments. */
|
2189 |
|
|
if (GET_CODE (expr) == PARALLEL)
|
2190 |
|
|
for (par_index = 0; par_index < limit; par_index++)
|
2191 |
|
|
{
|
2192 |
|
|
elem = XVECEXP (expr, 0, par_index);
|
2193 |
|
|
if (GET_CODE (elem) == SET
|
2194 |
|
|
&& MEM_P (SET_DEST (elem))
|
2195 |
|
|
&& (RTX_FRAME_RELATED_P (elem) || par_index == 0))
|
2196 |
|
|
dwarf2out_frame_debug_expr (elem, label);
|
2197 |
|
|
}
|
2198 |
|
|
|
2199 |
|
|
for (par_index = 0; par_index < limit; par_index++)
|
2200 |
|
|
{
|
2201 |
|
|
elem = XVECEXP (expr, 0, par_index);
|
2202 |
|
|
if (GET_CODE (elem) == SET
|
2203 |
|
|
&& (!MEM_P (SET_DEST (elem)) || GET_CODE (expr) == SEQUENCE)
|
2204 |
|
|
&& (RTX_FRAME_RELATED_P (elem) || par_index == 0))
|
2205 |
|
|
dwarf2out_frame_debug_expr (elem, label);
|
2206 |
|
|
else if (GET_CODE (elem) == SET
|
2207 |
|
|
&& par_index != 0
|
2208 |
|
|
&& !RTX_FRAME_RELATED_P (elem))
|
2209 |
|
|
{
|
2210 |
|
|
/* Stack adjustment combining might combine some post-prologue
|
2211 |
|
|
stack adjustment into a prologue stack adjustment. */
|
2212 |
|
|
HOST_WIDE_INT offset = stack_adjust_offset (elem, args_size, 0);
|
2213 |
|
|
|
2214 |
|
|
if (offset != 0)
|
2215 |
|
|
dwarf2out_stack_adjust (offset, label);
|
2216 |
|
|
}
|
2217 |
|
|
}
|
2218 |
|
|
return;
|
2219 |
|
|
}
|
2220 |
|
|
|
2221 |
|
|
gcc_assert (GET_CODE (expr) == SET);
|
2222 |
|
|
|
2223 |
|
|
src = SET_SRC (expr);
|
2224 |
|
|
dest = SET_DEST (expr);
|
2225 |
|
|
|
2226 |
|
|
if (REG_P (src))
|
2227 |
|
|
{
|
2228 |
|
|
rtx rsi = reg_saved_in (src);
|
2229 |
|
|
if (rsi)
|
2230 |
|
|
src = rsi;
|
2231 |
|
|
}
|
2232 |
|
|
|
2233 |
|
|
fde = current_fde ();
|
2234 |
|
|
|
2235 |
|
|
switch (GET_CODE (dest))
|
2236 |
|
|
{
|
2237 |
|
|
case REG:
|
2238 |
|
|
switch (GET_CODE (src))
|
2239 |
|
|
{
|
2240 |
|
|
/* Setting FP from SP. */
|
2241 |
|
|
case REG:
|
2242 |
|
|
if (cfa.reg == (unsigned) REGNO (src))
|
2243 |
|
|
{
|
2244 |
|
|
/* Rule 1 */
|
2245 |
|
|
/* Update the CFA rule wrt SP or FP. Make sure src is
|
2246 |
|
|
relative to the current CFA register.
|
2247 |
|
|
|
2248 |
|
|
We used to require that dest be either SP or FP, but the
|
2249 |
|
|
ARM copies SP to a temporary register, and from there to
|
2250 |
|
|
FP. So we just rely on the backends to only set
|
2251 |
|
|
RTX_FRAME_RELATED_P on appropriate insns. */
|
2252 |
|
|
cfa.reg = REGNO (dest);
|
2253 |
|
|
cfa_temp.reg = cfa.reg;
|
2254 |
|
|
cfa_temp.offset = cfa.offset;
|
2255 |
|
|
}
|
2256 |
|
|
else
|
2257 |
|
|
{
|
2258 |
|
|
/* Saving a register in a register. */
|
2259 |
|
|
gcc_assert (!fixed_regs [REGNO (dest)]
|
2260 |
|
|
/* For the SPARC and its register window. */
|
2261 |
|
|
|| (DWARF_FRAME_REGNUM (REGNO (src))
|
2262 |
|
|
== DWARF_FRAME_RETURN_COLUMN));
|
2263 |
|
|
|
2264 |
|
|
/* After stack is aligned, we can only save SP in FP
|
2265 |
|
|
if drap register is used. In this case, we have
|
2266 |
|
|
to restore stack pointer with the CFA value and we
|
2267 |
|
|
don't generate this DWARF information. */
|
2268 |
|
|
if (fde
|
2269 |
|
|
&& fde->stack_realign
|
2270 |
|
|
&& REGNO (src) == STACK_POINTER_REGNUM)
|
2271 |
|
|
gcc_assert (REGNO (dest) == HARD_FRAME_POINTER_REGNUM
|
2272 |
|
|
&& fde->drap_reg != INVALID_REGNUM
|
2273 |
|
|
&& cfa.reg != REGNO (src));
|
2274 |
|
|
else
|
2275 |
|
|
queue_reg_save (label, src, dest, 0);
|
2276 |
|
|
}
|
2277 |
|
|
break;
|
2278 |
|
|
|
2279 |
|
|
case PLUS:
|
2280 |
|
|
case MINUS:
|
2281 |
|
|
case LO_SUM:
|
2282 |
|
|
if (dest == stack_pointer_rtx)
|
2283 |
|
|
{
|
2284 |
|
|
/* Rule 2 */
|
2285 |
|
|
/* Adjusting SP. */
|
2286 |
|
|
switch (GET_CODE (XEXP (src, 1)))
|
2287 |
|
|
{
|
2288 |
|
|
case CONST_INT:
|
2289 |
|
|
offset = INTVAL (XEXP (src, 1));
|
2290 |
|
|
break;
|
2291 |
|
|
case REG:
|
2292 |
|
|
gcc_assert ((unsigned) REGNO (XEXP (src, 1))
|
2293 |
|
|
== cfa_temp.reg);
|
2294 |
|
|
offset = cfa_temp.offset;
|
2295 |
|
|
break;
|
2296 |
|
|
default:
|
2297 |
|
|
gcc_unreachable ();
|
2298 |
|
|
}
|
2299 |
|
|
|
2300 |
|
|
if (XEXP (src, 0) == hard_frame_pointer_rtx)
|
2301 |
|
|
{
|
2302 |
|
|
/* Restoring SP from FP in the epilogue. */
|
2303 |
|
|
gcc_assert (cfa.reg == (unsigned) HARD_FRAME_POINTER_REGNUM);
|
2304 |
|
|
cfa.reg = STACK_POINTER_REGNUM;
|
2305 |
|
|
}
|
2306 |
|
|
else if (GET_CODE (src) == LO_SUM)
|
2307 |
|
|
/* Assume we've set the source reg of the LO_SUM from sp. */
|
2308 |
|
|
;
|
2309 |
|
|
else
|
2310 |
|
|
gcc_assert (XEXP (src, 0) == stack_pointer_rtx);
|
2311 |
|
|
|
2312 |
|
|
if (GET_CODE (src) != MINUS)
|
2313 |
|
|
offset = -offset;
|
2314 |
|
|
if (cfa.reg == STACK_POINTER_REGNUM)
|
2315 |
|
|
cfa.offset += offset;
|
2316 |
|
|
if (cfa_store.reg == STACK_POINTER_REGNUM)
|
2317 |
|
|
cfa_store.offset += offset;
|
2318 |
|
|
}
|
2319 |
|
|
else if (dest == hard_frame_pointer_rtx)
|
2320 |
|
|
{
|
2321 |
|
|
/* Rule 3 */
|
2322 |
|
|
/* Either setting the FP from an offset of the SP,
|
2323 |
|
|
or adjusting the FP */
|
2324 |
|
|
gcc_assert (frame_pointer_needed);
|
2325 |
|
|
|
2326 |
|
|
gcc_assert (REG_P (XEXP (src, 0))
|
2327 |
|
|
&& (unsigned) REGNO (XEXP (src, 0)) == cfa.reg
|
2328 |
|
|
&& CONST_INT_P (XEXP (src, 1)));
|
2329 |
|
|
offset = INTVAL (XEXP (src, 1));
|
2330 |
|
|
if (GET_CODE (src) != MINUS)
|
2331 |
|
|
offset = -offset;
|
2332 |
|
|
cfa.offset += offset;
|
2333 |
|
|
cfa.reg = HARD_FRAME_POINTER_REGNUM;
|
2334 |
|
|
}
|
2335 |
|
|
else
|
2336 |
|
|
{
|
2337 |
|
|
gcc_assert (GET_CODE (src) != MINUS);
|
2338 |
|
|
|
2339 |
|
|
/* Rule 4 */
|
2340 |
|
|
if (REG_P (XEXP (src, 0))
|
2341 |
|
|
&& REGNO (XEXP (src, 0)) == cfa.reg
|
2342 |
|
|
&& CONST_INT_P (XEXP (src, 1)))
|
2343 |
|
|
{
|
2344 |
|
|
/* Setting a temporary CFA register that will be copied
|
2345 |
|
|
into the FP later on. */
|
2346 |
|
|
offset = - INTVAL (XEXP (src, 1));
|
2347 |
|
|
cfa.offset += offset;
|
2348 |
|
|
cfa.reg = REGNO (dest);
|
2349 |
|
|
/* Or used to save regs to the stack. */
|
2350 |
|
|
cfa_temp.reg = cfa.reg;
|
2351 |
|
|
cfa_temp.offset = cfa.offset;
|
2352 |
|
|
}
|
2353 |
|
|
|
2354 |
|
|
/* Rule 5 */
|
2355 |
|
|
else if (REG_P (XEXP (src, 0))
|
2356 |
|
|
&& REGNO (XEXP (src, 0)) == cfa_temp.reg
|
2357 |
|
|
&& XEXP (src, 1) == stack_pointer_rtx)
|
2358 |
|
|
{
|
2359 |
|
|
/* Setting a scratch register that we will use instead
|
2360 |
|
|
of SP for saving registers to the stack. */
|
2361 |
|
|
gcc_assert (cfa.reg == STACK_POINTER_REGNUM);
|
2362 |
|
|
cfa_store.reg = REGNO (dest);
|
2363 |
|
|
cfa_store.offset = cfa.offset - cfa_temp.offset;
|
2364 |
|
|
}
|
2365 |
|
|
|
2366 |
|
|
/* Rule 9 */
|
2367 |
|
|
else if (GET_CODE (src) == LO_SUM
|
2368 |
|
|
&& CONST_INT_P (XEXP (src, 1)))
|
2369 |
|
|
{
|
2370 |
|
|
cfa_temp.reg = REGNO (dest);
|
2371 |
|
|
cfa_temp.offset = INTVAL (XEXP (src, 1));
|
2372 |
|
|
}
|
2373 |
|
|
else
|
2374 |
|
|
gcc_unreachable ();
|
2375 |
|
|
}
|
2376 |
|
|
break;
|
2377 |
|
|
|
2378 |
|
|
/* Rule 6 */
|
2379 |
|
|
case CONST_INT:
|
2380 |
|
|
cfa_temp.reg = REGNO (dest);
|
2381 |
|
|
cfa_temp.offset = INTVAL (src);
|
2382 |
|
|
break;
|
2383 |
|
|
|
2384 |
|
|
/* Rule 7 */
|
2385 |
|
|
case IOR:
|
2386 |
|
|
gcc_assert (REG_P (XEXP (src, 0))
|
2387 |
|
|
&& (unsigned) REGNO (XEXP (src, 0)) == cfa_temp.reg
|
2388 |
|
|
&& CONST_INT_P (XEXP (src, 1)));
|
2389 |
|
|
|
2390 |
|
|
if ((unsigned) REGNO (dest) != cfa_temp.reg)
|
2391 |
|
|
cfa_temp.reg = REGNO (dest);
|
2392 |
|
|
cfa_temp.offset |= INTVAL (XEXP (src, 1));
|
2393 |
|
|
break;
|
2394 |
|
|
|
2395 |
|
|
/* Skip over HIGH, assuming it will be followed by a LO_SUM,
|
2396 |
|
|
which will fill in all of the bits. */
|
2397 |
|
|
/* Rule 8 */
|
2398 |
|
|
case HIGH:
|
2399 |
|
|
break;
|
2400 |
|
|
|
2401 |
|
|
/* Rule 15 */
|
2402 |
|
|
case UNSPEC:
|
2403 |
|
|
case UNSPEC_VOLATILE:
|
2404 |
|
|
gcc_assert (targetm.dwarf_handle_frame_unspec);
|
2405 |
|
|
targetm.dwarf_handle_frame_unspec (label, expr, XINT (src, 1));
|
2406 |
|
|
return;
|
2407 |
|
|
|
2408 |
|
|
/* Rule 16 */
|
2409 |
|
|
case AND:
|
2410 |
|
|
/* If this AND operation happens on stack pointer in prologue,
|
2411 |
|
|
we assume the stack is realigned and we extract the
|
2412 |
|
|
alignment. */
|
2413 |
|
|
if (fde && XEXP (src, 0) == stack_pointer_rtx)
|
2414 |
|
|
{
|
2415 |
|
|
gcc_assert (cfa_store.reg == REGNO (XEXP (src, 0)));
|
2416 |
|
|
fde->stack_realign = 1;
|
2417 |
|
|
fde->stack_realignment = INTVAL (XEXP (src, 1));
|
2418 |
|
|
cfa_store.offset = 0;
|
2419 |
|
|
|
2420 |
|
|
if (cfa.reg != STACK_POINTER_REGNUM
|
2421 |
|
|
&& cfa.reg != HARD_FRAME_POINTER_REGNUM)
|
2422 |
|
|
fde->drap_reg = cfa.reg;
|
2423 |
|
|
}
|
2424 |
|
|
return;
|
2425 |
|
|
|
2426 |
|
|
default:
|
2427 |
|
|
gcc_unreachable ();
|
2428 |
|
|
}
|
2429 |
|
|
|
2430 |
|
|
def_cfa_1 (label, &cfa);
|
2431 |
|
|
break;
|
2432 |
|
|
|
2433 |
|
|
case MEM:
|
2434 |
|
|
|
2435 |
|
|
/* Saving a register to the stack. Make sure dest is relative to the
|
2436 |
|
|
CFA register. */
|
2437 |
|
|
switch (GET_CODE (XEXP (dest, 0)))
|
2438 |
|
|
{
|
2439 |
|
|
/* Rule 10 */
|
2440 |
|
|
/* With a push. */
|
2441 |
|
|
case PRE_MODIFY:
|
2442 |
|
|
/* We can't handle variable size modifications. */
|
2443 |
|
|
gcc_assert (GET_CODE (XEXP (XEXP (XEXP (dest, 0), 1), 1))
|
2444 |
|
|
== CONST_INT);
|
2445 |
|
|
offset = -INTVAL (XEXP (XEXP (XEXP (dest, 0), 1), 1));
|
2446 |
|
|
|
2447 |
|
|
gcc_assert (REGNO (XEXP (XEXP (dest, 0), 0)) == STACK_POINTER_REGNUM
|
2448 |
|
|
&& cfa_store.reg == STACK_POINTER_REGNUM);
|
2449 |
|
|
|
2450 |
|
|
cfa_store.offset += offset;
|
2451 |
|
|
if (cfa.reg == STACK_POINTER_REGNUM)
|
2452 |
|
|
cfa.offset = cfa_store.offset;
|
2453 |
|
|
|
2454 |
|
|
offset = -cfa_store.offset;
|
2455 |
|
|
break;
|
2456 |
|
|
|
2457 |
|
|
/* Rule 11 */
|
2458 |
|
|
case PRE_INC:
|
2459 |
|
|
case PRE_DEC:
|
2460 |
|
|
offset = GET_MODE_SIZE (GET_MODE (dest));
|
2461 |
|
|
if (GET_CODE (XEXP (dest, 0)) == PRE_INC)
|
2462 |
|
|
offset = -offset;
|
2463 |
|
|
|
2464 |
|
|
gcc_assert ((REGNO (XEXP (XEXP (dest, 0), 0))
|
2465 |
|
|
== STACK_POINTER_REGNUM)
|
2466 |
|
|
&& cfa_store.reg == STACK_POINTER_REGNUM);
|
2467 |
|
|
|
2468 |
|
|
cfa_store.offset += offset;
|
2469 |
|
|
|
2470 |
|
|
/* Rule 18: If stack is aligned, we will use FP as a
|
2471 |
|
|
reference to represent the address of the stored
|
2472 |
|
|
regiser. */
|
2473 |
|
|
if (fde
|
2474 |
|
|
&& fde->stack_realign
|
2475 |
|
|
&& src == hard_frame_pointer_rtx)
|
2476 |
|
|
{
|
2477 |
|
|
gcc_assert (cfa.reg != HARD_FRAME_POINTER_REGNUM);
|
2478 |
|
|
cfa_store.offset = 0;
|
2479 |
|
|
}
|
2480 |
|
|
|
2481 |
|
|
if (cfa.reg == STACK_POINTER_REGNUM)
|
2482 |
|
|
cfa.offset = cfa_store.offset;
|
2483 |
|
|
|
2484 |
|
|
offset = -cfa_store.offset;
|
2485 |
|
|
break;
|
2486 |
|
|
|
2487 |
|
|
/* Rule 12 */
|
2488 |
|
|
/* With an offset. */
|
2489 |
|
|
case PLUS:
|
2490 |
|
|
case MINUS:
|
2491 |
|
|
case LO_SUM:
|
2492 |
|
|
{
|
2493 |
|
|
int regno;
|
2494 |
|
|
|
2495 |
|
|
gcc_assert (CONST_INT_P (XEXP (XEXP (dest, 0), 1))
|
2496 |
|
|
&& REG_P (XEXP (XEXP (dest, 0), 0)));
|
2497 |
|
|
offset = INTVAL (XEXP (XEXP (dest, 0), 1));
|
2498 |
|
|
if (GET_CODE (XEXP (dest, 0)) == MINUS)
|
2499 |
|
|
offset = -offset;
|
2500 |
|
|
|
2501 |
|
|
regno = REGNO (XEXP (XEXP (dest, 0), 0));
|
2502 |
|
|
|
2503 |
|
|
if (cfa_store.reg == (unsigned) regno)
|
2504 |
|
|
offset -= cfa_store.offset;
|
2505 |
|
|
else
|
2506 |
|
|
{
|
2507 |
|
|
gcc_assert (cfa_temp.reg == (unsigned) regno);
|
2508 |
|
|
offset -= cfa_temp.offset;
|
2509 |
|
|
}
|
2510 |
|
|
}
|
2511 |
|
|
break;
|
2512 |
|
|
|
2513 |
|
|
/* Rule 13 */
|
2514 |
|
|
/* Without an offset. */
|
2515 |
|
|
case REG:
|
2516 |
|
|
{
|
2517 |
|
|
int regno = REGNO (XEXP (dest, 0));
|
2518 |
|
|
|
2519 |
|
|
if (cfa_store.reg == (unsigned) regno)
|
2520 |
|
|
offset = -cfa_store.offset;
|
2521 |
|
|
else
|
2522 |
|
|
{
|
2523 |
|
|
gcc_assert (cfa_temp.reg == (unsigned) regno);
|
2524 |
|
|
offset = -cfa_temp.offset;
|
2525 |
|
|
}
|
2526 |
|
|
}
|
2527 |
|
|
break;
|
2528 |
|
|
|
2529 |
|
|
/* Rule 14 */
|
2530 |
|
|
case POST_INC:
|
2531 |
|
|
gcc_assert (cfa_temp.reg
|
2532 |
|
|
== (unsigned) REGNO (XEXP (XEXP (dest, 0), 0)));
|
2533 |
|
|
offset = -cfa_temp.offset;
|
2534 |
|
|
cfa_temp.offset -= GET_MODE_SIZE (GET_MODE (dest));
|
2535 |
|
|
break;
|
2536 |
|
|
|
2537 |
|
|
default:
|
2538 |
|
|
gcc_unreachable ();
|
2539 |
|
|
}
|
2540 |
|
|
|
2541 |
|
|
/* Rule 17 */
|
2542 |
|
|
/* If the source operand of this MEM operation is not a
|
2543 |
|
|
register, basically the source is return address. Here
|
2544 |
|
|
we only care how much stack grew and we don't save it. */
|
2545 |
|
|
if (!REG_P (src))
|
2546 |
|
|
break;
|
2547 |
|
|
|
2548 |
|
|
if (REGNO (src) != STACK_POINTER_REGNUM
|
2549 |
|
|
&& REGNO (src) != HARD_FRAME_POINTER_REGNUM
|
2550 |
|
|
&& (unsigned) REGNO (src) == cfa.reg)
|
2551 |
|
|
{
|
2552 |
|
|
/* We're storing the current CFA reg into the stack. */
|
2553 |
|
|
|
2554 |
|
|
if (cfa.offset == 0)
|
2555 |
|
|
{
|
2556 |
|
|
/* Rule 19 */
|
2557 |
|
|
/* If stack is aligned, putting CFA reg into stack means
|
2558 |
|
|
we can no longer use reg + offset to represent CFA.
|
2559 |
|
|
Here we use DW_CFA_def_cfa_expression instead. The
|
2560 |
|
|
result of this expression equals to the original CFA
|
2561 |
|
|
value. */
|
2562 |
|
|
if (fde
|
2563 |
|
|
&& fde->stack_realign
|
2564 |
|
|
&& cfa.indirect == 0
|
2565 |
|
|
&& cfa.reg != HARD_FRAME_POINTER_REGNUM)
|
2566 |
|
|
{
|
2567 |
|
|
dw_cfa_location cfa_exp;
|
2568 |
|
|
|
2569 |
|
|
gcc_assert (fde->drap_reg == cfa.reg);
|
2570 |
|
|
|
2571 |
|
|
cfa_exp.indirect = 1;
|
2572 |
|
|
cfa_exp.reg = HARD_FRAME_POINTER_REGNUM;
|
2573 |
|
|
cfa_exp.base_offset = offset;
|
2574 |
|
|
cfa_exp.offset = 0;
|
2575 |
|
|
|
2576 |
|
|
fde->drap_reg_saved = 1;
|
2577 |
|
|
|
2578 |
|
|
def_cfa_1 (label, &cfa_exp);
|
2579 |
|
|
break;
|
2580 |
|
|
}
|
2581 |
|
|
|
2582 |
|
|
/* If the source register is exactly the CFA, assume
|
2583 |
|
|
we're saving SP like any other register; this happens
|
2584 |
|
|
on the ARM. */
|
2585 |
|
|
def_cfa_1 (label, &cfa);
|
2586 |
|
|
queue_reg_save (label, stack_pointer_rtx, NULL_RTX, offset);
|
2587 |
|
|
break;
|
2588 |
|
|
}
|
2589 |
|
|
else
|
2590 |
|
|
{
|
2591 |
|
|
/* Otherwise, we'll need to look in the stack to
|
2592 |
|
|
calculate the CFA. */
|
2593 |
|
|
rtx x = XEXP (dest, 0);
|
2594 |
|
|
|
2595 |
|
|
if (!REG_P (x))
|
2596 |
|
|
x = XEXP (x, 0);
|
2597 |
|
|
gcc_assert (REG_P (x));
|
2598 |
|
|
|
2599 |
|
|
cfa.reg = REGNO (x);
|
2600 |
|
|
cfa.base_offset = offset;
|
2601 |
|
|
cfa.indirect = 1;
|
2602 |
|
|
def_cfa_1 (label, &cfa);
|
2603 |
|
|
break;
|
2604 |
|
|
}
|
2605 |
|
|
}
|
2606 |
|
|
|
2607 |
|
|
def_cfa_1 (label, &cfa);
|
2608 |
|
|
{
|
2609 |
|
|
span = targetm.dwarf_register_span (src);
|
2610 |
|
|
|
2611 |
|
|
if (!span)
|
2612 |
|
|
queue_reg_save (label, src, NULL_RTX, offset);
|
2613 |
|
|
else
|
2614 |
|
|
{
|
2615 |
|
|
/* We have a PARALLEL describing where the contents of SRC
|
2616 |
|
|
live. Queue register saves for each piece of the
|
2617 |
|
|
PARALLEL. */
|
2618 |
|
|
int par_index;
|
2619 |
|
|
int limit;
|
2620 |
|
|
HOST_WIDE_INT span_offset = offset;
|
2621 |
|
|
|
2622 |
|
|
gcc_assert (GET_CODE (span) == PARALLEL);
|
2623 |
|
|
|
2624 |
|
|
limit = XVECLEN (span, 0);
|
2625 |
|
|
for (par_index = 0; par_index < limit; par_index++)
|
2626 |
|
|
{
|
2627 |
|
|
rtx elem = XVECEXP (span, 0, par_index);
|
2628 |
|
|
|
2629 |
|
|
queue_reg_save (label, elem, NULL_RTX, span_offset);
|
2630 |
|
|
span_offset += GET_MODE_SIZE (GET_MODE (elem));
|
2631 |
|
|
}
|
2632 |
|
|
}
|
2633 |
|
|
}
|
2634 |
|
|
break;
|
2635 |
|
|
|
2636 |
|
|
default:
|
2637 |
|
|
gcc_unreachable ();
|
2638 |
|
|
}
|
2639 |
|
|
}
|
2640 |
|
|
|
2641 |
|
|
/* Record call frame debugging information for INSN, which either
|
2642 |
|
|
sets SP or FP (adjusting how we calculate the frame address) or saves a
|
2643 |
|
|
register to the stack. If INSN is NULL_RTX, initialize our state.
|
2644 |
|
|
|
2645 |
|
|
If AFTER_P is false, we're being called before the insn is emitted,
|
2646 |
|
|
otherwise after. Call instructions get invoked twice. */
|
2647 |
|
|
|
2648 |
|
|
void
|
2649 |
|
|
dwarf2out_frame_debug (rtx insn, bool after_p)
|
2650 |
|
|
{
|
2651 |
|
|
const char *label;
|
2652 |
|
|
rtx note, n;
|
2653 |
|
|
bool handled_one = false;
|
2654 |
|
|
|
2655 |
|
|
if (insn == NULL_RTX)
|
2656 |
|
|
{
|
2657 |
|
|
size_t i;
|
2658 |
|
|
|
2659 |
|
|
/* Flush any queued register saves. */
|
2660 |
|
|
flush_queued_reg_saves ();
|
2661 |
|
|
|
2662 |
|
|
/* Set up state for generating call frame debug info. */
|
2663 |
|
|
lookup_cfa (&cfa);
|
2664 |
|
|
gcc_assert (cfa.reg
|
2665 |
|
|
== (unsigned long)DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM));
|
2666 |
|
|
|
2667 |
|
|
cfa.reg = STACK_POINTER_REGNUM;
|
2668 |
|
|
cfa_store = cfa;
|
2669 |
|
|
cfa_temp.reg = -1;
|
2670 |
|
|
cfa_temp.offset = 0;
|
2671 |
|
|
|
2672 |
|
|
for (i = 0; i < num_regs_saved_in_regs; i++)
|
2673 |
|
|
{
|
2674 |
|
|
regs_saved_in_regs[i].orig_reg = NULL_RTX;
|
2675 |
|
|
regs_saved_in_regs[i].saved_in_reg = NULL_RTX;
|
2676 |
|
|
}
|
2677 |
|
|
num_regs_saved_in_regs = 0;
|
2678 |
|
|
|
2679 |
|
|
if (barrier_args_size)
|
2680 |
|
|
{
|
2681 |
|
|
XDELETEVEC (barrier_args_size);
|
2682 |
|
|
barrier_args_size = NULL;
|
2683 |
|
|
}
|
2684 |
|
|
return;
|
2685 |
|
|
}
|
2686 |
|
|
|
2687 |
|
|
if (!NONJUMP_INSN_P (insn) || clobbers_queued_reg_save (insn))
|
2688 |
|
|
flush_queued_reg_saves ();
|
2689 |
|
|
|
2690 |
|
|
if (!RTX_FRAME_RELATED_P (insn))
|
2691 |
|
|
{
|
2692 |
|
|
/* ??? This should be done unconditionally since stack adjustments
|
2693 |
|
|
matter if the stack pointer is not the CFA register anymore but
|
2694 |
|
|
is still used to save registers. */
|
2695 |
|
|
if (!ACCUMULATE_OUTGOING_ARGS)
|
2696 |
|
|
dwarf2out_notice_stack_adjust (insn, after_p);
|
2697 |
|
|
return;
|
2698 |
|
|
}
|
2699 |
|
|
|
2700 |
|
|
label = dwarf2out_cfi_label (false);
|
2701 |
|
|
|
2702 |
|
|
for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
|
2703 |
|
|
switch (REG_NOTE_KIND (note))
|
2704 |
|
|
{
|
2705 |
|
|
case REG_FRAME_RELATED_EXPR:
|
2706 |
|
|
insn = XEXP (note, 0);
|
2707 |
|
|
goto found;
|
2708 |
|
|
|
2709 |
|
|
case REG_CFA_DEF_CFA:
|
2710 |
|
|
dwarf2out_frame_debug_def_cfa (XEXP (note, 0), label);
|
2711 |
|
|
handled_one = true;
|
2712 |
|
|
break;
|
2713 |
|
|
|
2714 |
|
|
case REG_CFA_ADJUST_CFA:
|
2715 |
|
|
n = XEXP (note, 0);
|
2716 |
|
|
if (n == NULL)
|
2717 |
|
|
{
|
2718 |
|
|
n = PATTERN (insn);
|
2719 |
|
|
if (GET_CODE (n) == PARALLEL)
|
2720 |
|
|
n = XVECEXP (n, 0, 0);
|
2721 |
|
|
}
|
2722 |
|
|
dwarf2out_frame_debug_adjust_cfa (n, label);
|
2723 |
|
|
handled_one = true;
|
2724 |
|
|
break;
|
2725 |
|
|
|
2726 |
|
|
case REG_CFA_OFFSET:
|
2727 |
|
|
n = XEXP (note, 0);
|
2728 |
|
|
if (n == NULL)
|
2729 |
|
|
n = single_set (insn);
|
2730 |
|
|
dwarf2out_frame_debug_cfa_offset (n, label);
|
2731 |
|
|
handled_one = true;
|
2732 |
|
|
break;
|
2733 |
|
|
|
2734 |
|
|
case REG_CFA_REGISTER:
|
2735 |
|
|
n = XEXP (note, 0);
|
2736 |
|
|
if (n == NULL)
|
2737 |
|
|
{
|
2738 |
|
|
n = PATTERN (insn);
|
2739 |
|
|
if (GET_CODE (n) == PARALLEL)
|
2740 |
|
|
n = XVECEXP (n, 0, 0);
|
2741 |
|
|
}
|
2742 |
|
|
dwarf2out_frame_debug_cfa_register (n, label);
|
2743 |
|
|
handled_one = true;
|
2744 |
|
|
break;
|
2745 |
|
|
|
2746 |
|
|
case REG_CFA_RESTORE:
|
2747 |
|
|
n = XEXP (note, 0);
|
2748 |
|
|
if (n == NULL)
|
2749 |
|
|
{
|
2750 |
|
|
n = PATTERN (insn);
|
2751 |
|
|
if (GET_CODE (n) == PARALLEL)
|
2752 |
|
|
n = XVECEXP (n, 0, 0);
|
2753 |
|
|
n = XEXP (n, 0);
|
2754 |
|
|
}
|
2755 |
|
|
dwarf2out_frame_debug_cfa_restore (n, label);
|
2756 |
|
|
handled_one = true;
|
2757 |
|
|
break;
|
2758 |
|
|
|
2759 |
|
|
case REG_CFA_SET_VDRAP:
|
2760 |
|
|
n = XEXP (note, 0);
|
2761 |
|
|
if (REG_P (n))
|
2762 |
|
|
{
|
2763 |
|
|
dw_fde_ref fde = current_fde ();
|
2764 |
|
|
if (fde)
|
2765 |
|
|
{
|
2766 |
|
|
gcc_assert (fde->vdrap_reg == INVALID_REGNUM);
|
2767 |
|
|
if (REG_P (n))
|
2768 |
|
|
fde->vdrap_reg = REGNO (n);
|
2769 |
|
|
}
|
2770 |
|
|
}
|
2771 |
|
|
handled_one = true;
|
2772 |
|
|
break;
|
2773 |
|
|
|
2774 |
|
|
default:
|
2775 |
|
|
break;
|
2776 |
|
|
}
|
2777 |
|
|
if (handled_one)
|
2778 |
|
|
return;
|
2779 |
|
|
|
2780 |
|
|
insn = PATTERN (insn);
|
2781 |
|
|
found:
|
2782 |
|
|
dwarf2out_frame_debug_expr (insn, label);
|
2783 |
|
|
}
|
2784 |
|
|
|
2785 |
|
|
/* Determine if we need to save and restore CFI information around this
|
2786 |
|
|
epilogue. If SIBCALL is true, then this is a sibcall epilogue. If
|
2787 |
|
|
we do need to save/restore, then emit the save now, and insert a
|
2788 |
|
|
NOTE_INSN_CFA_RESTORE_STATE at the appropriate place in the stream. */
|
2789 |
|
|
|
2790 |
|
|
void
|
2791 |
|
|
dwarf2out_begin_epilogue (rtx insn)
|
2792 |
|
|
{
|
2793 |
|
|
bool saw_frp = false;
|
2794 |
|
|
rtx i;
|
2795 |
|
|
|
2796 |
|
|
/* Scan forward to the return insn, noticing if there are possible
|
2797 |
|
|
frame related insns. */
|
2798 |
|
|
for (i = NEXT_INSN (insn); i ; i = NEXT_INSN (i))
|
2799 |
|
|
{
|
2800 |
|
|
if (!INSN_P (i))
|
2801 |
|
|
continue;
|
2802 |
|
|
|
2803 |
|
|
/* Look for both regular and sibcalls to end the block. */
|
2804 |
|
|
if (returnjump_p (i))
|
2805 |
|
|
break;
|
2806 |
|
|
if (CALL_P (i) && SIBLING_CALL_P (i))
|
2807 |
|
|
break;
|
2808 |
|
|
|
2809 |
|
|
if (GET_CODE (PATTERN (i)) == SEQUENCE)
|
2810 |
|
|
{
|
2811 |
|
|
int idx;
|
2812 |
|
|
rtx seq = PATTERN (i);
|
2813 |
|
|
|
2814 |
|
|
if (returnjump_p (XVECEXP (seq, 0, 0)))
|
2815 |
|
|
break;
|
2816 |
|
|
if (CALL_P (XVECEXP (seq, 0, 0))
|
2817 |
|
|
&& SIBLING_CALL_P (XVECEXP (seq, 0, 0)))
|
2818 |
|
|
break;
|
2819 |
|
|
|
2820 |
|
|
for (idx = 0; idx < XVECLEN (seq, 0); idx++)
|
2821 |
|
|
if (RTX_FRAME_RELATED_P (XVECEXP (seq, 0, idx)))
|
2822 |
|
|
saw_frp = true;
|
2823 |
|
|
}
|
2824 |
|
|
|
2825 |
|
|
if (RTX_FRAME_RELATED_P (i))
|
2826 |
|
|
saw_frp = true;
|
2827 |
|
|
}
|
2828 |
|
|
|
2829 |
|
|
/* If the port doesn't emit epilogue unwind info, we don't need a
|
2830 |
|
|
save/restore pair. */
|
2831 |
|
|
if (!saw_frp)
|
2832 |
|
|
return;
|
2833 |
|
|
|
2834 |
|
|
/* Otherwise, search forward to see if the return insn was the last
|
2835 |
|
|
basic block of the function. If so, we don't need save/restore. */
|
2836 |
|
|
gcc_assert (i != NULL);
|
2837 |
|
|
i = next_real_insn (i);
|
2838 |
|
|
if (i == NULL)
|
2839 |
|
|
return;
|
2840 |
|
|
|
2841 |
|
|
/* Insert the restore before that next real insn in the stream, and before
|
2842 |
|
|
a potential NOTE_INSN_EPILOGUE_BEG -- we do need these notes to be
|
2843 |
|
|
properly nested. This should be after any label or alignment. This
|
2844 |
|
|
will be pushed into the CFI stream by the function below. */
|
2845 |
|
|
while (1)
|
2846 |
|
|
{
|
2847 |
|
|
rtx p = PREV_INSN (i);
|
2848 |
|
|
if (!NOTE_P (p))
|
2849 |
|
|
break;
|
2850 |
|
|
if (NOTE_KIND (p) == NOTE_INSN_BASIC_BLOCK)
|
2851 |
|
|
break;
|
2852 |
|
|
i = p;
|
2853 |
|
|
}
|
2854 |
|
|
emit_note_before (NOTE_INSN_CFA_RESTORE_STATE, i);
|
2855 |
|
|
|
2856 |
|
|
emit_cfa_remember = true;
|
2857 |
|
|
|
2858 |
|
|
/* And emulate the state save. */
|
2859 |
|
|
gcc_assert (!cfa_remember.in_use);
|
2860 |
|
|
cfa_remember = cfa;
|
2861 |
|
|
cfa_remember.in_use = 1;
|
2862 |
|
|
}
|
2863 |
|
|
|
2864 |
|
|
/* A "subroutine" of dwarf2out_begin_epilogue. Emit the restore required. */
|
2865 |
|
|
|
2866 |
|
|
void
|
2867 |
|
|
dwarf2out_frame_debug_restore_state (void)
|
2868 |
|
|
{
|
2869 |
|
|
dw_cfi_ref cfi = new_cfi ();
|
2870 |
|
|
const char *label = dwarf2out_cfi_label (false);
|
2871 |
|
|
|
2872 |
|
|
cfi->dw_cfi_opc = DW_CFA_restore_state;
|
2873 |
|
|
add_fde_cfi (label, cfi);
|
2874 |
|
|
|
2875 |
|
|
gcc_assert (cfa_remember.in_use);
|
2876 |
|
|
cfa = cfa_remember;
|
2877 |
|
|
cfa_remember.in_use = 0;
|
2878 |
|
|
}
|
2879 |
|
|
|
2880 |
|
|
#endif
|
2881 |
|
|
|
2882 |
|
|
/* Describe for the GTY machinery what parts of dw_cfi_oprnd1 are used. */
|
2883 |
|
|
static enum dw_cfi_oprnd_type dw_cfi_oprnd1_desc
|
2884 |
|
|
(enum dwarf_call_frame_info cfi);
|
2885 |
|
|
|
2886 |
|
|
static enum dw_cfi_oprnd_type
|
2887 |
|
|
dw_cfi_oprnd1_desc (enum dwarf_call_frame_info cfi)
|
2888 |
|
|
{
|
2889 |
|
|
switch (cfi)
|
2890 |
|
|
{
|
2891 |
|
|
case DW_CFA_nop:
|
2892 |
|
|
case DW_CFA_GNU_window_save:
|
2893 |
|
|
case DW_CFA_remember_state:
|
2894 |
|
|
case DW_CFA_restore_state:
|
2895 |
|
|
return dw_cfi_oprnd_unused;
|
2896 |
|
|
|
2897 |
|
|
case DW_CFA_set_loc:
|
2898 |
|
|
case DW_CFA_advance_loc1:
|
2899 |
|
|
case DW_CFA_advance_loc2:
|
2900 |
|
|
case DW_CFA_advance_loc4:
|
2901 |
|
|
case DW_CFA_MIPS_advance_loc8:
|
2902 |
|
|
return dw_cfi_oprnd_addr;
|
2903 |
|
|
|
2904 |
|
|
case DW_CFA_offset:
|
2905 |
|
|
case DW_CFA_offset_extended:
|
2906 |
|
|
case DW_CFA_def_cfa:
|
2907 |
|
|
case DW_CFA_offset_extended_sf:
|
2908 |
|
|
case DW_CFA_def_cfa_sf:
|
2909 |
|
|
case DW_CFA_restore:
|
2910 |
|
|
case DW_CFA_restore_extended:
|
2911 |
|
|
case DW_CFA_undefined:
|
2912 |
|
|
case DW_CFA_same_value:
|
2913 |
|
|
case DW_CFA_def_cfa_register:
|
2914 |
|
|
case DW_CFA_register:
|
2915 |
|
|
case DW_CFA_expression:
|
2916 |
|
|
return dw_cfi_oprnd_reg_num;
|
2917 |
|
|
|
2918 |
|
|
case DW_CFA_def_cfa_offset:
|
2919 |
|
|
case DW_CFA_GNU_args_size:
|
2920 |
|
|
case DW_CFA_def_cfa_offset_sf:
|
2921 |
|
|
return dw_cfi_oprnd_offset;
|
2922 |
|
|
|
2923 |
|
|
case DW_CFA_def_cfa_expression:
|
2924 |
|
|
return dw_cfi_oprnd_loc;
|
2925 |
|
|
|
2926 |
|
|
default:
|
2927 |
|
|
gcc_unreachable ();
|
2928 |
|
|
}
|
2929 |
|
|
}
|
2930 |
|
|
|
2931 |
|
|
/* Describe for the GTY machinery what parts of dw_cfi_oprnd2 are used. */
|
2932 |
|
|
static enum dw_cfi_oprnd_type dw_cfi_oprnd2_desc
|
2933 |
|
|
(enum dwarf_call_frame_info cfi);
|
2934 |
|
|
|
2935 |
|
|
static enum dw_cfi_oprnd_type
|
2936 |
|
|
dw_cfi_oprnd2_desc (enum dwarf_call_frame_info cfi)
|
2937 |
|
|
{
|
2938 |
|
|
switch (cfi)
|
2939 |
|
|
{
|
2940 |
|
|
case DW_CFA_def_cfa:
|
2941 |
|
|
case DW_CFA_def_cfa_sf:
|
2942 |
|
|
case DW_CFA_offset:
|
2943 |
|
|
case DW_CFA_offset_extended_sf:
|
2944 |
|
|
case DW_CFA_offset_extended:
|
2945 |
|
|
return dw_cfi_oprnd_offset;
|
2946 |
|
|
|
2947 |
|
|
case DW_CFA_register:
|
2948 |
|
|
return dw_cfi_oprnd_reg_num;
|
2949 |
|
|
|
2950 |
|
|
case DW_CFA_expression:
|
2951 |
|
|
return dw_cfi_oprnd_loc;
|
2952 |
|
|
|
2953 |
|
|
default:
|
2954 |
|
|
return dw_cfi_oprnd_unused;
|
2955 |
|
|
}
|
2956 |
|
|
}
|
2957 |
|
|
|
2958 |
|
|
#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
|
2959 |
|
|
|
2960 |
|
|
/* Switch [BACK] to eh_frame_section. If we don't have an eh_frame_section,
|
2961 |
|
|
switch to the data section instead, and write out a synthetic start label
|
2962 |
|
|
for collect2 the first time around. */
|
2963 |
|
|
|
2964 |
|
|
static void
|
2965 |
|
|
switch_to_eh_frame_section (bool back)
|
2966 |
|
|
{
|
2967 |
|
|
tree label;
|
2968 |
|
|
|
2969 |
|
|
#ifdef EH_FRAME_SECTION_NAME
|
2970 |
|
|
if (eh_frame_section == 0)
|
2971 |
|
|
{
|
2972 |
|
|
int flags;
|
2973 |
|
|
|
2974 |
|
|
if (EH_TABLES_CAN_BE_READ_ONLY)
|
2975 |
|
|
{
|
2976 |
|
|
int fde_encoding;
|
2977 |
|
|
int per_encoding;
|
2978 |
|
|
int lsda_encoding;
|
2979 |
|
|
|
2980 |
|
|
fde_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/1,
|
2981 |
|
|
/*global=*/0);
|
2982 |
|
|
per_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2,
|
2983 |
|
|
/*global=*/1);
|
2984 |
|
|
lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0,
|
2985 |
|
|
/*global=*/0);
|
2986 |
|
|
flags = ((! flag_pic
|
2987 |
|
|
|| ((fde_encoding & 0x70) != DW_EH_PE_absptr
|
2988 |
|
|
&& (fde_encoding & 0x70) != DW_EH_PE_aligned
|
2989 |
|
|
&& (per_encoding & 0x70) != DW_EH_PE_absptr
|
2990 |
|
|
&& (per_encoding & 0x70) != DW_EH_PE_aligned
|
2991 |
|
|
&& (lsda_encoding & 0x70) != DW_EH_PE_absptr
|
2992 |
|
|
&& (lsda_encoding & 0x70) != DW_EH_PE_aligned))
|
2993 |
|
|
? 0 : SECTION_WRITE);
|
2994 |
|
|
}
|
2995 |
|
|
else
|
2996 |
|
|
flags = SECTION_WRITE;
|
2997 |
|
|
eh_frame_section = get_section (EH_FRAME_SECTION_NAME, flags, NULL);
|
2998 |
|
|
}
|
2999 |
|
|
#endif
|
3000 |
|
|
|
3001 |
|
|
if (eh_frame_section)
|
3002 |
|
|
switch_to_section (eh_frame_section);
|
3003 |
|
|
else
|
3004 |
|
|
{
|
3005 |
|
|
/* We have no special eh_frame section. Put the information in
|
3006 |
|
|
the data section and emit special labels to guide collect2. */
|
3007 |
|
|
switch_to_section (data_section);
|
3008 |
|
|
|
3009 |
|
|
if (!back)
|
3010 |
|
|
{
|
3011 |
|
|
label = get_file_function_name ("F");
|
3012 |
|
|
ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE));
|
3013 |
|
|
targetm.asm_out.globalize_label (asm_out_file,
|
3014 |
|
|
IDENTIFIER_POINTER (label));
|
3015 |
|
|
ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
|
3016 |
|
|
}
|
3017 |
|
|
}
|
3018 |
|
|
}
|
3019 |
|
|
|
3020 |
|
|
/* Switch [BACK] to the eh or debug frame table section, depending on
|
3021 |
|
|
FOR_EH. */
|
3022 |
|
|
|
3023 |
|
|
static void
|
3024 |
|
|
switch_to_frame_table_section (int for_eh, bool back)
|
3025 |
|
|
{
|
3026 |
|
|
if (for_eh)
|
3027 |
|
|
switch_to_eh_frame_section (back);
|
3028 |
|
|
else
|
3029 |
|
|
{
|
3030 |
|
|
if (!debug_frame_section)
|
3031 |
|
|
debug_frame_section = get_section (DEBUG_FRAME_SECTION,
|
3032 |
|
|
SECTION_DEBUG, NULL);
|
3033 |
|
|
switch_to_section (debug_frame_section);
|
3034 |
|
|
}
|
3035 |
|
|
}
|
3036 |
|
|
|
3037 |
|
|
/* Output a Call Frame Information opcode and its operand(s). */
|
3038 |
|
|
|
3039 |
|
|
static void
|
3040 |
|
|
output_cfi (dw_cfi_ref cfi, dw_fde_ref fde, int for_eh)
|
3041 |
|
|
{
|
3042 |
|
|
unsigned long r;
|
3043 |
|
|
HOST_WIDE_INT off;
|
3044 |
|
|
|
3045 |
|
|
if (cfi->dw_cfi_opc == DW_CFA_advance_loc)
|
3046 |
|
|
dw2_asm_output_data (1, (cfi->dw_cfi_opc
|
3047 |
|
|
| (cfi->dw_cfi_oprnd1.dw_cfi_offset & 0x3f)),
|
3048 |
|
|
"DW_CFA_advance_loc " HOST_WIDE_INT_PRINT_HEX,
|
3049 |
|
|
((unsigned HOST_WIDE_INT)
|
3050 |
|
|
cfi->dw_cfi_oprnd1.dw_cfi_offset));
|
3051 |
|
|
else if (cfi->dw_cfi_opc == DW_CFA_offset)
|
3052 |
|
|
{
|
3053 |
|
|
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
|
3054 |
|
|
dw2_asm_output_data (1, (cfi->dw_cfi_opc | (r & 0x3f)),
|
3055 |
|
|
"DW_CFA_offset, column 0x%lx", r);
|
3056 |
|
|
off = div_data_align (cfi->dw_cfi_oprnd2.dw_cfi_offset);
|
3057 |
|
|
dw2_asm_output_data_uleb128 (off, NULL);
|
3058 |
|
|
}
|
3059 |
|
|
else if (cfi->dw_cfi_opc == DW_CFA_restore)
|
3060 |
|
|
{
|
3061 |
|
|
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
|
3062 |
|
|
dw2_asm_output_data (1, (cfi->dw_cfi_opc | (r & 0x3f)),
|
3063 |
|
|
"DW_CFA_restore, column 0x%lx", r);
|
3064 |
|
|
}
|
3065 |
|
|
else
|
3066 |
|
|
{
|
3067 |
|
|
dw2_asm_output_data (1, cfi->dw_cfi_opc,
|
3068 |
|
|
"%s", dwarf_cfi_name (cfi->dw_cfi_opc));
|
3069 |
|
|
|
3070 |
|
|
switch (cfi->dw_cfi_opc)
|
3071 |
|
|
{
|
3072 |
|
|
case DW_CFA_set_loc:
|
3073 |
|
|
if (for_eh)
|
3074 |
|
|
dw2_asm_output_encoded_addr_rtx (
|
3075 |
|
|
ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/1, /*global=*/0),
|
3076 |
|
|
gen_rtx_SYMBOL_REF (Pmode, cfi->dw_cfi_oprnd1.dw_cfi_addr),
|
3077 |
|
|
false, NULL);
|
3078 |
|
|
else
|
3079 |
|
|
dw2_asm_output_addr (DWARF2_ADDR_SIZE,
|
3080 |
|
|
cfi->dw_cfi_oprnd1.dw_cfi_addr, NULL);
|
3081 |
|
|
fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
|
3082 |
|
|
break;
|
3083 |
|
|
|
3084 |
|
|
case DW_CFA_advance_loc1:
|
3085 |
|
|
dw2_asm_output_delta (1, cfi->dw_cfi_oprnd1.dw_cfi_addr,
|
3086 |
|
|
fde->dw_fde_current_label, NULL);
|
3087 |
|
|
fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
|
3088 |
|
|
break;
|
3089 |
|
|
|
3090 |
|
|
case DW_CFA_advance_loc2:
|
3091 |
|
|
dw2_asm_output_delta (2, cfi->dw_cfi_oprnd1.dw_cfi_addr,
|
3092 |
|
|
fde->dw_fde_current_label, NULL);
|
3093 |
|
|
fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
|
3094 |
|
|
break;
|
3095 |
|
|
|
3096 |
|
|
case DW_CFA_advance_loc4:
|
3097 |
|
|
dw2_asm_output_delta (4, cfi->dw_cfi_oprnd1.dw_cfi_addr,
|
3098 |
|
|
fde->dw_fde_current_label, NULL);
|
3099 |
|
|
fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
|
3100 |
|
|
break;
|
3101 |
|
|
|
3102 |
|
|
case DW_CFA_MIPS_advance_loc8:
|
3103 |
|
|
dw2_asm_output_delta (8, cfi->dw_cfi_oprnd1.dw_cfi_addr,
|
3104 |
|
|
fde->dw_fde_current_label, NULL);
|
3105 |
|
|
fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
|
3106 |
|
|
break;
|
3107 |
|
|
|
3108 |
|
|
case DW_CFA_offset_extended:
|
3109 |
|
|
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
|
3110 |
|
|
dw2_asm_output_data_uleb128 (r, NULL);
|
3111 |
|
|
off = div_data_align (cfi->dw_cfi_oprnd2.dw_cfi_offset);
|
3112 |
|
|
dw2_asm_output_data_uleb128 (off, NULL);
|
3113 |
|
|
break;
|
3114 |
|
|
|
3115 |
|
|
case DW_CFA_def_cfa:
|
3116 |
|
|
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
|
3117 |
|
|
dw2_asm_output_data_uleb128 (r, NULL);
|
3118 |
|
|
dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset, NULL);
|
3119 |
|
|
break;
|
3120 |
|
|
|
3121 |
|
|
case DW_CFA_offset_extended_sf:
|
3122 |
|
|
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
|
3123 |
|
|
dw2_asm_output_data_uleb128 (r, NULL);
|
3124 |
|
|
off = div_data_align (cfi->dw_cfi_oprnd2.dw_cfi_offset);
|
3125 |
|
|
dw2_asm_output_data_sleb128 (off, NULL);
|
3126 |
|
|
break;
|
3127 |
|
|
|
3128 |
|
|
case DW_CFA_def_cfa_sf:
|
3129 |
|
|
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
|
3130 |
|
|
dw2_asm_output_data_uleb128 (r, NULL);
|
3131 |
|
|
off = div_data_align (cfi->dw_cfi_oprnd2.dw_cfi_offset);
|
3132 |
|
|
dw2_asm_output_data_sleb128 (off, NULL);
|
3133 |
|
|
break;
|
3134 |
|
|
|
3135 |
|
|
case DW_CFA_restore_extended:
|
3136 |
|
|
case DW_CFA_undefined:
|
3137 |
|
|
case DW_CFA_same_value:
|
3138 |
|
|
case DW_CFA_def_cfa_register:
|
3139 |
|
|
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
|
3140 |
|
|
dw2_asm_output_data_uleb128 (r, NULL);
|
3141 |
|
|
break;
|
3142 |
|
|
|
3143 |
|
|
case DW_CFA_register:
|
3144 |
|
|
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
|
3145 |
|
|
dw2_asm_output_data_uleb128 (r, NULL);
|
3146 |
|
|
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd2.dw_cfi_reg_num, for_eh);
|
3147 |
|
|
dw2_asm_output_data_uleb128 (r, NULL);
|
3148 |
|
|
break;
|
3149 |
|
|
|
3150 |
|
|
case DW_CFA_def_cfa_offset:
|
3151 |
|
|
case DW_CFA_GNU_args_size:
|
3152 |
|
|
dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset, NULL);
|
3153 |
|
|
break;
|
3154 |
|
|
|
3155 |
|
|
case DW_CFA_def_cfa_offset_sf:
|
3156 |
|
|
off = div_data_align (cfi->dw_cfi_oprnd1.dw_cfi_offset);
|
3157 |
|
|
dw2_asm_output_data_sleb128 (off, NULL);
|
3158 |
|
|
break;
|
3159 |
|
|
|
3160 |
|
|
case DW_CFA_GNU_window_save:
|
3161 |
|
|
break;
|
3162 |
|
|
|
3163 |
|
|
case DW_CFA_def_cfa_expression:
|
3164 |
|
|
case DW_CFA_expression:
|
3165 |
|
|
output_cfa_loc (cfi);
|
3166 |
|
|
break;
|
3167 |
|
|
|
3168 |
|
|
case DW_CFA_GNU_negative_offset_extended:
|
3169 |
|
|
/* Obsoleted by DW_CFA_offset_extended_sf. */
|
3170 |
|
|
gcc_unreachable ();
|
3171 |
|
|
|
3172 |
|
|
default:
|
3173 |
|
|
break;
|
3174 |
|
|
}
|
3175 |
|
|
}
|
3176 |
|
|
}
|
3177 |
|
|
|
3178 |
|
|
/* Similar, but do it via assembler directives instead. */
|
3179 |
|
|
|
3180 |
|
|
static void
|
3181 |
|
|
output_cfi_directive (dw_cfi_ref cfi)
|
3182 |
|
|
{
|
3183 |
|
|
unsigned long r, r2;
|
3184 |
|
|
|
3185 |
|
|
switch (cfi->dw_cfi_opc)
|
3186 |
|
|
{
|
3187 |
|
|
case DW_CFA_advance_loc:
|
3188 |
|
|
case DW_CFA_advance_loc1:
|
3189 |
|
|
case DW_CFA_advance_loc2:
|
3190 |
|
|
case DW_CFA_advance_loc4:
|
3191 |
|
|
case DW_CFA_MIPS_advance_loc8:
|
3192 |
|
|
case DW_CFA_set_loc:
|
3193 |
|
|
/* Should only be created by add_fde_cfi in a code path not
|
3194 |
|
|
followed when emitting via directives. The assembler is
|
3195 |
|
|
going to take care of this for us. */
|
3196 |
|
|
gcc_unreachable ();
|
3197 |
|
|
|
3198 |
|
|
case DW_CFA_offset:
|
3199 |
|
|
case DW_CFA_offset_extended:
|
3200 |
|
|
case DW_CFA_offset_extended_sf:
|
3201 |
|
|
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
|
3202 |
|
|
fprintf (asm_out_file, "\t.cfi_offset %lu, "HOST_WIDE_INT_PRINT_DEC"\n",
|
3203 |
|
|
r, cfi->dw_cfi_oprnd2.dw_cfi_offset);
|
3204 |
|
|
break;
|
3205 |
|
|
|
3206 |
|
|
case DW_CFA_restore:
|
3207 |
|
|
case DW_CFA_restore_extended:
|
3208 |
|
|
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
|
3209 |
|
|
fprintf (asm_out_file, "\t.cfi_restore %lu\n", r);
|
3210 |
|
|
break;
|
3211 |
|
|
|
3212 |
|
|
case DW_CFA_undefined:
|
3213 |
|
|
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
|
3214 |
|
|
fprintf (asm_out_file, "\t.cfi_undefined %lu\n", r);
|
3215 |
|
|
break;
|
3216 |
|
|
|
3217 |
|
|
case DW_CFA_same_value:
|
3218 |
|
|
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
|
3219 |
|
|
fprintf (asm_out_file, "\t.cfi_same_value %lu\n", r);
|
3220 |
|
|
break;
|
3221 |
|
|
|
3222 |
|
|
case DW_CFA_def_cfa:
|
3223 |
|
|
case DW_CFA_def_cfa_sf:
|
3224 |
|
|
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
|
3225 |
|
|
fprintf (asm_out_file, "\t.cfi_def_cfa %lu, "HOST_WIDE_INT_PRINT_DEC"\n",
|
3226 |
|
|
r, cfi->dw_cfi_oprnd2.dw_cfi_offset);
|
3227 |
|
|
break;
|
3228 |
|
|
|
3229 |
|
|
case DW_CFA_def_cfa_register:
|
3230 |
|
|
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
|
3231 |
|
|
fprintf (asm_out_file, "\t.cfi_def_cfa_register %lu\n", r);
|
3232 |
|
|
break;
|
3233 |
|
|
|
3234 |
|
|
case DW_CFA_register:
|
3235 |
|
|
r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
|
3236 |
|
|
r2 = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd2.dw_cfi_reg_num, 1);
|
3237 |
|
|
fprintf (asm_out_file, "\t.cfi_register %lu, %lu\n", r, r2);
|
3238 |
|
|
break;
|
3239 |
|
|
|
3240 |
|
|
case DW_CFA_def_cfa_offset:
|
3241 |
|
|
case DW_CFA_def_cfa_offset_sf:
|
3242 |
|
|
fprintf (asm_out_file, "\t.cfi_def_cfa_offset "
|
3243 |
|
|
HOST_WIDE_INT_PRINT_DEC"\n",
|
3244 |
|
|
cfi->dw_cfi_oprnd1.dw_cfi_offset);
|
3245 |
|
|
break;
|
3246 |
|
|
|
3247 |
|
|
case DW_CFA_remember_state:
|
3248 |
|
|
fprintf (asm_out_file, "\t.cfi_remember_state\n");
|
3249 |
|
|
break;
|
3250 |
|
|
case DW_CFA_restore_state:
|
3251 |
|
|
fprintf (asm_out_file, "\t.cfi_restore_state\n");
|
3252 |
|
|
break;
|
3253 |
|
|
|
3254 |
|
|
case DW_CFA_GNU_args_size:
|
3255 |
|
|
fprintf (asm_out_file, "\t.cfi_escape 0x%x,", DW_CFA_GNU_args_size);
|
3256 |
|
|
dw2_asm_output_data_uleb128_raw (cfi->dw_cfi_oprnd1.dw_cfi_offset);
|
3257 |
|
|
if (flag_debug_asm)
|
3258 |
|
|
fprintf (asm_out_file, "\t%s args_size "HOST_WIDE_INT_PRINT_DEC,
|
3259 |
|
|
ASM_COMMENT_START, cfi->dw_cfi_oprnd1.dw_cfi_offset);
|
3260 |
|
|
fputc ('\n', asm_out_file);
|
3261 |
|
|
break;
|
3262 |
|
|
|
3263 |
|
|
case DW_CFA_GNU_window_save:
|
3264 |
|
|
fprintf (asm_out_file, "\t.cfi_window_save\n");
|
3265 |
|
|
break;
|
3266 |
|
|
|
3267 |
|
|
case DW_CFA_def_cfa_expression:
|
3268 |
|
|
case DW_CFA_expression:
|
3269 |
|
|
fprintf (asm_out_file, "\t.cfi_escape 0x%x,", cfi->dw_cfi_opc);
|
3270 |
|
|
output_cfa_loc_raw (cfi);
|
3271 |
|
|
fputc ('\n', asm_out_file);
|
3272 |
|
|
break;
|
3273 |
|
|
|
3274 |
|
|
default:
|
3275 |
|
|
gcc_unreachable ();
|
3276 |
|
|
}
|
3277 |
|
|
}
|
3278 |
|
|
|
3279 |
|
|
DEF_VEC_P (dw_cfi_ref);
|
3280 |
|
|
DEF_VEC_ALLOC_P (dw_cfi_ref, heap);
|
3281 |
|
|
|
3282 |
|
|
/* Output CFIs to bring current FDE to the same state as after executing
|
3283 |
|
|
CFIs in CFI chain. DO_CFI_ASM is true if .cfi_* directives shall
|
3284 |
|
|
be emitted, false otherwise. If it is false, FDE and FOR_EH are the
|
3285 |
|
|
other arguments to pass to output_cfi. */
|
3286 |
|
|
|
3287 |
|
|
static void
|
3288 |
|
|
output_cfis (dw_cfi_ref cfi, bool do_cfi_asm, dw_fde_ref fde, bool for_eh)
|
3289 |
|
|
{
|
3290 |
|
|
struct dw_cfi_struct cfi_buf;
|
3291 |
|
|
dw_cfi_ref cfi2;
|
3292 |
|
|
dw_cfi_ref cfi_args_size = NULL, cfi_cfa = NULL, cfi_cfa_offset = NULL;
|
3293 |
|
|
VEC (dw_cfi_ref, heap) *regs = VEC_alloc (dw_cfi_ref, heap, 32);
|
3294 |
|
|
unsigned int len, idx;
|
3295 |
|
|
|
3296 |
|
|
for (;; cfi = cfi->dw_cfi_next)
|
3297 |
|
|
switch (cfi ? cfi->dw_cfi_opc : DW_CFA_nop)
|
3298 |
|
|
{
|
3299 |
|
|
case DW_CFA_advance_loc:
|
3300 |
|
|
case DW_CFA_advance_loc1:
|
3301 |
|
|
case DW_CFA_advance_loc2:
|
3302 |
|
|
case DW_CFA_advance_loc4:
|
3303 |
|
|
case DW_CFA_MIPS_advance_loc8:
|
3304 |
|
|
case DW_CFA_set_loc:
|
3305 |
|
|
/* All advances should be ignored. */
|
3306 |
|
|
break;
|
3307 |
|
|
case DW_CFA_remember_state:
|
3308 |
|
|
{
|
3309 |
|
|
dw_cfi_ref args_size = cfi_args_size;
|
3310 |
|
|
|
3311 |
|
|
/* Skip everything between .cfi_remember_state and
|
3312 |
|
|
.cfi_restore_state. */
|
3313 |
|
|
for (cfi2 = cfi->dw_cfi_next; cfi2; cfi2 = cfi2->dw_cfi_next)
|
3314 |
|
|
if (cfi2->dw_cfi_opc == DW_CFA_restore_state)
|
3315 |
|
|
break;
|
3316 |
|
|
else if (cfi2->dw_cfi_opc == DW_CFA_GNU_args_size)
|
3317 |
|
|
args_size = cfi2;
|
3318 |
|
|
else
|
3319 |
|
|
gcc_assert (cfi2->dw_cfi_opc != DW_CFA_remember_state);
|
3320 |
|
|
|
3321 |
|
|
if (cfi2 == NULL)
|
3322 |
|
|
goto flush_all;
|
3323 |
|
|
else
|
3324 |
|
|
{
|
3325 |
|
|
cfi = cfi2;
|
3326 |
|
|
cfi_args_size = args_size;
|
3327 |
|
|
}
|
3328 |
|
|
break;
|
3329 |
|
|
}
|
3330 |
|
|
case DW_CFA_GNU_args_size:
|
3331 |
|
|
cfi_args_size = cfi;
|
3332 |
|
|
break;
|
3333 |
|
|
case DW_CFA_GNU_window_save:
|
3334 |
|
|
goto flush_all;
|
3335 |
|
|
case DW_CFA_offset:
|
3336 |
|
|
case DW_CFA_offset_extended:
|
3337 |
|
|
case DW_CFA_offset_extended_sf:
|
3338 |
|
|
case DW_CFA_restore:
|
3339 |
|
|
case DW_CFA_restore_extended:
|
3340 |
|
|
case DW_CFA_undefined:
|
3341 |
|
|
case DW_CFA_same_value:
|
3342 |
|
|
case DW_CFA_register:
|
3343 |
|
|
case DW_CFA_val_offset:
|
3344 |
|
|
case DW_CFA_val_offset_sf:
|
3345 |
|
|
case DW_CFA_expression:
|
3346 |
|
|
case DW_CFA_val_expression:
|
3347 |
|
|
case DW_CFA_GNU_negative_offset_extended:
|
3348 |
|
|
if (VEC_length (dw_cfi_ref, regs) <= cfi->dw_cfi_oprnd1.dw_cfi_reg_num)
|
3349 |
|
|
VEC_safe_grow_cleared (dw_cfi_ref, heap, regs,
|
3350 |
|
|
cfi->dw_cfi_oprnd1.dw_cfi_reg_num + 1);
|
3351 |
|
|
VEC_replace (dw_cfi_ref, regs, cfi->dw_cfi_oprnd1.dw_cfi_reg_num, cfi);
|
3352 |
|
|
break;
|
3353 |
|
|
case DW_CFA_def_cfa:
|
3354 |
|
|
case DW_CFA_def_cfa_sf:
|
3355 |
|
|
case DW_CFA_def_cfa_expression:
|
3356 |
|
|
cfi_cfa = cfi;
|
3357 |
|
|
cfi_cfa_offset = cfi;
|
3358 |
|
|
break;
|
3359 |
|
|
case DW_CFA_def_cfa_register:
|
3360 |
|
|
cfi_cfa = cfi;
|
3361 |
|
|
break;
|
3362 |
|
|
case DW_CFA_def_cfa_offset:
|
3363 |
|
|
case DW_CFA_def_cfa_offset_sf:
|
3364 |
|
|
cfi_cfa_offset = cfi;
|
3365 |
|
|
break;
|
3366 |
|
|
case DW_CFA_nop:
|
3367 |
|
|
gcc_assert (cfi == NULL);
|
3368 |
|
|
flush_all:
|
3369 |
|
|
len = VEC_length (dw_cfi_ref, regs);
|
3370 |
|
|
for (idx = 0; idx < len; idx++)
|
3371 |
|
|
{
|
3372 |
|
|
cfi2 = VEC_replace (dw_cfi_ref, regs, idx, NULL);
|
3373 |
|
|
if (cfi2 != NULL
|
3374 |
|
|
&& cfi2->dw_cfi_opc != DW_CFA_restore
|
3375 |
|
|
&& cfi2->dw_cfi_opc != DW_CFA_restore_extended)
|
3376 |
|
|
{
|
3377 |
|
|
if (do_cfi_asm)
|
3378 |
|
|
output_cfi_directive (cfi2);
|
3379 |
|
|
else
|
3380 |
|
|
output_cfi (cfi2, fde, for_eh);
|
3381 |
|
|
}
|
3382 |
|
|
}
|
3383 |
|
|
if (cfi_cfa && cfi_cfa_offset && cfi_cfa_offset != cfi_cfa)
|
3384 |
|
|
{
|
3385 |
|
|
gcc_assert (cfi_cfa->dw_cfi_opc != DW_CFA_def_cfa_expression);
|
3386 |
|
|
cfi_buf = *cfi_cfa;
|
3387 |
|
|
switch (cfi_cfa_offset->dw_cfi_opc)
|
3388 |
|
|
{
|
3389 |
|
|
case DW_CFA_def_cfa_offset:
|
3390 |
|
|
cfi_buf.dw_cfi_opc = DW_CFA_def_cfa;
|
3391 |
|
|
cfi_buf.dw_cfi_oprnd2 = cfi_cfa_offset->dw_cfi_oprnd1;
|
3392 |
|
|
break;
|
3393 |
|
|
case DW_CFA_def_cfa_offset_sf:
|
3394 |
|
|
cfi_buf.dw_cfi_opc = DW_CFA_def_cfa_sf;
|
3395 |
|
|
cfi_buf.dw_cfi_oprnd2 = cfi_cfa_offset->dw_cfi_oprnd1;
|
3396 |
|
|
break;
|
3397 |
|
|
case DW_CFA_def_cfa:
|
3398 |
|
|
case DW_CFA_def_cfa_sf:
|
3399 |
|
|
cfi_buf.dw_cfi_opc = cfi_cfa_offset->dw_cfi_opc;
|
3400 |
|
|
cfi_buf.dw_cfi_oprnd2 = cfi_cfa_offset->dw_cfi_oprnd2;
|
3401 |
|
|
break;
|
3402 |
|
|
default:
|
3403 |
|
|
gcc_unreachable ();
|
3404 |
|
|
}
|
3405 |
|
|
cfi_cfa = &cfi_buf;
|
3406 |
|
|
}
|
3407 |
|
|
else if (cfi_cfa_offset)
|
3408 |
|
|
cfi_cfa = cfi_cfa_offset;
|
3409 |
|
|
if (cfi_cfa)
|
3410 |
|
|
{
|
3411 |
|
|
if (do_cfi_asm)
|
3412 |
|
|
output_cfi_directive (cfi_cfa);
|
3413 |
|
|
else
|
3414 |
|
|
output_cfi (cfi_cfa, fde, for_eh);
|
3415 |
|
|
}
|
3416 |
|
|
cfi_cfa = NULL;
|
3417 |
|
|
cfi_cfa_offset = NULL;
|
3418 |
|
|
if (cfi_args_size
|
3419 |
|
|
&& cfi_args_size->dw_cfi_oprnd1.dw_cfi_offset)
|
3420 |
|
|
{
|
3421 |
|
|
if (do_cfi_asm)
|
3422 |
|
|
output_cfi_directive (cfi_args_size);
|
3423 |
|
|
else
|
3424 |
|
|
output_cfi (cfi_args_size, fde, for_eh);
|
3425 |
|
|
}
|
3426 |
|
|
cfi_args_size = NULL;
|
3427 |
|
|
if (cfi == NULL)
|
3428 |
|
|
{
|
3429 |
|
|
VEC_free (dw_cfi_ref, heap, regs);
|
3430 |
|
|
return;
|
3431 |
|
|
}
|
3432 |
|
|
else if (do_cfi_asm)
|
3433 |
|
|
output_cfi_directive (cfi);
|
3434 |
|
|
else
|
3435 |
|
|
output_cfi (cfi, fde, for_eh);
|
3436 |
|
|
break;
|
3437 |
|
|
default:
|
3438 |
|
|
gcc_unreachable ();
|
3439 |
|
|
}
|
3440 |
|
|
}
|
3441 |
|
|
|
3442 |
|
|
/* Output one FDE. */
|
3443 |
|
|
|
3444 |
|
|
static void
|
3445 |
|
|
output_fde (dw_fde_ref fde, bool for_eh, bool second,
|
3446 |
|
|
char *section_start_label, int fde_encoding, char *augmentation,
|
3447 |
|
|
bool any_lsda_needed, int lsda_encoding)
|
3448 |
|
|
{
|
3449 |
|
|
const char *begin, *end;
|
3450 |
|
|
static unsigned int j;
|
3451 |
|
|
char l1[20], l2[20];
|
3452 |
|
|
dw_cfi_ref cfi;
|
3453 |
|
|
|
3454 |
|
|
targetm.asm_out.unwind_label (asm_out_file, fde->decl, for_eh,
|
3455 |
|
|
/* empty */ 0);
|
3456 |
|
|
targetm.asm_out.internal_label (asm_out_file, FDE_LABEL,
|
3457 |
|
|
for_eh + j);
|
3458 |
|
|
ASM_GENERATE_INTERNAL_LABEL (l1, FDE_AFTER_SIZE_LABEL, for_eh + j);
|
3459 |
|
|
ASM_GENERATE_INTERNAL_LABEL (l2, FDE_END_LABEL, for_eh + j);
|
3460 |
|
|
if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4 && !for_eh)
|
3461 |
|
|
dw2_asm_output_data (4, 0xffffffff, "Initial length escape value"
|
3462 |
|
|
" indicating 64-bit DWARF extension");
|
3463 |
|
|
dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1,
|
3464 |
|
|
"FDE Length");
|
3465 |
|
|
ASM_OUTPUT_LABEL (asm_out_file, l1);
|
3466 |
|
|
|
3467 |
|
|
if (for_eh)
|
3468 |
|
|
dw2_asm_output_delta (4, l1, section_start_label, "FDE CIE offset");
|
3469 |
|
|
else
|
3470 |
|
|
dw2_asm_output_offset (DWARF_OFFSET_SIZE, section_start_label,
|
3471 |
|
|
debug_frame_section, "FDE CIE offset");
|
3472 |
|
|
|
3473 |
|
|
if (!fde->dw_fde_switched_sections)
|
3474 |
|
|
{
|
3475 |
|
|
begin = fde->dw_fde_begin;
|
3476 |
|
|
end = fde->dw_fde_end;
|
3477 |
|
|
}
|
3478 |
|
|
else
|
3479 |
|
|
{
|
3480 |
|
|
/* For the first section, prefer dw_fde_begin over
|
3481 |
|
|
dw_fde_{hot,cold}_section_label, as the latter
|
3482 |
|
|
might be separated from the real start of the
|
3483 |
|
|
function by alignment padding. */
|
3484 |
|
|
if (!second)
|
3485 |
|
|
begin = fde->dw_fde_begin;
|
3486 |
|
|
else if (fde->dw_fde_switched_cold_to_hot)
|
3487 |
|
|
begin = fde->dw_fde_hot_section_label;
|
3488 |
|
|
else
|
3489 |
|
|
begin = fde->dw_fde_unlikely_section_label;
|
3490 |
|
|
if (second ^ fde->dw_fde_switched_cold_to_hot)
|
3491 |
|
|
end = fde->dw_fde_unlikely_section_end_label;
|
3492 |
|
|
else
|
3493 |
|
|
end = fde->dw_fde_hot_section_end_label;
|
3494 |
|
|
}
|
3495 |
|
|
|
3496 |
|
|
if (for_eh)
|
3497 |
|
|
{
|
3498 |
|
|
rtx sym_ref = gen_rtx_SYMBOL_REF (Pmode, begin);
|
3499 |
|
|
SYMBOL_REF_FLAGS (sym_ref) |= SYMBOL_FLAG_LOCAL;
|
3500 |
|
|
dw2_asm_output_encoded_addr_rtx (fde_encoding, sym_ref, false,
|
3501 |
|
|
"FDE initial location");
|
3502 |
|
|
dw2_asm_output_delta (size_of_encoded_value (fde_encoding),
|
3503 |
|
|
end, begin, "FDE address range");
|
3504 |
|
|
}
|
3505 |
|
|
else
|
3506 |
|
|
{
|
3507 |
|
|
dw2_asm_output_addr (DWARF2_ADDR_SIZE, begin, "FDE initial location");
|
3508 |
|
|
dw2_asm_output_delta (DWARF2_ADDR_SIZE, end, begin, "FDE address range");
|
3509 |
|
|
}
|
3510 |
|
|
|
3511 |
|
|
if (augmentation[0])
|
3512 |
|
|
{
|
3513 |
|
|
if (any_lsda_needed)
|
3514 |
|
|
{
|
3515 |
|
|
int size = size_of_encoded_value (lsda_encoding);
|
3516 |
|
|
|
3517 |
|
|
if (lsda_encoding == DW_EH_PE_aligned)
|
3518 |
|
|
{
|
3519 |
|
|
int offset = ( 4 /* Length */
|
3520 |
|
|
+ 4 /* CIE offset */
|
3521 |
|
|
+ 2 * size_of_encoded_value (fde_encoding)
|
3522 |
|
|
+ 1 /* Augmentation size */ );
|
3523 |
|
|
int pad = -offset & (PTR_SIZE - 1);
|
3524 |
|
|
|
3525 |
|
|
size += pad;
|
3526 |
|
|
gcc_assert (size_of_uleb128 (size) == 1);
|
3527 |
|
|
}
|
3528 |
|
|
|
3529 |
|
|
dw2_asm_output_data_uleb128 (size, "Augmentation size");
|
3530 |
|
|
|
3531 |
|
|
if (fde->uses_eh_lsda)
|
3532 |
|
|
{
|
3533 |
|
|
ASM_GENERATE_INTERNAL_LABEL (l1, second ? "LLSDAC" : "LLSDA",
|
3534 |
|
|
fde->funcdef_number);
|
3535 |
|
|
dw2_asm_output_encoded_addr_rtx (lsda_encoding,
|
3536 |
|
|
gen_rtx_SYMBOL_REF (Pmode, l1),
|
3537 |
|
|
false,
|
3538 |
|
|
"Language Specific Data Area");
|
3539 |
|
|
}
|
3540 |
|
|
else
|
3541 |
|
|
{
|
3542 |
|
|
if (lsda_encoding == DW_EH_PE_aligned)
|
3543 |
|
|
ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE));
|
3544 |
|
|
dw2_asm_output_data (size_of_encoded_value (lsda_encoding), 0,
|
3545 |
|
|
"Language Specific Data Area (none)");
|
3546 |
|
|
}
|
3547 |
|
|
}
|
3548 |
|
|
else
|
3549 |
|
|
dw2_asm_output_data_uleb128 (0, "Augmentation size");
|
3550 |
|
|
}
|
3551 |
|
|
|
3552 |
|
|
/* Loop through the Call Frame Instructions associated with
|
3553 |
|
|
this FDE. */
|
3554 |
|
|
fde->dw_fde_current_label = begin;
|
3555 |
|
|
if (!fde->dw_fde_switched_sections)
|
3556 |
|
|
for (cfi = fde->dw_fde_cfi; cfi != NULL; cfi = cfi->dw_cfi_next)
|
3557 |
|
|
output_cfi (cfi, fde, for_eh);
|
3558 |
|
|
else if (!second)
|
3559 |
|
|
{
|
3560 |
|
|
if (fde->dw_fde_switch_cfi)
|
3561 |
|
|
for (cfi = fde->dw_fde_cfi; cfi != NULL; cfi = cfi->dw_cfi_next)
|
3562 |
|
|
{
|
3563 |
|
|
output_cfi (cfi, fde, for_eh);
|
3564 |
|
|
if (cfi == fde->dw_fde_switch_cfi)
|
3565 |
|
|
break;
|
3566 |
|
|
}
|
3567 |
|
|
}
|
3568 |
|
|
else
|
3569 |
|
|
{
|
3570 |
|
|
dw_cfi_ref cfi_next = fde->dw_fde_cfi;
|
3571 |
|
|
|
3572 |
|
|
if (fde->dw_fde_switch_cfi)
|
3573 |
|
|
{
|
3574 |
|
|
cfi_next = fde->dw_fde_switch_cfi->dw_cfi_next;
|
3575 |
|
|
fde->dw_fde_switch_cfi->dw_cfi_next = NULL;
|
3576 |
|
|
output_cfis (fde->dw_fde_cfi, false, fde, for_eh);
|
3577 |
|
|
fde->dw_fde_switch_cfi->dw_cfi_next = cfi_next;
|
3578 |
|
|
}
|
3579 |
|
|
for (cfi = cfi_next; cfi != NULL; cfi = cfi->dw_cfi_next)
|
3580 |
|
|
output_cfi (cfi, fde, for_eh);
|
3581 |
|
|
}
|
3582 |
|
|
|
3583 |
|
|
/* If we are to emit a ref/link from function bodies to their frame tables,
|
3584 |
|
|
do it now. This is typically performed to make sure that tables
|
3585 |
|
|
associated with functions are dragged with them and not discarded in
|
3586 |
|
|
garbage collecting links. We need to do this on a per function basis to
|
3587 |
|
|
cope with -ffunction-sections. */
|
3588 |
|
|
|
3589 |
|
|
#ifdef ASM_OUTPUT_DWARF_TABLE_REF
|
3590 |
|
|
/* Switch to the function section, emit the ref to the tables, and
|
3591 |
|
|
switch *back* into the table section. */
|
3592 |
|
|
switch_to_section (function_section (fde->decl));
|
3593 |
|
|
ASM_OUTPUT_DWARF_TABLE_REF (section_start_label);
|
3594 |
|
|
switch_to_frame_table_section (for_eh, true);
|
3595 |
|
|
#endif
|
3596 |
|
|
|
3597 |
|
|
/* Pad the FDE out to an address sized boundary. */
|
3598 |
|
|
ASM_OUTPUT_ALIGN (asm_out_file,
|
3599 |
|
|
floor_log2 ((for_eh ? PTR_SIZE : DWARF2_ADDR_SIZE)));
|
3600 |
|
|
ASM_OUTPUT_LABEL (asm_out_file, l2);
|
3601 |
|
|
|
3602 |
|
|
j += 2;
|
3603 |
|
|
}
|
3604 |
|
|
|
3605 |
|
|
/* Output the call frame information used to record information
|
3606 |
|
|
that relates to calculating the frame pointer, and records the
|
3607 |
|
|
location of saved registers. */
|
3608 |
|
|
|
3609 |
|
|
static void
|
3610 |
|
|
output_call_frame_info (int for_eh)
|
3611 |
|
|
{
|
3612 |
|
|
unsigned int i;
|
3613 |
|
|
dw_fde_ref fde;
|
3614 |
|
|
dw_cfi_ref cfi;
|
3615 |
|
|
char l1[20], l2[20], section_start_label[20];
|
3616 |
|
|
bool any_lsda_needed = false;
|
3617 |
|
|
char augmentation[6];
|
3618 |
|
|
int augmentation_size;
|
3619 |
|
|
int fde_encoding = DW_EH_PE_absptr;
|
3620 |
|
|
int per_encoding = DW_EH_PE_absptr;
|
3621 |
|
|
int lsda_encoding = DW_EH_PE_absptr;
|
3622 |
|
|
int return_reg;
|
3623 |
|
|
rtx personality = NULL;
|
3624 |
|
|
int dw_cie_version;
|
3625 |
|
|
|
3626 |
|
|
/* Don't emit a CIE if there won't be any FDEs. */
|
3627 |
|
|
if (fde_table_in_use == 0)
|
3628 |
|
|
return;
|
3629 |
|
|
|
3630 |
|
|
/* Nothing to do if the assembler's doing it all. */
|
3631 |
|
|
if (dwarf2out_do_cfi_asm ())
|
3632 |
|
|
return;
|
3633 |
|
|
|
3634 |
|
|
/* If we make FDEs linkonce, we may have to emit an empty label for
|
3635 |
|
|
an FDE that wouldn't otherwise be emitted. We want to avoid
|
3636 |
|
|
having an FDE kept around when the function it refers to is
|
3637 |
|
|
discarded. Example where this matters: a primary function
|
3638 |
|
|
template in C++ requires EH information, but an explicit
|
3639 |
|
|
specialization doesn't. */
|
3640 |
|
|
if (TARGET_USES_WEAK_UNWIND_INFO
|
3641 |
|
|
&& ! flag_asynchronous_unwind_tables
|
3642 |
|
|
&& flag_exceptions
|
3643 |
|
|
&& for_eh)
|
3644 |
|
|
for (i = 0; i < fde_table_in_use; i++)
|
3645 |
|
|
if ((fde_table[i].nothrow || fde_table[i].all_throwers_are_sibcalls)
|
3646 |
|
|
&& !fde_table[i].uses_eh_lsda
|
3647 |
|
|
&& ! DECL_WEAK (fde_table[i].decl))
|
3648 |
|
|
targetm.asm_out.unwind_label (asm_out_file, fde_table[i].decl,
|
3649 |
|
|
for_eh, /* empty */ 1);
|
3650 |
|
|
|
3651 |
|
|
/* If we don't have any functions we'll want to unwind out of, don't
|
3652 |
|
|
emit any EH unwind information. Note that if exceptions aren't
|
3653 |
|
|
enabled, we won't have collected nothrow information, and if we
|
3654 |
|
|
asked for asynchronous tables, we always want this info. */
|
3655 |
|
|
if (for_eh)
|
3656 |
|
|
{
|
3657 |
|
|
bool any_eh_needed = !flag_exceptions || flag_asynchronous_unwind_tables;
|
3658 |
|
|
|
3659 |
|
|
for (i = 0; i < fde_table_in_use; i++)
|
3660 |
|
|
if (fde_table[i].uses_eh_lsda)
|
3661 |
|
|
any_eh_needed = any_lsda_needed = true;
|
3662 |
|
|
else if (TARGET_USES_WEAK_UNWIND_INFO && DECL_WEAK (fde_table[i].decl))
|
3663 |
|
|
any_eh_needed = true;
|
3664 |
|
|
else if (! fde_table[i].nothrow
|
3665 |
|
|
&& ! fde_table[i].all_throwers_are_sibcalls)
|
3666 |
|
|
any_eh_needed = true;
|
3667 |
|
|
|
3668 |
|
|
if (! any_eh_needed)
|
3669 |
|
|
return;
|
3670 |
|
|
}
|
3671 |
|
|
|
3672 |
|
|
/* We're going to be generating comments, so turn on app. */
|
3673 |
|
|
if (flag_debug_asm)
|
3674 |
|
|
app_enable ();
|
3675 |
|
|
|
3676 |
|
|
/* Switch to the proper frame section, first time. */
|
3677 |
|
|
switch_to_frame_table_section (for_eh, false);
|
3678 |
|
|
|
3679 |
|
|
ASM_GENERATE_INTERNAL_LABEL (section_start_label, FRAME_BEGIN_LABEL, for_eh);
|
3680 |
|
|
ASM_OUTPUT_LABEL (asm_out_file, section_start_label);
|
3681 |
|
|
|
3682 |
|
|
/* Output the CIE. */
|
3683 |
|
|
ASM_GENERATE_INTERNAL_LABEL (l1, CIE_AFTER_SIZE_LABEL, for_eh);
|
3684 |
|
|
ASM_GENERATE_INTERNAL_LABEL (l2, CIE_END_LABEL, for_eh);
|
3685 |
|
|
if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4 && !for_eh)
|
3686 |
|
|
dw2_asm_output_data (4, 0xffffffff,
|
3687 |
|
|
"Initial length escape value indicating 64-bit DWARF extension");
|
3688 |
|
|
dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1,
|
3689 |
|
|
"Length of Common Information Entry");
|
3690 |
|
|
ASM_OUTPUT_LABEL (asm_out_file, l1);
|
3691 |
|
|
|
3692 |
|
|
/* Now that the CIE pointer is PC-relative for EH,
|
3693 |
|
|
use 0 to identify the CIE. */
|
3694 |
|
|
dw2_asm_output_data ((for_eh ? 4 : DWARF_OFFSET_SIZE),
|
3695 |
|
|
(for_eh ? 0 : DWARF_CIE_ID),
|
3696 |
|
|
"CIE Identifier Tag");
|
3697 |
|
|
|
3698 |
|
|
/* Use the CIE version 3 for DWARF3; allow DWARF2 to continue to
|
3699 |
|
|
use CIE version 1, unless that would produce incorrect results
|
3700 |
|
|
due to overflowing the return register column. */
|
3701 |
|
|
return_reg = DWARF2_FRAME_REG_OUT (DWARF_FRAME_RETURN_COLUMN, for_eh);
|
3702 |
|
|
dw_cie_version = 1;
|
3703 |
|
|
if (return_reg >= 256 || dwarf_version > 2)
|
3704 |
|
|
dw_cie_version = 3;
|
3705 |
|
|
dw2_asm_output_data (1, dw_cie_version, "CIE Version");
|
3706 |
|
|
|
3707 |
|
|
augmentation[0] = 0;
|
3708 |
|
|
augmentation_size = 0;
|
3709 |
|
|
|
3710 |
|
|
personality = current_unit_personality;
|
3711 |
|
|
if (for_eh)
|
3712 |
|
|
{
|
3713 |
|
|
char *p;
|
3714 |
|
|
|
3715 |
|
|
/* Augmentation:
|
3716 |
|
|
z Indicates that a uleb128 is present to size the
|
3717 |
|
|
augmentation section.
|
3718 |
|
|
L Indicates the encoding (and thus presence) of
|
3719 |
|
|
an LSDA pointer in the FDE augmentation.
|
3720 |
|
|
R Indicates a non-default pointer encoding for
|
3721 |
|
|
FDE code pointers.
|
3722 |
|
|
P Indicates the presence of an encoding + language
|
3723 |
|
|
personality routine in the CIE augmentation. */
|
3724 |
|
|
|
3725 |
|
|
fde_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/1, /*global=*/0);
|
3726 |
|
|
per_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1);
|
3727 |
|
|
lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0);
|
3728 |
|
|
|
3729 |
|
|
p = augmentation + 1;
|
3730 |
|
|
if (personality)
|
3731 |
|
|
{
|
3732 |
|
|
*p++ = 'P';
|
3733 |
|
|
augmentation_size += 1 + size_of_encoded_value (per_encoding);
|
3734 |
|
|
assemble_external_libcall (personality);
|
3735 |
|
|
}
|
3736 |
|
|
if (any_lsda_needed)
|
3737 |
|
|
{
|
3738 |
|
|
*p++ = 'L';
|
3739 |
|
|
augmentation_size += 1;
|
3740 |
|
|
}
|
3741 |
|
|
if (fde_encoding != DW_EH_PE_absptr)
|
3742 |
|
|
{
|
3743 |
|
|
*p++ = 'R';
|
3744 |
|
|
augmentation_size += 1;
|
3745 |
|
|
}
|
3746 |
|
|
if (p > augmentation + 1)
|
3747 |
|
|
{
|
3748 |
|
|
augmentation[0] = 'z';
|
3749 |
|
|
*p = '\0';
|
3750 |
|
|
}
|
3751 |
|
|
|
3752 |
|
|
/* Ug. Some platforms can't do unaligned dynamic relocations at all. */
|
3753 |
|
|
if (personality && per_encoding == DW_EH_PE_aligned)
|
3754 |
|
|
{
|
3755 |
|
|
int offset = ( 4 /* Length */
|
3756 |
|
|
+ 4 /* CIE Id */
|
3757 |
|
|
+ 1 /* CIE version */
|
3758 |
|
|
+ strlen (augmentation) + 1 /* Augmentation */
|
3759 |
|
|
+ size_of_uleb128 (1) /* Code alignment */
|
3760 |
|
|
+ size_of_sleb128 (DWARF_CIE_DATA_ALIGNMENT)
|
3761 |
|
|
+ 1 /* RA column */
|
3762 |
|
|
+ 1 /* Augmentation size */
|
3763 |
|
|
+ 1 /* Personality encoding */ );
|
3764 |
|
|
int pad = -offset & (PTR_SIZE - 1);
|
3765 |
|
|
|
3766 |
|
|
augmentation_size += pad;
|
3767 |
|
|
|
3768 |
|
|
/* Augmentations should be small, so there's scarce need to
|
3769 |
|
|
iterate for a solution. Die if we exceed one uleb128 byte. */
|
3770 |
|
|
gcc_assert (size_of_uleb128 (augmentation_size) == 1);
|
3771 |
|
|
}
|
3772 |
|
|
}
|
3773 |
|
|
|
3774 |
|
|
dw2_asm_output_nstring (augmentation, -1, "CIE Augmentation");
|
3775 |
|
|
dw2_asm_output_data_uleb128 (1, "CIE Code Alignment Factor");
|
3776 |
|
|
dw2_asm_output_data_sleb128 (DWARF_CIE_DATA_ALIGNMENT,
|
3777 |
|
|
"CIE Data Alignment Factor");
|
3778 |
|
|
|
3779 |
|
|
if (dw_cie_version == 1)
|
3780 |
|
|
dw2_asm_output_data (1, return_reg, "CIE RA Column");
|
3781 |
|
|
else
|
3782 |
|
|
dw2_asm_output_data_uleb128 (return_reg, "CIE RA Column");
|
3783 |
|
|
|
3784 |
|
|
if (augmentation[0])
|
3785 |
|
|
{
|
3786 |
|
|
dw2_asm_output_data_uleb128 (augmentation_size, "Augmentation size");
|
3787 |
|
|
if (personality)
|
3788 |
|
|
{
|
3789 |
|
|
dw2_asm_output_data (1, per_encoding, "Personality (%s)",
|
3790 |
|
|
eh_data_format_name (per_encoding));
|
3791 |
|
|
dw2_asm_output_encoded_addr_rtx (per_encoding,
|
3792 |
|
|
personality,
|
3793 |
|
|
true, NULL);
|
3794 |
|
|
}
|
3795 |
|
|
|
3796 |
|
|
if (any_lsda_needed)
|
3797 |
|
|
dw2_asm_output_data (1, lsda_encoding, "LSDA Encoding (%s)",
|
3798 |
|
|
eh_data_format_name (lsda_encoding));
|
3799 |
|
|
|
3800 |
|
|
if (fde_encoding != DW_EH_PE_absptr)
|
3801 |
|
|
dw2_asm_output_data (1, fde_encoding, "FDE Encoding (%s)",
|
3802 |
|
|
eh_data_format_name (fde_encoding));
|
3803 |
|
|
}
|
3804 |
|
|
|
3805 |
|
|
for (cfi = cie_cfi_head; cfi != NULL; cfi = cfi->dw_cfi_next)
|
3806 |
|
|
output_cfi (cfi, NULL, for_eh);
|
3807 |
|
|
|
3808 |
|
|
/* Pad the CIE out to an address sized boundary. */
|
3809 |
|
|
ASM_OUTPUT_ALIGN (asm_out_file,
|
3810 |
|
|
floor_log2 (for_eh ? PTR_SIZE : DWARF2_ADDR_SIZE));
|
3811 |
|
|
ASM_OUTPUT_LABEL (asm_out_file, l2);
|
3812 |
|
|
|
3813 |
|
|
/* Loop through all of the FDE's. */
|
3814 |
|
|
for (i = 0; i < fde_table_in_use; i++)
|
3815 |
|
|
{
|
3816 |
|
|
unsigned int k;
|
3817 |
|
|
fde = &fde_table[i];
|
3818 |
|
|
|
3819 |
|
|
/* Don't emit EH unwind info for leaf functions that don't need it. */
|
3820 |
|
|
if (for_eh && !flag_asynchronous_unwind_tables && flag_exceptions
|
3821 |
|
|
&& (fde->nothrow || fde->all_throwers_are_sibcalls)
|
3822 |
|
|
&& ! (TARGET_USES_WEAK_UNWIND_INFO && DECL_WEAK (fde_table[i].decl))
|
3823 |
|
|
&& !fde->uses_eh_lsda)
|
3824 |
|
|
continue;
|
3825 |
|
|
|
3826 |
|
|
for (k = 0; k < (fde->dw_fde_switched_sections ? 2 : 1); k++)
|
3827 |
|
|
output_fde (fde, for_eh, k, section_start_label, fde_encoding,
|
3828 |
|
|
augmentation, any_lsda_needed, lsda_encoding);
|
3829 |
|
|
}
|
3830 |
|
|
|
3831 |
|
|
if (for_eh && targetm.terminate_dw2_eh_frame_info)
|
3832 |
|
|
dw2_asm_output_data (4, 0, "End of Table");
|
3833 |
|
|
#ifdef MIPS_DEBUGGING_INFO
|
3834 |
|
|
/* Work around Irix 6 assembler bug whereby labels at the end of a section
|
3835 |
|
|
get a value of 0. Putting .align 0 after the label fixes it. */
|
3836 |
|
|
ASM_OUTPUT_ALIGN (asm_out_file, 0);
|
3837 |
|
|
#endif
|
3838 |
|
|
|
3839 |
|
|
/* Turn off app to make assembly quicker. */
|
3840 |
|
|
if (flag_debug_asm)
|
3841 |
|
|
app_disable ();
|
3842 |
|
|
}
|
3843 |
|
|
|
3844 |
|
|
/* Emit .cfi_startproc and .cfi_personality/.cfi_lsda if needed. */
|
3845 |
|
|
|
3846 |
|
|
static void
|
3847 |
|
|
dwarf2out_do_cfi_startproc (bool second)
|
3848 |
|
|
{
|
3849 |
|
|
int enc;
|
3850 |
|
|
rtx ref;
|
3851 |
|
|
rtx personality = get_personality_function (current_function_decl);
|
3852 |
|
|
|
3853 |
|
|
fprintf (asm_out_file, "\t.cfi_startproc\n");
|
3854 |
|
|
|
3855 |
|
|
if (personality)
|
3856 |
|
|
{
|
3857 |
|
|
enc = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1);
|
3858 |
|
|
ref = personality;
|
3859 |
|
|
|
3860 |
|
|
/* ??? The GAS support isn't entirely consistent. We have to
|
3861 |
|
|
handle indirect support ourselves, but PC-relative is done
|
3862 |
|
|
in the assembler. Further, the assembler can't handle any
|
3863 |
|
|
of the weirder relocation types. */
|
3864 |
|
|
if (enc & DW_EH_PE_indirect)
|
3865 |
|
|
ref = dw2_force_const_mem (ref, true);
|
3866 |
|
|
|
3867 |
|
|
fprintf (asm_out_file, "\t.cfi_personality 0x%x,", enc);
|
3868 |
|
|
output_addr_const (asm_out_file, ref);
|
3869 |
|
|
fputc ('\n', asm_out_file);
|
3870 |
|
|
}
|
3871 |
|
|
|
3872 |
|
|
if (crtl->uses_eh_lsda)
|
3873 |
|
|
{
|
3874 |
|
|
char lab[20];
|
3875 |
|
|
|
3876 |
|
|
enc = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0);
|
3877 |
|
|
ASM_GENERATE_INTERNAL_LABEL (lab, second ? "LLSDAC" : "LLSDA",
|
3878 |
|
|
current_function_funcdef_no);
|
3879 |
|
|
ref = gen_rtx_SYMBOL_REF (Pmode, lab);
|
3880 |
|
|
SYMBOL_REF_FLAGS (ref) = SYMBOL_FLAG_LOCAL;
|
3881 |
|
|
|
3882 |
|
|
if (enc & DW_EH_PE_indirect)
|
3883 |
|
|
ref = dw2_force_const_mem (ref, true);
|
3884 |
|
|
|
3885 |
|
|
fprintf (asm_out_file, "\t.cfi_lsda 0x%x,", enc);
|
3886 |
|
|
output_addr_const (asm_out_file, ref);
|
3887 |
|
|
fputc ('\n', asm_out_file);
|
3888 |
|
|
}
|
3889 |
|
|
}
|
3890 |
|
|
|
3891 |
|
|
/* Output a marker (i.e. a label) for the beginning of a function, before
|
3892 |
|
|
the prologue. */
|
3893 |
|
|
|
3894 |
|
|
void
|
3895 |
|
|
dwarf2out_begin_prologue (unsigned int line ATTRIBUTE_UNUSED,
|
3896 |
|
|
const char *file ATTRIBUTE_UNUSED)
|
3897 |
|
|
{
|
3898 |
|
|
char label[MAX_ARTIFICIAL_LABEL_BYTES];
|
3899 |
|
|
char * dup_label;
|
3900 |
|
|
dw_fde_ref fde;
|
3901 |
|
|
section *fnsec;
|
3902 |
|
|
|
3903 |
|
|
current_function_func_begin_label = NULL;
|
3904 |
|
|
|
3905 |
|
|
#ifdef TARGET_UNWIND_INFO
|
3906 |
|
|
/* ??? current_function_func_begin_label is also used by except.c
|
3907 |
|
|
for call-site information. We must emit this label if it might
|
3908 |
|
|
be used. */
|
3909 |
|
|
if ((! flag_exceptions || USING_SJLJ_EXCEPTIONS)
|
3910 |
|
|
&& ! dwarf2out_do_frame ())
|
3911 |
|
|
return;
|
3912 |
|
|
#else
|
3913 |
|
|
if (! dwarf2out_do_frame ())
|
3914 |
|
|
return;
|
3915 |
|
|
#endif
|
3916 |
|
|
|
3917 |
|
|
fnsec = function_section (current_function_decl);
|
3918 |
|
|
switch_to_section (fnsec);
|
3919 |
|
|
ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL,
|
3920 |
|
|
current_function_funcdef_no);
|
3921 |
|
|
ASM_OUTPUT_DEBUG_LABEL (asm_out_file, FUNC_BEGIN_LABEL,
|
3922 |
|
|
current_function_funcdef_no);
|
3923 |
|
|
dup_label = xstrdup (label);
|
3924 |
|
|
current_function_func_begin_label = dup_label;
|
3925 |
|
|
|
3926 |
|
|
#ifdef TARGET_UNWIND_INFO
|
3927 |
|
|
/* We can elide the fde allocation if we're not emitting debug info. */
|
3928 |
|
|
if (! dwarf2out_do_frame ())
|
3929 |
|
|
return;
|
3930 |
|
|
#endif
|
3931 |
|
|
|
3932 |
|
|
/* Expand the fde table if necessary. */
|
3933 |
|
|
if (fde_table_in_use == fde_table_allocated)
|
3934 |
|
|
{
|
3935 |
|
|
fde_table_allocated += FDE_TABLE_INCREMENT;
|
3936 |
|
|
fde_table = GGC_RESIZEVEC (dw_fde_node, fde_table, fde_table_allocated);
|
3937 |
|
|
memset (fde_table + fde_table_in_use, 0,
|
3938 |
|
|
FDE_TABLE_INCREMENT * sizeof (dw_fde_node));
|
3939 |
|
|
}
|
3940 |
|
|
|
3941 |
|
|
/* Record the FDE associated with this function. */
|
3942 |
|
|
current_funcdef_fde = fde_table_in_use;
|
3943 |
|
|
|
3944 |
|
|
/* Add the new FDE at the end of the fde_table. */
|
3945 |
|
|
fde = &fde_table[fde_table_in_use++];
|
3946 |
|
|
fde->decl = current_function_decl;
|
3947 |
|
|
fde->dw_fde_begin = dup_label;
|
3948 |
|
|
fde->dw_fde_current_label = dup_label;
|
3949 |
|
|
fde->dw_fde_hot_section_label = NULL;
|
3950 |
|
|
fde->dw_fde_hot_section_end_label = NULL;
|
3951 |
|
|
fde->dw_fde_unlikely_section_label = NULL;
|
3952 |
|
|
fde->dw_fde_unlikely_section_end_label = NULL;
|
3953 |
|
|
fde->dw_fde_switched_sections = 0;
|
3954 |
|
|
fde->dw_fde_switched_cold_to_hot = 0;
|
3955 |
|
|
fde->dw_fde_end = NULL;
|
3956 |
|
|
fde->dw_fde_cfi = NULL;
|
3957 |
|
|
fde->dw_fde_switch_cfi = NULL;
|
3958 |
|
|
fde->funcdef_number = current_function_funcdef_no;
|
3959 |
|
|
fde->nothrow = crtl->nothrow;
|
3960 |
|
|
fde->uses_eh_lsda = crtl->uses_eh_lsda;
|
3961 |
|
|
fde->all_throwers_are_sibcalls = crtl->all_throwers_are_sibcalls;
|
3962 |
|
|
fde->drap_reg = INVALID_REGNUM;
|
3963 |
|
|
fde->vdrap_reg = INVALID_REGNUM;
|
3964 |
|
|
if (flag_reorder_blocks_and_partition)
|
3965 |
|
|
{
|
3966 |
|
|
section *unlikelysec;
|
3967 |
|
|
if (first_function_block_is_cold)
|
3968 |
|
|
fde->in_std_section = 1;
|
3969 |
|
|
else
|
3970 |
|
|
fde->in_std_section
|
3971 |
|
|
= (fnsec == text_section
|
3972 |
|
|
|| (cold_text_section && fnsec == cold_text_section));
|
3973 |
|
|
unlikelysec = unlikely_text_section ();
|
3974 |
|
|
fde->cold_in_std_section
|
3975 |
|
|
= (unlikelysec == text_section
|
3976 |
|
|
|| (cold_text_section && unlikelysec == cold_text_section));
|
3977 |
|
|
}
|
3978 |
|
|
else
|
3979 |
|
|
{
|
3980 |
|
|
fde->in_std_section
|
3981 |
|
|
= (fnsec == text_section
|
3982 |
|
|
|| (cold_text_section && fnsec == cold_text_section));
|
3983 |
|
|
fde->cold_in_std_section = 0;
|
3984 |
|
|
}
|
3985 |
|
|
|
3986 |
|
|
args_size = old_args_size = 0;
|
3987 |
|
|
|
3988 |
|
|
/* We only want to output line number information for the genuine dwarf2
|
3989 |
|
|
prologue case, not the eh frame case. */
|
3990 |
|
|
#ifdef DWARF2_DEBUGGING_INFO
|
3991 |
|
|
if (file)
|
3992 |
|
|
dwarf2out_source_line (line, file, 0, true);
|
3993 |
|
|
#endif
|
3994 |
|
|
|
3995 |
|
|
if (dwarf2out_do_cfi_asm ())
|
3996 |
|
|
dwarf2out_do_cfi_startproc (false);
|
3997 |
|
|
else
|
3998 |
|
|
{
|
3999 |
|
|
rtx personality = get_personality_function (current_function_decl);
|
4000 |
|
|
if (!current_unit_personality)
|
4001 |
|
|
current_unit_personality = personality;
|
4002 |
|
|
|
4003 |
|
|
/* We cannot keep a current personality per function as without CFI
|
4004 |
|
|
asm at the point where we emit the CFI data there is no current
|
4005 |
|
|
function anymore. */
|
4006 |
|
|
if (personality
|
4007 |
|
|
&& current_unit_personality != personality)
|
4008 |
|
|
sorry ("Multiple EH personalities are supported only with assemblers "
|
4009 |
|
|
"supporting .cfi.personality directive.");
|
4010 |
|
|
}
|
4011 |
|
|
}
|
4012 |
|
|
|
4013 |
|
|
/* Output a marker (i.e. a label) for the absolute end of the generated code
|
4014 |
|
|
for a function definition. This gets called *after* the epilogue code has
|
4015 |
|
|
been generated. */
|
4016 |
|
|
|
4017 |
|
|
void
|
4018 |
|
|
dwarf2out_end_epilogue (unsigned int line ATTRIBUTE_UNUSED,
|
4019 |
|
|
const char *file ATTRIBUTE_UNUSED)
|
4020 |
|
|
{
|
4021 |
|
|
dw_fde_ref fde;
|
4022 |
|
|
char label[MAX_ARTIFICIAL_LABEL_BYTES];
|
4023 |
|
|
|
4024 |
|
|
#ifdef DWARF2_DEBUGGING_INFO
|
4025 |
|
|
last_var_location_insn = NULL_RTX;
|
4026 |
|
|
#endif
|
4027 |
|
|
|
4028 |
|
|
if (dwarf2out_do_cfi_asm ())
|
4029 |
|
|
fprintf (asm_out_file, "\t.cfi_endproc\n");
|
4030 |
|
|
|
4031 |
|
|
/* Output a label to mark the endpoint of the code generated for this
|
4032 |
|
|
function. */
|
4033 |
|
|
ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL,
|
4034 |
|
|
current_function_funcdef_no);
|
4035 |
|
|
ASM_OUTPUT_LABEL (asm_out_file, label);
|
4036 |
|
|
fde = current_fde ();
|
4037 |
|
|
gcc_assert (fde != NULL);
|
4038 |
|
|
fde->dw_fde_end = xstrdup (label);
|
4039 |
|
|
}
|
4040 |
|
|
|
4041 |
|
|
void
|
4042 |
|
|
dwarf2out_frame_init (void)
|
4043 |
|
|
{
|
4044 |
|
|
/* Allocate the initial hunk of the fde_table. */
|
4045 |
|
|
fde_table = GGC_CNEWVEC (dw_fde_node, FDE_TABLE_INCREMENT);
|
4046 |
|
|
fde_table_allocated = FDE_TABLE_INCREMENT;
|
4047 |
|
|
fde_table_in_use = 0;
|
4048 |
|
|
|
4049 |
|
|
/* Generate the CFA instructions common to all FDE's. Do it now for the
|
4050 |
|
|
sake of lookup_cfa. */
|
4051 |
|
|
|
4052 |
|
|
/* On entry, the Canonical Frame Address is at SP. */
|
4053 |
|
|
dwarf2out_def_cfa (NULL, STACK_POINTER_REGNUM, INCOMING_FRAME_SP_OFFSET);
|
4054 |
|
|
|
4055 |
|
|
#ifdef DWARF2_UNWIND_INFO
|
4056 |
|
|
if (DWARF2_UNWIND_INFO || DWARF2_FRAME_INFO)
|
4057 |
|
|
initial_return_save (INCOMING_RETURN_ADDR_RTX);
|
4058 |
|
|
#endif
|
4059 |
|
|
}
|
4060 |
|
|
|
4061 |
|
|
void
|
4062 |
|
|
dwarf2out_frame_finish (void)
|
4063 |
|
|
{
|
4064 |
|
|
/* Output call frame information. */
|
4065 |
|
|
if (DWARF2_FRAME_INFO)
|
4066 |
|
|
output_call_frame_info (0);
|
4067 |
|
|
|
4068 |
|
|
#ifndef TARGET_UNWIND_INFO
|
4069 |
|
|
/* Output another copy for the unwinder. */
|
4070 |
|
|
if (! USING_SJLJ_EXCEPTIONS && (flag_unwind_tables || flag_exceptions))
|
4071 |
|
|
output_call_frame_info (1);
|
4072 |
|
|
#endif
|
4073 |
|
|
}
|
4074 |
|
|
|
4075 |
|
|
/* Note that the current function section is being used for code. */
|
4076 |
|
|
|
4077 |
|
|
static void
|
4078 |
|
|
dwarf2out_note_section_used (void)
|
4079 |
|
|
{
|
4080 |
|
|
section *sec = current_function_section ();
|
4081 |
|
|
if (sec == text_section)
|
4082 |
|
|
text_section_used = true;
|
4083 |
|
|
else if (sec == cold_text_section)
|
4084 |
|
|
cold_text_section_used = true;
|
4085 |
|
|
}
|
4086 |
|
|
|
4087 |
|
|
void
|
4088 |
|
|
dwarf2out_switch_text_section (void)
|
4089 |
|
|
{
|
4090 |
|
|
dw_fde_ref fde = current_fde ();
|
4091 |
|
|
|
4092 |
|
|
gcc_assert (cfun && fde && !fde->dw_fde_switched_sections);
|
4093 |
|
|
|
4094 |
|
|
fde->dw_fde_switched_sections = 1;
|
4095 |
|
|
fde->dw_fde_switched_cold_to_hot = !in_cold_section_p;
|
4096 |
|
|
|
4097 |
|
|
fde->dw_fde_hot_section_label = crtl->subsections.hot_section_label;
|
4098 |
|
|
fde->dw_fde_hot_section_end_label = crtl->subsections.hot_section_end_label;
|
4099 |
|
|
fde->dw_fde_unlikely_section_label = crtl->subsections.cold_section_label;
|
4100 |
|
|
fde->dw_fde_unlikely_section_end_label = crtl->subsections.cold_section_end_label;
|
4101 |
|
|
have_multiple_function_sections = true;
|
4102 |
|
|
|
4103 |
|
|
/* Reset the current label on switching text sections, so that we
|
4104 |
|
|
don't attempt to advance_loc4 between labels in different sections. */
|
4105 |
|
|
fde->dw_fde_current_label = NULL;
|
4106 |
|
|
|
4107 |
|
|
/* There is no need to mark used sections when not debugging. */
|
4108 |
|
|
if (cold_text_section != NULL)
|
4109 |
|
|
dwarf2out_note_section_used ();
|
4110 |
|
|
|
4111 |
|
|
if (dwarf2out_do_cfi_asm ())
|
4112 |
|
|
fprintf (asm_out_file, "\t.cfi_endproc\n");
|
4113 |
|
|
|
4114 |
|
|
/* Now do the real section switch. */
|
4115 |
|
|
switch_to_section (current_function_section ());
|
4116 |
|
|
|
4117 |
|
|
if (dwarf2out_do_cfi_asm ())
|
4118 |
|
|
{
|
4119 |
|
|
dwarf2out_do_cfi_startproc (true);
|
4120 |
|
|
/* As this is a different FDE, insert all current CFI instructions
|
4121 |
|
|
again. */
|
4122 |
|
|
output_cfis (fde->dw_fde_cfi, true, fde, true);
|
4123 |
|
|
}
|
4124 |
|
|
else
|
4125 |
|
|
{
|
4126 |
|
|
dw_cfi_ref cfi = fde->dw_fde_cfi;
|
4127 |
|
|
|
4128 |
|
|
cfi = fde->dw_fde_cfi;
|
4129 |
|
|
if (cfi)
|
4130 |
|
|
while (cfi->dw_cfi_next != NULL)
|
4131 |
|
|
cfi = cfi->dw_cfi_next;
|
4132 |
|
|
fde->dw_fde_switch_cfi = cfi;
|
4133 |
|
|
}
|
4134 |
|
|
}
|
4135 |
|
|
#endif
|
4136 |
|
|
|
4137 |
|
|
/* And now, the subset of the debugging information support code necessary
|
4138 |
|
|
for emitting location expressions. */
|
4139 |
|
|
|
4140 |
|
|
/* Data about a single source file. */
|
4141 |
|
|
struct GTY(()) dwarf_file_data {
|
4142 |
|
|
const char * filename;
|
4143 |
|
|
int emitted_number;
|
4144 |
|
|
};
|
4145 |
|
|
|
4146 |
|
|
typedef struct dw_val_struct *dw_val_ref;
|
4147 |
|
|
typedef struct die_struct *dw_die_ref;
|
4148 |
|
|
typedef const struct die_struct *const_dw_die_ref;
|
4149 |
|
|
typedef struct dw_loc_descr_struct *dw_loc_descr_ref;
|
4150 |
|
|
typedef struct dw_loc_list_struct *dw_loc_list_ref;
|
4151 |
|
|
|
4152 |
|
|
typedef struct GTY(()) deferred_locations_struct
|
4153 |
|
|
{
|
4154 |
|
|
tree variable;
|
4155 |
|
|
dw_die_ref die;
|
4156 |
|
|
} deferred_locations;
|
4157 |
|
|
|
4158 |
|
|
DEF_VEC_O(deferred_locations);
|
4159 |
|
|
DEF_VEC_ALLOC_O(deferred_locations,gc);
|
4160 |
|
|
|
4161 |
|
|
static GTY(()) VEC(deferred_locations, gc) *deferred_locations_list;
|
4162 |
|
|
|
4163 |
|
|
DEF_VEC_P(dw_die_ref);
|
4164 |
|
|
DEF_VEC_ALLOC_P(dw_die_ref,heap);
|
4165 |
|
|
|
4166 |
|
|
/* Each DIE may have a series of attribute/value pairs. Values
|
4167 |
|
|
can take on several forms. The forms that are used in this
|
4168 |
|
|
implementation are listed below. */
|
4169 |
|
|
|
4170 |
|
|
enum dw_val_class
|
4171 |
|
|
{
|
4172 |
|
|
dw_val_class_addr,
|
4173 |
|
|
dw_val_class_offset,
|
4174 |
|
|
dw_val_class_loc,
|
4175 |
|
|
dw_val_class_loc_list,
|
4176 |
|
|
dw_val_class_range_list,
|
4177 |
|
|
dw_val_class_const,
|
4178 |
|
|
dw_val_class_unsigned_const,
|
4179 |
|
|
dw_val_class_const_double,
|
4180 |
|
|
dw_val_class_vec,
|
4181 |
|
|
dw_val_class_flag,
|
4182 |
|
|
dw_val_class_die_ref,
|
4183 |
|
|
dw_val_class_fde_ref,
|
4184 |
|
|
dw_val_class_lbl_id,
|
4185 |
|
|
dw_val_class_lineptr,
|
4186 |
|
|
dw_val_class_str,
|
4187 |
|
|
dw_val_class_macptr,
|
4188 |
|
|
dw_val_class_file,
|
4189 |
|
|
dw_val_class_data8
|
4190 |
|
|
};
|
4191 |
|
|
|
4192 |
|
|
/* Describe a floating point constant value, or a vector constant value. */
|
4193 |
|
|
|
4194 |
|
|
typedef struct GTY(()) dw_vec_struct {
|
4195 |
|
|
unsigned char * GTY((length ("%h.length"))) array;
|
4196 |
|
|
unsigned length;
|
4197 |
|
|
unsigned elt_size;
|
4198 |
|
|
}
|
4199 |
|
|
dw_vec_const;
|
4200 |
|
|
|
4201 |
|
|
/* The dw_val_node describes an attribute's value, as it is
|
4202 |
|
|
represented internally. */
|
4203 |
|
|
|
4204 |
|
|
typedef struct GTY(()) dw_val_struct {
|
4205 |
|
|
enum dw_val_class val_class;
|
4206 |
|
|
union dw_val_struct_union
|
4207 |
|
|
{
|
4208 |
|
|
rtx GTY ((tag ("dw_val_class_addr"))) val_addr;
|
4209 |
|
|
unsigned HOST_WIDE_INT GTY ((tag ("dw_val_class_offset"))) val_offset;
|
4210 |
|
|
dw_loc_list_ref GTY ((tag ("dw_val_class_loc_list"))) val_loc_list;
|
4211 |
|
|
dw_loc_descr_ref GTY ((tag ("dw_val_class_loc"))) val_loc;
|
4212 |
|
|
HOST_WIDE_INT GTY ((default)) val_int;
|
4213 |
|
|
unsigned HOST_WIDE_INT GTY ((tag ("dw_val_class_unsigned_const"))) val_unsigned;
|
4214 |
|
|
double_int GTY ((tag ("dw_val_class_const_double"))) val_double;
|
4215 |
|
|
dw_vec_const GTY ((tag ("dw_val_class_vec"))) val_vec;
|
4216 |
|
|
struct dw_val_die_union
|
4217 |
|
|
{
|
4218 |
|
|
dw_die_ref die;
|
4219 |
|
|
int external;
|
4220 |
|
|
} GTY ((tag ("dw_val_class_die_ref"))) val_die_ref;
|
4221 |
|
|
unsigned GTY ((tag ("dw_val_class_fde_ref"))) val_fde_index;
|
4222 |
|
|
struct indirect_string_node * GTY ((tag ("dw_val_class_str"))) val_str;
|
4223 |
|
|
char * GTY ((tag ("dw_val_class_lbl_id"))) val_lbl_id;
|
4224 |
|
|
unsigned char GTY ((tag ("dw_val_class_flag"))) val_flag;
|
4225 |
|
|
struct dwarf_file_data * GTY ((tag ("dw_val_class_file"))) val_file;
|
4226 |
|
|
unsigned char GTY ((tag ("dw_val_class_data8"))) val_data8[8];
|
4227 |
|
|
}
|
4228 |
|
|
GTY ((desc ("%1.val_class"))) v;
|
4229 |
|
|
}
|
4230 |
|
|
dw_val_node;
|
4231 |
|
|
|
4232 |
|
|
/* Locations in memory are described using a sequence of stack machine
|
4233 |
|
|
operations. */
|
4234 |
|
|
|
4235 |
|
|
typedef struct GTY(()) dw_loc_descr_struct {
|
4236 |
|
|
dw_loc_descr_ref dw_loc_next;
|
4237 |
|
|
ENUM_BITFIELD (dwarf_location_atom) dw_loc_opc : 8;
|
4238 |
|
|
/* Used to distinguish DW_OP_addr with a direct symbol relocation
|
4239 |
|
|
from DW_OP_addr with a dtp-relative symbol relocation. */
|
4240 |
|
|
unsigned int dtprel : 1;
|
4241 |
|
|
int dw_loc_addr;
|
4242 |
|
|
dw_val_node dw_loc_oprnd1;
|
4243 |
|
|
dw_val_node dw_loc_oprnd2;
|
4244 |
|
|
}
|
4245 |
|
|
dw_loc_descr_node;
|
4246 |
|
|
|
4247 |
|
|
/* Location lists are ranges + location descriptions for that range,
|
4248 |
|
|
so you can track variables that are in different places over
|
4249 |
|
|
their entire life. */
|
4250 |
|
|
typedef struct GTY(()) dw_loc_list_struct {
|
4251 |
|
|
dw_loc_list_ref dw_loc_next;
|
4252 |
|
|
const char *begin; /* Label for begin address of range */
|
4253 |
|
|
const char *end; /* Label for end address of range */
|
4254 |
|
|
char *ll_symbol; /* Label for beginning of location list.
|
4255 |
|
|
Only on head of list */
|
4256 |
|
|
const char *section; /* Section this loclist is relative to */
|
4257 |
|
|
dw_loc_descr_ref expr;
|
4258 |
|
|
} dw_loc_list_node;
|
4259 |
|
|
|
4260 |
|
|
#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
|
4261 |
|
|
|
4262 |
|
|
static dw_loc_descr_ref int_loc_descriptor (HOST_WIDE_INT);
|
4263 |
|
|
|
4264 |
|
|
/* Convert a DWARF stack opcode into its string name. */
|
4265 |
|
|
|
4266 |
|
|
static const char *
|
4267 |
|
|
dwarf_stack_op_name (unsigned int op)
|
4268 |
|
|
{
|
4269 |
|
|
switch (op)
|
4270 |
|
|
{
|
4271 |
|
|
case DW_OP_addr:
|
4272 |
|
|
return "DW_OP_addr";
|
4273 |
|
|
case DW_OP_deref:
|
4274 |
|
|
return "DW_OP_deref";
|
4275 |
|
|
case DW_OP_const1u:
|
4276 |
|
|
return "DW_OP_const1u";
|
4277 |
|
|
case DW_OP_const1s:
|
4278 |
|
|
return "DW_OP_const1s";
|
4279 |
|
|
case DW_OP_const2u:
|
4280 |
|
|
return "DW_OP_const2u";
|
4281 |
|
|
case DW_OP_const2s:
|
4282 |
|
|
return "DW_OP_const2s";
|
4283 |
|
|
case DW_OP_const4u:
|
4284 |
|
|
return "DW_OP_const4u";
|
4285 |
|
|
case DW_OP_const4s:
|
4286 |
|
|
return "DW_OP_const4s";
|
4287 |
|
|
case DW_OP_const8u:
|
4288 |
|
|
return "DW_OP_const8u";
|
4289 |
|
|
case DW_OP_const8s:
|
4290 |
|
|
return "DW_OP_const8s";
|
4291 |
|
|
case DW_OP_constu:
|
4292 |
|
|
return "DW_OP_constu";
|
4293 |
|
|
case DW_OP_consts:
|
4294 |
|
|
return "DW_OP_consts";
|
4295 |
|
|
case DW_OP_dup:
|
4296 |
|
|
return "DW_OP_dup";
|
4297 |
|
|
case DW_OP_drop:
|
4298 |
|
|
return "DW_OP_drop";
|
4299 |
|
|
case DW_OP_over:
|
4300 |
|
|
return "DW_OP_over";
|
4301 |
|
|
case DW_OP_pick:
|
4302 |
|
|
return "DW_OP_pick";
|
4303 |
|
|
case DW_OP_swap:
|
4304 |
|
|
return "DW_OP_swap";
|
4305 |
|
|
case DW_OP_rot:
|
4306 |
|
|
return "DW_OP_rot";
|
4307 |
|
|
case DW_OP_xderef:
|
4308 |
|
|
return "DW_OP_xderef";
|
4309 |
|
|
case DW_OP_abs:
|
4310 |
|
|
return "DW_OP_abs";
|
4311 |
|
|
case DW_OP_and:
|
4312 |
|
|
return "DW_OP_and";
|
4313 |
|
|
case DW_OP_div:
|
4314 |
|
|
return "DW_OP_div";
|
4315 |
|
|
case DW_OP_minus:
|
4316 |
|
|
return "DW_OP_minus";
|
4317 |
|
|
case DW_OP_mod:
|
4318 |
|
|
return "DW_OP_mod";
|
4319 |
|
|
case DW_OP_mul:
|
4320 |
|
|
return "DW_OP_mul";
|
4321 |
|
|
case DW_OP_neg:
|
4322 |
|
|
return "DW_OP_neg";
|
4323 |
|
|
case DW_OP_not:
|
4324 |
|
|
return "DW_OP_not";
|
4325 |
|
|
case DW_OP_or:
|
4326 |
|
|
return "DW_OP_or";
|
4327 |
|
|
case DW_OP_plus:
|
4328 |
|
|
return "DW_OP_plus";
|
4329 |
|
|
case DW_OP_plus_uconst:
|
4330 |
|
|
return "DW_OP_plus_uconst";
|
4331 |
|
|
case DW_OP_shl:
|
4332 |
|
|
return "DW_OP_shl";
|
4333 |
|
|
case DW_OP_shr:
|
4334 |
|
|
return "DW_OP_shr";
|
4335 |
|
|
case DW_OP_shra:
|
4336 |
|
|
return "DW_OP_shra";
|
4337 |
|
|
case DW_OP_xor:
|
4338 |
|
|
return "DW_OP_xor";
|
4339 |
|
|
case DW_OP_bra:
|
4340 |
|
|
return "DW_OP_bra";
|
4341 |
|
|
case DW_OP_eq:
|
4342 |
|
|
return "DW_OP_eq";
|
4343 |
|
|
case DW_OP_ge:
|
4344 |
|
|
return "DW_OP_ge";
|
4345 |
|
|
case DW_OP_gt:
|
4346 |
|
|
return "DW_OP_gt";
|
4347 |
|
|
case DW_OP_le:
|
4348 |
|
|
return "DW_OP_le";
|
4349 |
|
|
case DW_OP_lt:
|
4350 |
|
|
return "DW_OP_lt";
|
4351 |
|
|
case DW_OP_ne:
|
4352 |
|
|
return "DW_OP_ne";
|
4353 |
|
|
case DW_OP_skip:
|
4354 |
|
|
return "DW_OP_skip";
|
4355 |
|
|
case DW_OP_lit0:
|
4356 |
|
|
return "DW_OP_lit0";
|
4357 |
|
|
case DW_OP_lit1:
|
4358 |
|
|
return "DW_OP_lit1";
|
4359 |
|
|
case DW_OP_lit2:
|
4360 |
|
|
return "DW_OP_lit2";
|
4361 |
|
|
case DW_OP_lit3:
|
4362 |
|
|
return "DW_OP_lit3";
|
4363 |
|
|
case DW_OP_lit4:
|
4364 |
|
|
return "DW_OP_lit4";
|
4365 |
|
|
case DW_OP_lit5:
|
4366 |
|
|
return "DW_OP_lit5";
|
4367 |
|
|
case DW_OP_lit6:
|
4368 |
|
|
return "DW_OP_lit6";
|
4369 |
|
|
case DW_OP_lit7:
|
4370 |
|
|
return "DW_OP_lit7";
|
4371 |
|
|
case DW_OP_lit8:
|
4372 |
|
|
return "DW_OP_lit8";
|
4373 |
|
|
case DW_OP_lit9:
|
4374 |
|
|
return "DW_OP_lit9";
|
4375 |
|
|
case DW_OP_lit10:
|
4376 |
|
|
return "DW_OP_lit10";
|
4377 |
|
|
case DW_OP_lit11:
|
4378 |
|
|
return "DW_OP_lit11";
|
4379 |
|
|
case DW_OP_lit12:
|
4380 |
|
|
return "DW_OP_lit12";
|
4381 |
|
|
case DW_OP_lit13:
|
4382 |
|
|
return "DW_OP_lit13";
|
4383 |
|
|
case DW_OP_lit14:
|
4384 |
|
|
return "DW_OP_lit14";
|
4385 |
|
|
case DW_OP_lit15:
|
4386 |
|
|
return "DW_OP_lit15";
|
4387 |
|
|
case DW_OP_lit16:
|
4388 |
|
|
return "DW_OP_lit16";
|
4389 |
|
|
case DW_OP_lit17:
|
4390 |
|
|
return "DW_OP_lit17";
|
4391 |
|
|
case DW_OP_lit18:
|
4392 |
|
|
return "DW_OP_lit18";
|
4393 |
|
|
case DW_OP_lit19:
|
4394 |
|
|
return "DW_OP_lit19";
|
4395 |
|
|
case DW_OP_lit20:
|
4396 |
|
|
return "DW_OP_lit20";
|
4397 |
|
|
case DW_OP_lit21:
|
4398 |
|
|
return "DW_OP_lit21";
|
4399 |
|
|
case DW_OP_lit22:
|
4400 |
|
|
return "DW_OP_lit22";
|
4401 |
|
|
case DW_OP_lit23:
|
4402 |
|
|
return "DW_OP_lit23";
|
4403 |
|
|
case DW_OP_lit24:
|
4404 |
|
|
return "DW_OP_lit24";
|
4405 |
|
|
case DW_OP_lit25:
|
4406 |
|
|
return "DW_OP_lit25";
|
4407 |
|
|
case DW_OP_lit26:
|
4408 |
|
|
return "DW_OP_lit26";
|
4409 |
|
|
case DW_OP_lit27:
|
4410 |
|
|
return "DW_OP_lit27";
|
4411 |
|
|
case DW_OP_lit28:
|
4412 |
|
|
return "DW_OP_lit28";
|
4413 |
|
|
case DW_OP_lit29:
|
4414 |
|
|
return "DW_OP_lit29";
|
4415 |
|
|
case DW_OP_lit30:
|
4416 |
|
|
return "DW_OP_lit30";
|
4417 |
|
|
case DW_OP_lit31:
|
4418 |
|
|
return "DW_OP_lit31";
|
4419 |
|
|
case DW_OP_reg0:
|
4420 |
|
|
return "DW_OP_reg0";
|
4421 |
|
|
case DW_OP_reg1:
|
4422 |
|
|
return "DW_OP_reg1";
|
4423 |
|
|
case DW_OP_reg2:
|
4424 |
|
|
return "DW_OP_reg2";
|
4425 |
|
|
case DW_OP_reg3:
|
4426 |
|
|
return "DW_OP_reg3";
|
4427 |
|
|
case DW_OP_reg4:
|
4428 |
|
|
return "DW_OP_reg4";
|
4429 |
|
|
case DW_OP_reg5:
|
4430 |
|
|
return "DW_OP_reg5";
|
4431 |
|
|
case DW_OP_reg6:
|
4432 |
|
|
return "DW_OP_reg6";
|
4433 |
|
|
case DW_OP_reg7:
|
4434 |
|
|
return "DW_OP_reg7";
|
4435 |
|
|
case DW_OP_reg8:
|
4436 |
|
|
return "DW_OP_reg8";
|
4437 |
|
|
case DW_OP_reg9:
|
4438 |
|
|
return "DW_OP_reg9";
|
4439 |
|
|
case DW_OP_reg10:
|
4440 |
|
|
return "DW_OP_reg10";
|
4441 |
|
|
case DW_OP_reg11:
|
4442 |
|
|
return "DW_OP_reg11";
|
4443 |
|
|
case DW_OP_reg12:
|
4444 |
|
|
return "DW_OP_reg12";
|
4445 |
|
|
case DW_OP_reg13:
|
4446 |
|
|
return "DW_OP_reg13";
|
4447 |
|
|
case DW_OP_reg14:
|
4448 |
|
|
return "DW_OP_reg14";
|
4449 |
|
|
case DW_OP_reg15:
|
4450 |
|
|
return "DW_OP_reg15";
|
4451 |
|
|
case DW_OP_reg16:
|
4452 |
|
|
return "DW_OP_reg16";
|
4453 |
|
|
case DW_OP_reg17:
|
4454 |
|
|
return "DW_OP_reg17";
|
4455 |
|
|
case DW_OP_reg18:
|
4456 |
|
|
return "DW_OP_reg18";
|
4457 |
|
|
case DW_OP_reg19:
|
4458 |
|
|
return "DW_OP_reg19";
|
4459 |
|
|
case DW_OP_reg20:
|
4460 |
|
|
return "DW_OP_reg20";
|
4461 |
|
|
case DW_OP_reg21:
|
4462 |
|
|
return "DW_OP_reg21";
|
4463 |
|
|
case DW_OP_reg22:
|
4464 |
|
|
return "DW_OP_reg22";
|
4465 |
|
|
case DW_OP_reg23:
|
4466 |
|
|
return "DW_OP_reg23";
|
4467 |
|
|
case DW_OP_reg24:
|
4468 |
|
|
return "DW_OP_reg24";
|
4469 |
|
|
case DW_OP_reg25:
|
4470 |
|
|
return "DW_OP_reg25";
|
4471 |
|
|
case DW_OP_reg26:
|
4472 |
|
|
return "DW_OP_reg26";
|
4473 |
|
|
case DW_OP_reg27:
|
4474 |
|
|
return "DW_OP_reg27";
|
4475 |
|
|
case DW_OP_reg28:
|
4476 |
|
|
return "DW_OP_reg28";
|
4477 |
|
|
case DW_OP_reg29:
|
4478 |
|
|
return "DW_OP_reg29";
|
4479 |
|
|
case DW_OP_reg30:
|
4480 |
|
|
return "DW_OP_reg30";
|
4481 |
|
|
case DW_OP_reg31:
|
4482 |
|
|
return "DW_OP_reg31";
|
4483 |
|
|
case DW_OP_breg0:
|
4484 |
|
|
return "DW_OP_breg0";
|
4485 |
|
|
case DW_OP_breg1:
|
4486 |
|
|
return "DW_OP_breg1";
|
4487 |
|
|
case DW_OP_breg2:
|
4488 |
|
|
return "DW_OP_breg2";
|
4489 |
|
|
case DW_OP_breg3:
|
4490 |
|
|
return "DW_OP_breg3";
|
4491 |
|
|
case DW_OP_breg4:
|
4492 |
|
|
return "DW_OP_breg4";
|
4493 |
|
|
case DW_OP_breg5:
|
4494 |
|
|
return "DW_OP_breg5";
|
4495 |
|
|
case DW_OP_breg6:
|
4496 |
|
|
return "DW_OP_breg6";
|
4497 |
|
|
case DW_OP_breg7:
|
4498 |
|
|
return "DW_OP_breg7";
|
4499 |
|
|
case DW_OP_breg8:
|
4500 |
|
|
return "DW_OP_breg8";
|
4501 |
|
|
case DW_OP_breg9:
|
4502 |
|
|
return "DW_OP_breg9";
|
4503 |
|
|
case DW_OP_breg10:
|
4504 |
|
|
return "DW_OP_breg10";
|
4505 |
|
|
case DW_OP_breg11:
|
4506 |
|
|
return "DW_OP_breg11";
|
4507 |
|
|
case DW_OP_breg12:
|
4508 |
|
|
return "DW_OP_breg12";
|
4509 |
|
|
case DW_OP_breg13:
|
4510 |
|
|
return "DW_OP_breg13";
|
4511 |
|
|
case DW_OP_breg14:
|
4512 |
|
|
return "DW_OP_breg14";
|
4513 |
|
|
case DW_OP_breg15:
|
4514 |
|
|
return "DW_OP_breg15";
|
4515 |
|
|
case DW_OP_breg16:
|
4516 |
|
|
return "DW_OP_breg16";
|
4517 |
|
|
case DW_OP_breg17:
|
4518 |
|
|
return "DW_OP_breg17";
|
4519 |
|
|
case DW_OP_breg18:
|
4520 |
|
|
return "DW_OP_breg18";
|
4521 |
|
|
case DW_OP_breg19:
|
4522 |
|
|
return "DW_OP_breg19";
|
4523 |
|
|
case DW_OP_breg20:
|
4524 |
|
|
return "DW_OP_breg20";
|
4525 |
|
|
case DW_OP_breg21:
|
4526 |
|
|
return "DW_OP_breg21";
|
4527 |
|
|
case DW_OP_breg22:
|
4528 |
|
|
return "DW_OP_breg22";
|
4529 |
|
|
case DW_OP_breg23:
|
4530 |
|
|
return "DW_OP_breg23";
|
4531 |
|
|
case DW_OP_breg24:
|
4532 |
|
|
return "DW_OP_breg24";
|
4533 |
|
|
case DW_OP_breg25:
|
4534 |
|
|
return "DW_OP_breg25";
|
4535 |
|
|
case DW_OP_breg26:
|
4536 |
|
|
return "DW_OP_breg26";
|
4537 |
|
|
case DW_OP_breg27:
|
4538 |
|
|
return "DW_OP_breg27";
|
4539 |
|
|
case DW_OP_breg28:
|
4540 |
|
|
return "DW_OP_breg28";
|
4541 |
|
|
case DW_OP_breg29:
|
4542 |
|
|
return "DW_OP_breg29";
|
4543 |
|
|
case DW_OP_breg30:
|
4544 |
|
|
return "DW_OP_breg30";
|
4545 |
|
|
case DW_OP_breg31:
|
4546 |
|
|
return "DW_OP_breg31";
|
4547 |
|
|
case DW_OP_regx:
|
4548 |
|
|
return "DW_OP_regx";
|
4549 |
|
|
case DW_OP_fbreg:
|
4550 |
|
|
return "DW_OP_fbreg";
|
4551 |
|
|
case DW_OP_bregx:
|
4552 |
|
|
return "DW_OP_bregx";
|
4553 |
|
|
case DW_OP_piece:
|
4554 |
|
|
return "DW_OP_piece";
|
4555 |
|
|
case DW_OP_deref_size:
|
4556 |
|
|
return "DW_OP_deref_size";
|
4557 |
|
|
case DW_OP_xderef_size:
|
4558 |
|
|
return "DW_OP_xderef_size";
|
4559 |
|
|
case DW_OP_nop:
|
4560 |
|
|
return "DW_OP_nop";
|
4561 |
|
|
|
4562 |
|
|
case DW_OP_push_object_address:
|
4563 |
|
|
return "DW_OP_push_object_address";
|
4564 |
|
|
case DW_OP_call2:
|
4565 |
|
|
return "DW_OP_call2";
|
4566 |
|
|
case DW_OP_call4:
|
4567 |
|
|
return "DW_OP_call4";
|
4568 |
|
|
case DW_OP_call_ref:
|
4569 |
|
|
return "DW_OP_call_ref";
|
4570 |
|
|
case DW_OP_implicit_value:
|
4571 |
|
|
return "DW_OP_implicit_value";
|
4572 |
|
|
case DW_OP_stack_value:
|
4573 |
|
|
return "DW_OP_stack_value";
|
4574 |
|
|
case DW_OP_form_tls_address:
|
4575 |
|
|
return "DW_OP_form_tls_address";
|
4576 |
|
|
case DW_OP_call_frame_cfa:
|
4577 |
|
|
return "DW_OP_call_frame_cfa";
|
4578 |
|
|
case DW_OP_bit_piece:
|
4579 |
|
|
return "DW_OP_bit_piece";
|
4580 |
|
|
|
4581 |
|
|
case DW_OP_GNU_push_tls_address:
|
4582 |
|
|
return "DW_OP_GNU_push_tls_address";
|
4583 |
|
|
case DW_OP_GNU_uninit:
|
4584 |
|
|
return "DW_OP_GNU_uninit";
|
4585 |
|
|
case DW_OP_GNU_encoded_addr:
|
4586 |
|
|
return "DW_OP_GNU_encoded_addr";
|
4587 |
|
|
|
4588 |
|
|
default:
|
4589 |
|
|
return "OP_<unknown>";
|
4590 |
|
|
}
|
4591 |
|
|
}
|
4592 |
|
|
|
4593 |
|
|
/* Return a pointer to a newly allocated location description. Location
|
4594 |
|
|
descriptions are simple expression terms that can be strung
|
4595 |
|
|
together to form more complicated location (address) descriptions. */
|
4596 |
|
|
|
4597 |
|
|
static inline dw_loc_descr_ref
|
4598 |
|
|
new_loc_descr (enum dwarf_location_atom op, unsigned HOST_WIDE_INT oprnd1,
|
4599 |
|
|
unsigned HOST_WIDE_INT oprnd2)
|
4600 |
|
|
{
|
4601 |
|
|
dw_loc_descr_ref descr = GGC_CNEW (dw_loc_descr_node);
|
4602 |
|
|
|
4603 |
|
|
descr->dw_loc_opc = op;
|
4604 |
|
|
descr->dw_loc_oprnd1.val_class = dw_val_class_unsigned_const;
|
4605 |
|
|
descr->dw_loc_oprnd1.v.val_unsigned = oprnd1;
|
4606 |
|
|
descr->dw_loc_oprnd2.val_class = dw_val_class_unsigned_const;
|
4607 |
|
|
descr->dw_loc_oprnd2.v.val_unsigned = oprnd2;
|
4608 |
|
|
|
4609 |
|
|
return descr;
|
4610 |
|
|
}
|
4611 |
|
|
|
4612 |
|
|
/* Return a pointer to a newly allocated location description for
|
4613 |
|
|
REG and OFFSET. */
|
4614 |
|
|
|
4615 |
|
|
static inline dw_loc_descr_ref
|
4616 |
|
|
new_reg_loc_descr (unsigned int reg, unsigned HOST_WIDE_INT offset)
|
4617 |
|
|
{
|
4618 |
|
|
if (reg <= 31)
|
4619 |
|
|
return new_loc_descr ((enum dwarf_location_atom) (DW_OP_breg0 + reg),
|
4620 |
|
|
offset, 0);
|
4621 |
|
|
else
|
4622 |
|
|
return new_loc_descr (DW_OP_bregx, reg, offset);
|
4623 |
|
|
}
|
4624 |
|
|
|
4625 |
|
|
/* Add a location description term to a location description expression. */
|
4626 |
|
|
|
4627 |
|
|
static inline void
|
4628 |
|
|
add_loc_descr (dw_loc_descr_ref *list_head, dw_loc_descr_ref descr)
|
4629 |
|
|
{
|
4630 |
|
|
dw_loc_descr_ref *d;
|
4631 |
|
|
|
4632 |
|
|
/* Find the end of the chain. */
|
4633 |
|
|
for (d = list_head; (*d) != NULL; d = &(*d)->dw_loc_next)
|
4634 |
|
|
;
|
4635 |
|
|
|
4636 |
|
|
*d = descr;
|
4637 |
|
|
}
|
4638 |
|
|
|
4639 |
|
|
/* Add a constant OFFSET to a location expression. */
|
4640 |
|
|
|
4641 |
|
|
static void
|
4642 |
|
|
loc_descr_plus_const (dw_loc_descr_ref *list_head, HOST_WIDE_INT offset)
|
4643 |
|
|
{
|
4644 |
|
|
dw_loc_descr_ref loc;
|
4645 |
|
|
HOST_WIDE_INT *p;
|
4646 |
|
|
|
4647 |
|
|
gcc_assert (*list_head != NULL);
|
4648 |
|
|
|
4649 |
|
|
if (!offset)
|
4650 |
|
|
return;
|
4651 |
|
|
|
4652 |
|
|
/* Find the end of the chain. */
|
4653 |
|
|
for (loc = *list_head; loc->dw_loc_next != NULL; loc = loc->dw_loc_next)
|
4654 |
|
|
;
|
4655 |
|
|
|
4656 |
|
|
p = NULL;
|
4657 |
|
|
if (loc->dw_loc_opc == DW_OP_fbreg
|
4658 |
|
|
|| (loc->dw_loc_opc >= DW_OP_breg0 && loc->dw_loc_opc <= DW_OP_breg31))
|
4659 |
|
|
p = &loc->dw_loc_oprnd1.v.val_int;
|
4660 |
|
|
else if (loc->dw_loc_opc == DW_OP_bregx)
|
4661 |
|
|
p = &loc->dw_loc_oprnd2.v.val_int;
|
4662 |
|
|
|
4663 |
|
|
/* If the last operation is fbreg, breg{0..31,x}, optimize by adjusting its
|
4664 |
|
|
offset. Don't optimize if an signed integer overflow would happen. */
|
4665 |
|
|
if (p != NULL
|
4666 |
|
|
&& ((offset > 0 && *p <= INTTYPE_MAXIMUM (HOST_WIDE_INT) - offset)
|
4667 |
|
|
|| (offset < 0 && *p >= INTTYPE_MINIMUM (HOST_WIDE_INT) - offset)))
|
4668 |
|
|
*p += offset;
|
4669 |
|
|
|
4670 |
|
|
else if (offset > 0)
|
4671 |
|
|
loc->dw_loc_next = new_loc_descr (DW_OP_plus_uconst, offset, 0);
|
4672 |
|
|
|
4673 |
|
|
else
|
4674 |
|
|
{
|
4675 |
|
|
loc->dw_loc_next = int_loc_descriptor (offset);
|
4676 |
|
|
add_loc_descr (&loc->dw_loc_next, new_loc_descr (DW_OP_plus, 0, 0));
|
4677 |
|
|
}
|
4678 |
|
|
}
|
4679 |
|
|
|
4680 |
|
|
#ifdef DWARF2_DEBUGGING_INFO
|
4681 |
|
|
/* Add a constant OFFSET to a location list. */
|
4682 |
|
|
|
4683 |
|
|
static void
|
4684 |
|
|
loc_list_plus_const (dw_loc_list_ref list_head, HOST_WIDE_INT offset)
|
4685 |
|
|
{
|
4686 |
|
|
dw_loc_list_ref d;
|
4687 |
|
|
for (d = list_head; d != NULL; d = d->dw_loc_next)
|
4688 |
|
|
loc_descr_plus_const (&d->expr, offset);
|
4689 |
|
|
}
|
4690 |
|
|
#endif
|
4691 |
|
|
|
4692 |
|
|
/* Return the size of a location descriptor. */
|
4693 |
|
|
|
4694 |
|
|
static unsigned long
|
4695 |
|
|
size_of_loc_descr (dw_loc_descr_ref loc)
|
4696 |
|
|
{
|
4697 |
|
|
unsigned long size = 1;
|
4698 |
|
|
|
4699 |
|
|
switch (loc->dw_loc_opc)
|
4700 |
|
|
{
|
4701 |
|
|
case DW_OP_addr:
|
4702 |
|
|
size += DWARF2_ADDR_SIZE;
|
4703 |
|
|
break;
|
4704 |
|
|
case DW_OP_const1u:
|
4705 |
|
|
case DW_OP_const1s:
|
4706 |
|
|
size += 1;
|
4707 |
|
|
break;
|
4708 |
|
|
case DW_OP_const2u:
|
4709 |
|
|
case DW_OP_const2s:
|
4710 |
|
|
size += 2;
|
4711 |
|
|
break;
|
4712 |
|
|
case DW_OP_const4u:
|
4713 |
|
|
case DW_OP_const4s:
|
4714 |
|
|
size += 4;
|
4715 |
|
|
break;
|
4716 |
|
|
case DW_OP_const8u:
|
4717 |
|
|
case DW_OP_const8s:
|
4718 |
|
|
size += 8;
|
4719 |
|
|
break;
|
4720 |
|
|
case DW_OP_constu:
|
4721 |
|
|
size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
|
4722 |
|
|
break;
|
4723 |
|
|
case DW_OP_consts:
|
4724 |
|
|
size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int);
|
4725 |
|
|
break;
|
4726 |
|
|
case DW_OP_pick:
|
4727 |
|
|
size += 1;
|
4728 |
|
|
break;
|
4729 |
|
|
case DW_OP_plus_uconst:
|
4730 |
|
|
size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
|
4731 |
|
|
break;
|
4732 |
|
|
case DW_OP_skip:
|
4733 |
|
|
case DW_OP_bra:
|
4734 |
|
|
size += 2;
|
4735 |
|
|
break;
|
4736 |
|
|
case DW_OP_breg0:
|
4737 |
|
|
case DW_OP_breg1:
|
4738 |
|
|
case DW_OP_breg2:
|
4739 |
|
|
case DW_OP_breg3:
|
4740 |
|
|
case DW_OP_breg4:
|
4741 |
|
|
case DW_OP_breg5:
|
4742 |
|
|
case DW_OP_breg6:
|
4743 |
|
|
case DW_OP_breg7:
|
4744 |
|
|
case DW_OP_breg8:
|
4745 |
|
|
case DW_OP_breg9:
|
4746 |
|
|
case DW_OP_breg10:
|
4747 |
|
|
case DW_OP_breg11:
|
4748 |
|
|
case DW_OP_breg12:
|
4749 |
|
|
case DW_OP_breg13:
|
4750 |
|
|
case DW_OP_breg14:
|
4751 |
|
|
case DW_OP_breg15:
|
4752 |
|
|
case DW_OP_breg16:
|
4753 |
|
|
case DW_OP_breg17:
|
4754 |
|
|
case DW_OP_breg18:
|
4755 |
|
|
case DW_OP_breg19:
|
4756 |
|
|
case DW_OP_breg20:
|
4757 |
|
|
case DW_OP_breg21:
|
4758 |
|
|
case DW_OP_breg22:
|
4759 |
|
|
case DW_OP_breg23:
|
4760 |
|
|
case DW_OP_breg24:
|
4761 |
|
|
case DW_OP_breg25:
|
4762 |
|
|
case DW_OP_breg26:
|
4763 |
|
|
case DW_OP_breg27:
|
4764 |
|
|
case DW_OP_breg28:
|
4765 |
|
|
case DW_OP_breg29:
|
4766 |
|
|
case DW_OP_breg30:
|
4767 |
|
|
case DW_OP_breg31:
|
4768 |
|
|
size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int);
|
4769 |
|
|
break;
|
4770 |
|
|
case DW_OP_regx:
|
4771 |
|
|
size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
|
4772 |
|
|
break;
|
4773 |
|
|
case DW_OP_fbreg:
|
4774 |
|
|
size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int);
|
4775 |
|
|
break;
|
4776 |
|
|
case DW_OP_bregx:
|
4777 |
|
|
size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
|
4778 |
|
|
size += size_of_sleb128 (loc->dw_loc_oprnd2.v.val_int);
|
4779 |
|
|
break;
|
4780 |
|
|
case DW_OP_piece:
|
4781 |
|
|
size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
|
4782 |
|
|
break;
|
4783 |
|
|
case DW_OP_deref_size:
|
4784 |
|
|
case DW_OP_xderef_size:
|
4785 |
|
|
size += 1;
|
4786 |
|
|
break;
|
4787 |
|
|
case DW_OP_call2:
|
4788 |
|
|
size += 2;
|
4789 |
|
|
break;
|
4790 |
|
|
case DW_OP_call4:
|
4791 |
|
|
size += 4;
|
4792 |
|
|
break;
|
4793 |
|
|
case DW_OP_call_ref:
|
4794 |
|
|
size += DWARF2_ADDR_SIZE;
|
4795 |
|
|
break;
|
4796 |
|
|
case DW_OP_implicit_value:
|
4797 |
|
|
size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned)
|
4798 |
|
|
+ loc->dw_loc_oprnd1.v.val_unsigned;
|
4799 |
|
|
break;
|
4800 |
|
|
default:
|
4801 |
|
|
break;
|
4802 |
|
|
}
|
4803 |
|
|
|
4804 |
|
|
return size;
|
4805 |
|
|
}
|
4806 |
|
|
|
4807 |
|
|
/* Return the size of a series of location descriptors. */
|
4808 |
|
|
|
4809 |
|
|
static unsigned long
|
4810 |
|
|
size_of_locs (dw_loc_descr_ref loc)
|
4811 |
|
|
{
|
4812 |
|
|
dw_loc_descr_ref l;
|
4813 |
|
|
unsigned long size;
|
4814 |
|
|
|
4815 |
|
|
/* If there are no skip or bra opcodes, don't fill in the dw_loc_addr
|
4816 |
|
|
field, to avoid writing to a PCH file. */
|
4817 |
|
|
for (size = 0, l = loc; l != NULL; l = l->dw_loc_next)
|
4818 |
|
|
{
|
4819 |
|
|
if (l->dw_loc_opc == DW_OP_skip || l->dw_loc_opc == DW_OP_bra)
|
4820 |
|
|
break;
|
4821 |
|
|
size += size_of_loc_descr (l);
|
4822 |
|
|
}
|
4823 |
|
|
if (! l)
|
4824 |
|
|
return size;
|
4825 |
|
|
|
4826 |
|
|
for (size = 0, l = loc; l != NULL; l = l->dw_loc_next)
|
4827 |
|
|
{
|
4828 |
|
|
l->dw_loc_addr = size;
|
4829 |
|
|
size += size_of_loc_descr (l);
|
4830 |
|
|
}
|
4831 |
|
|
|
4832 |
|
|
return size;
|
4833 |
|
|
}
|
4834 |
|
|
|
4835 |
|
|
#ifdef DWARF2_DEBUGGING_INFO
|
4836 |
|
|
static HOST_WIDE_INT extract_int (const unsigned char *, unsigned);
|
4837 |
|
|
#endif
|
4838 |
|
|
|
4839 |
|
|
/* Output location description stack opcode's operands (if any). */
|
4840 |
|
|
|
4841 |
|
|
static void
|
4842 |
|
|
output_loc_operands (dw_loc_descr_ref loc)
|
4843 |
|
|
{
|
4844 |
|
|
dw_val_ref val1 = &loc->dw_loc_oprnd1;
|
4845 |
|
|
dw_val_ref val2 = &loc->dw_loc_oprnd2;
|
4846 |
|
|
|
4847 |
|
|
switch (loc->dw_loc_opc)
|
4848 |
|
|
{
|
4849 |
|
|
#ifdef DWARF2_DEBUGGING_INFO
|
4850 |
|
|
case DW_OP_const2u:
|
4851 |
|
|
case DW_OP_const2s:
|
4852 |
|
|
dw2_asm_output_data (2, val1->v.val_int, NULL);
|
4853 |
|
|
break;
|
4854 |
|
|
case DW_OP_const4u:
|
4855 |
|
|
case DW_OP_const4s:
|
4856 |
|
|
dw2_asm_output_data (4, val1->v.val_int, NULL);
|
4857 |
|
|
break;
|
4858 |
|
|
case DW_OP_const8u:
|
4859 |
|
|
case DW_OP_const8s:
|
4860 |
|
|
gcc_assert (HOST_BITS_PER_WIDE_INT >= 64);
|
4861 |
|
|
dw2_asm_output_data (8, val1->v.val_int, NULL);
|
4862 |
|
|
break;
|
4863 |
|
|
case DW_OP_skip:
|
4864 |
|
|
case DW_OP_bra:
|
4865 |
|
|
{
|
4866 |
|
|
int offset;
|
4867 |
|
|
|
4868 |
|
|
gcc_assert (val1->val_class == dw_val_class_loc);
|
4869 |
|
|
offset = val1->v.val_loc->dw_loc_addr - (loc->dw_loc_addr + 3);
|
4870 |
|
|
|
4871 |
|
|
dw2_asm_output_data (2, offset, NULL);
|
4872 |
|
|
}
|
4873 |
|
|
break;
|
4874 |
|
|
case DW_OP_implicit_value:
|
4875 |
|
|
dw2_asm_output_data_uleb128 (val1->v.val_unsigned, NULL);
|
4876 |
|
|
switch (val2->val_class)
|
4877 |
|
|
{
|
4878 |
|
|
case dw_val_class_const:
|
4879 |
|
|
dw2_asm_output_data (val1->v.val_unsigned, val2->v.val_int, NULL);
|
4880 |
|
|
break;
|
4881 |
|
|
case dw_val_class_vec:
|
4882 |
|
|
{
|
4883 |
|
|
unsigned int elt_size = val2->v.val_vec.elt_size;
|
4884 |
|
|
unsigned int len = val2->v.val_vec.length;
|
4885 |
|
|
unsigned int i;
|
4886 |
|
|
unsigned char *p;
|
4887 |
|
|
|
4888 |
|
|
if (elt_size > sizeof (HOST_WIDE_INT))
|
4889 |
|
|
{
|
4890 |
|
|
elt_size /= 2;
|
4891 |
|
|
len *= 2;
|
4892 |
|
|
}
|
4893 |
|
|
for (i = 0, p = val2->v.val_vec.array;
|
4894 |
|
|
i < len;
|
4895 |
|
|
i++, p += elt_size)
|
4896 |
|
|
dw2_asm_output_data (elt_size, extract_int (p, elt_size),
|
4897 |
|
|
"fp or vector constant word %u", i);
|
4898 |
|
|
}
|
4899 |
|
|
break;
|
4900 |
|
|
case dw_val_class_const_double:
|
4901 |
|
|
{
|
4902 |
|
|
unsigned HOST_WIDE_INT first, second;
|
4903 |
|
|
|
4904 |
|
|
if (WORDS_BIG_ENDIAN)
|
4905 |
|
|
{
|
4906 |
|
|
first = val2->v.val_double.high;
|
4907 |
|
|
second = val2->v.val_double.low;
|
4908 |
|
|
}
|
4909 |
|
|
else
|
4910 |
|
|
{
|
4911 |
|
|
first = val2->v.val_double.low;
|
4912 |
|
|
second = val2->v.val_double.high;
|
4913 |
|
|
}
|
4914 |
|
|
dw2_asm_output_data (HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR,
|
4915 |
|
|
first, NULL);
|
4916 |
|
|
dw2_asm_output_data (HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR,
|
4917 |
|
|
second, NULL);
|
4918 |
|
|
}
|
4919 |
|
|
break;
|
4920 |
|
|
case dw_val_class_addr:
|
4921 |
|
|
gcc_assert (val1->v.val_unsigned == DWARF2_ADDR_SIZE);
|
4922 |
|
|
dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, val2->v.val_addr, NULL);
|
4923 |
|
|
break;
|
4924 |
|
|
default:
|
4925 |
|
|
gcc_unreachable ();
|
4926 |
|
|
}
|
4927 |
|
|
break;
|
4928 |
|
|
#else
|
4929 |
|
|
case DW_OP_const2u:
|
4930 |
|
|
case DW_OP_const2s:
|
4931 |
|
|
case DW_OP_const4u:
|
4932 |
|
|
case DW_OP_const4s:
|
4933 |
|
|
case DW_OP_const8u:
|
4934 |
|
|
case DW_OP_const8s:
|
4935 |
|
|
case DW_OP_skip:
|
4936 |
|
|
case DW_OP_bra:
|
4937 |
|
|
case DW_OP_implicit_value:
|
4938 |
|
|
/* We currently don't make any attempt to make sure these are
|
4939 |
|
|
aligned properly like we do for the main unwind info, so
|
4940 |
|
|
don't support emitting things larger than a byte if we're
|
4941 |
|
|
only doing unwinding. */
|
4942 |
|
|
gcc_unreachable ();
|
4943 |
|
|
#endif
|
4944 |
|
|
case DW_OP_const1u:
|
4945 |
|
|
case DW_OP_const1s:
|
4946 |
|
|
dw2_asm_output_data (1, val1->v.val_int, NULL);
|
4947 |
|
|
break;
|
4948 |
|
|
case DW_OP_constu:
|
4949 |
|
|
dw2_asm_output_data_uleb128 (val1->v.val_unsigned, NULL);
|
4950 |
|
|
break;
|
4951 |
|
|
case DW_OP_consts:
|
4952 |
|
|
dw2_asm_output_data_sleb128 (val1->v.val_int, NULL);
|
4953 |
|
|
break;
|
4954 |
|
|
case DW_OP_pick:
|
4955 |
|
|
dw2_asm_output_data (1, val1->v.val_int, NULL);
|
4956 |
|
|
break;
|
4957 |
|
|
case DW_OP_plus_uconst:
|
4958 |
|
|
dw2_asm_output_data_uleb128 (val1->v.val_unsigned, NULL);
|
4959 |
|
|
break;
|
4960 |
|
|
case DW_OP_breg0:
|
4961 |
|
|
case DW_OP_breg1:
|
4962 |
|
|
case DW_OP_breg2:
|
4963 |
|
|
case DW_OP_breg3:
|
4964 |
|
|
case DW_OP_breg4:
|
4965 |
|
|
case DW_OP_breg5:
|
4966 |
|
|
case DW_OP_breg6:
|
4967 |
|
|
case DW_OP_breg7:
|
4968 |
|
|
case DW_OP_breg8:
|
4969 |
|
|
case DW_OP_breg9:
|
4970 |
|
|
case DW_OP_breg10:
|
4971 |
|
|
case DW_OP_breg11:
|
4972 |
|
|
case DW_OP_breg12:
|
4973 |
|
|
case DW_OP_breg13:
|
4974 |
|
|
case DW_OP_breg14:
|
4975 |
|
|
case DW_OP_breg15:
|
4976 |
|
|
case DW_OP_breg16:
|
4977 |
|
|
case DW_OP_breg17:
|
4978 |
|
|
case DW_OP_breg18:
|
4979 |
|
|
case DW_OP_breg19:
|
4980 |
|
|
case DW_OP_breg20:
|
4981 |
|
|
case DW_OP_breg21:
|
4982 |
|
|
case DW_OP_breg22:
|
4983 |
|
|
case DW_OP_breg23:
|
4984 |
|
|
case DW_OP_breg24:
|
4985 |
|
|
case DW_OP_breg25:
|
4986 |
|
|
case DW_OP_breg26:
|
4987 |
|
|
case DW_OP_breg27:
|
4988 |
|
|
case DW_OP_breg28:
|
4989 |
|
|
case DW_OP_breg29:
|
4990 |
|
|
case DW_OP_breg30:
|
4991 |
|
|
case DW_OP_breg31:
|
4992 |
|
|
dw2_asm_output_data_sleb128 (val1->v.val_int, NULL);
|
4993 |
|
|
break;
|
4994 |
|
|
case DW_OP_regx:
|
4995 |
|
|
dw2_asm_output_data_uleb128 (val1->v.val_unsigned, NULL);
|
4996 |
|
|
break;
|
4997 |
|
|
case DW_OP_fbreg:
|
4998 |
|
|
dw2_asm_output_data_sleb128 (val1->v.val_int, NULL);
|
4999 |
|
|
break;
|
5000 |
|
|
case DW_OP_bregx:
|
5001 |
|
|
dw2_asm_output_data_uleb128 (val1->v.val_unsigned, NULL);
|
5002 |
|
|
dw2_asm_output_data_sleb128 (val2->v.val_int, NULL);
|
5003 |
|
|
break;
|
5004 |
|
|
case DW_OP_piece:
|
5005 |
|
|
dw2_asm_output_data_uleb128 (val1->v.val_unsigned, NULL);
|
5006 |
|
|
break;
|
5007 |
|
|
case DW_OP_deref_size:
|
5008 |
|
|
case DW_OP_xderef_size:
|
5009 |
|
|
dw2_asm_output_data (1, val1->v.val_int, NULL);
|
5010 |
|
|
break;
|
5011 |
|
|
|
5012 |
|
|
case DW_OP_addr:
|
5013 |
|
|
if (loc->dtprel)
|
5014 |
|
|
{
|
5015 |
|
|
if (targetm.asm_out.output_dwarf_dtprel)
|
5016 |
|
|
{
|
5017 |
|
|
targetm.asm_out.output_dwarf_dtprel (asm_out_file,
|
5018 |
|
|
DWARF2_ADDR_SIZE,
|
5019 |
|
|
val1->v.val_addr);
|
5020 |
|
|
fputc ('\n', asm_out_file);
|
5021 |
|
|
}
|
5022 |
|
|
else
|
5023 |
|
|
gcc_unreachable ();
|
5024 |
|
|
}
|
5025 |
|
|
else
|
5026 |
|
|
{
|
5027 |
|
|
#ifdef DWARF2_DEBUGGING_INFO
|
5028 |
|
|
dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, val1->v.val_addr, NULL);
|
5029 |
|
|
#else
|
5030 |
|
|
gcc_unreachable ();
|
5031 |
|
|
#endif
|
5032 |
|
|
}
|
5033 |
|
|
break;
|
5034 |
|
|
|
5035 |
|
|
default:
|
5036 |
|
|
/* Other codes have no operands. */
|
5037 |
|
|
break;
|
5038 |
|
|
}
|
5039 |
|
|
}
|
5040 |
|
|
|
5041 |
|
|
/* Output a sequence of location operations. */
|
5042 |
|
|
|
5043 |
|
|
static void
|
5044 |
|
|
output_loc_sequence (dw_loc_descr_ref loc)
|
5045 |
|
|
{
|
5046 |
|
|
for (; loc != NULL; loc = loc->dw_loc_next)
|
5047 |
|
|
{
|
5048 |
|
|
/* Output the opcode. */
|
5049 |
|
|
dw2_asm_output_data (1, loc->dw_loc_opc,
|
5050 |
|
|
"%s", dwarf_stack_op_name (loc->dw_loc_opc));
|
5051 |
|
|
|
5052 |
|
|
/* Output the operand(s) (if any). */
|
5053 |
|
|
output_loc_operands (loc);
|
5054 |
|
|
}
|
5055 |
|
|
}
|
5056 |
|
|
|
5057 |
|
|
/* Output location description stack opcode's operands (if any).
|
5058 |
|
|
The output is single bytes on a line, suitable for .cfi_escape. */
|
5059 |
|
|
|
5060 |
|
|
static void
|
5061 |
|
|
output_loc_operands_raw (dw_loc_descr_ref loc)
|
5062 |
|
|
{
|
5063 |
|
|
dw_val_ref val1 = &loc->dw_loc_oprnd1;
|
5064 |
|
|
dw_val_ref val2 = &loc->dw_loc_oprnd2;
|
5065 |
|
|
|
5066 |
|
|
switch (loc->dw_loc_opc)
|
5067 |
|
|
{
|
5068 |
|
|
case DW_OP_addr:
|
5069 |
|
|
case DW_OP_implicit_value:
|
5070 |
|
|
/* We cannot output addresses in .cfi_escape, only bytes. */
|
5071 |
|
|
gcc_unreachable ();
|
5072 |
|
|
|
5073 |
|
|
case DW_OP_const1u:
|
5074 |
|
|
case DW_OP_const1s:
|
5075 |
|
|
case DW_OP_pick:
|
5076 |
|
|
case DW_OP_deref_size:
|
5077 |
|
|
case DW_OP_xderef_size:
|
5078 |
|
|
fputc (',', asm_out_file);
|
5079 |
|
|
dw2_asm_output_data_raw (1, val1->v.val_int);
|
5080 |
|
|
break;
|
5081 |
|
|
|
5082 |
|
|
case DW_OP_const2u:
|
5083 |
|
|
case DW_OP_const2s:
|
5084 |
|
|
fputc (',', asm_out_file);
|
5085 |
|
|
dw2_asm_output_data_raw (2, val1->v.val_int);
|
5086 |
|
|
break;
|
5087 |
|
|
|
5088 |
|
|
case DW_OP_const4u:
|
5089 |
|
|
case DW_OP_const4s:
|
5090 |
|
|
fputc (',', asm_out_file);
|
5091 |
|
|
dw2_asm_output_data_raw (4, val1->v.val_int);
|
5092 |
|
|
break;
|
5093 |
|
|
|
5094 |
|
|
case DW_OP_const8u:
|
5095 |
|
|
case DW_OP_const8s:
|
5096 |
|
|
gcc_assert (HOST_BITS_PER_WIDE_INT >= 64);
|
5097 |
|
|
fputc (',', asm_out_file);
|
5098 |
|
|
dw2_asm_output_data_raw (8, val1->v.val_int);
|
5099 |
|
|
break;
|
5100 |
|
|
|
5101 |
|
|
case DW_OP_skip:
|
5102 |
|
|
case DW_OP_bra:
|
5103 |
|
|
{
|
5104 |
|
|
int offset;
|
5105 |
|
|
|
5106 |
|
|
gcc_assert (val1->val_class == dw_val_class_loc);
|
5107 |
|
|
offset = val1->v.val_loc->dw_loc_addr - (loc->dw_loc_addr + 3);
|
5108 |
|
|
|
5109 |
|
|
fputc (',', asm_out_file);
|
5110 |
|
|
dw2_asm_output_data_raw (2, offset);
|
5111 |
|
|
}
|
5112 |
|
|
break;
|
5113 |
|
|
|
5114 |
|
|
case DW_OP_constu:
|
5115 |
|
|
case DW_OP_plus_uconst:
|
5116 |
|
|
case DW_OP_regx:
|
5117 |
|
|
case DW_OP_piece:
|
5118 |
|
|
fputc (',', asm_out_file);
|
5119 |
|
|
dw2_asm_output_data_uleb128_raw (val1->v.val_unsigned);
|
5120 |
|
|
break;
|
5121 |
|
|
|
5122 |
|
|
case DW_OP_consts:
|
5123 |
|
|
case DW_OP_breg0:
|
5124 |
|
|
case DW_OP_breg1:
|
5125 |
|
|
case DW_OP_breg2:
|
5126 |
|
|
case DW_OP_breg3:
|
5127 |
|
|
case DW_OP_breg4:
|
5128 |
|
|
case DW_OP_breg5:
|
5129 |
|
|
case DW_OP_breg6:
|
5130 |
|
|
case DW_OP_breg7:
|
5131 |
|
|
case DW_OP_breg8:
|
5132 |
|
|
case DW_OP_breg9:
|
5133 |
|
|
case DW_OP_breg10:
|
5134 |
|
|
case DW_OP_breg11:
|
5135 |
|
|
case DW_OP_breg12:
|
5136 |
|
|
case DW_OP_breg13:
|
5137 |
|
|
case DW_OP_breg14:
|
5138 |
|
|
case DW_OP_breg15:
|
5139 |
|
|
case DW_OP_breg16:
|
5140 |
|
|
case DW_OP_breg17:
|
5141 |
|
|
case DW_OP_breg18:
|
5142 |
|
|
case DW_OP_breg19:
|
5143 |
|
|
case DW_OP_breg20:
|
5144 |
|
|
case DW_OP_breg21:
|
5145 |
|
|
case DW_OP_breg22:
|
5146 |
|
|
case DW_OP_breg23:
|
5147 |
|
|
case DW_OP_breg24:
|
5148 |
|
|
case DW_OP_breg25:
|
5149 |
|
|
case DW_OP_breg26:
|
5150 |
|
|
case DW_OP_breg27:
|
5151 |
|
|
case DW_OP_breg28:
|
5152 |
|
|
case DW_OP_breg29:
|
5153 |
|
|
case DW_OP_breg30:
|
5154 |
|
|
case DW_OP_breg31:
|
5155 |
|
|
case DW_OP_fbreg:
|
5156 |
|
|
fputc (',', asm_out_file);
|
5157 |
|
|
dw2_asm_output_data_sleb128_raw (val1->v.val_int);
|
5158 |
|
|
break;
|
5159 |
|
|
|
5160 |
|
|
case DW_OP_bregx:
|
5161 |
|
|
fputc (',', asm_out_file);
|
5162 |
|
|
dw2_asm_output_data_uleb128_raw (val1->v.val_unsigned);
|
5163 |
|
|
fputc (',', asm_out_file);
|
5164 |
|
|
dw2_asm_output_data_sleb128_raw (val2->v.val_int);
|
5165 |
|
|
break;
|
5166 |
|
|
|
5167 |
|
|
default:
|
5168 |
|
|
/* Other codes have no operands. */
|
5169 |
|
|
break;
|
5170 |
|
|
}
|
5171 |
|
|
}
|
5172 |
|
|
|
5173 |
|
|
static void
|
5174 |
|
|
output_loc_sequence_raw (dw_loc_descr_ref loc)
|
5175 |
|
|
{
|
5176 |
|
|
while (1)
|
5177 |
|
|
{
|
5178 |
|
|
/* Output the opcode. */
|
5179 |
|
|
fprintf (asm_out_file, "0x%x", loc->dw_loc_opc);
|
5180 |
|
|
output_loc_operands_raw (loc);
|
5181 |
|
|
|
5182 |
|
|
if (!loc->dw_loc_next)
|
5183 |
|
|
break;
|
5184 |
|
|
loc = loc->dw_loc_next;
|
5185 |
|
|
|
5186 |
|
|
fputc (',', asm_out_file);
|
5187 |
|
|
}
|
5188 |
|
|
}
|
5189 |
|
|
|
5190 |
|
|
/* This routine will generate the correct assembly data for a location
|
5191 |
|
|
description based on a cfi entry with a complex address. */
|
5192 |
|
|
|
5193 |
|
|
static void
|
5194 |
|
|
output_cfa_loc (dw_cfi_ref cfi)
|
5195 |
|
|
{
|
5196 |
|
|
dw_loc_descr_ref loc;
|
5197 |
|
|
unsigned long size;
|
5198 |
|
|
|
5199 |
|
|
if (cfi->dw_cfi_opc == DW_CFA_expression)
|
5200 |
|
|
{
|
5201 |
|
|
dw2_asm_output_data (1, cfi->dw_cfi_oprnd1.dw_cfi_reg_num, NULL);
|
5202 |
|
|
loc = cfi->dw_cfi_oprnd2.dw_cfi_loc;
|
5203 |
|
|
}
|
5204 |
|
|
else
|
5205 |
|
|
loc = cfi->dw_cfi_oprnd1.dw_cfi_loc;
|
5206 |
|
|
|
5207 |
|
|
/* Output the size of the block. */
|
5208 |
|
|
size = size_of_locs (loc);
|
5209 |
|
|
dw2_asm_output_data_uleb128 (size, NULL);
|
5210 |
|
|
|
5211 |
|
|
/* Now output the operations themselves. */
|
5212 |
|
|
output_loc_sequence (loc);
|
5213 |
|
|
}
|
5214 |
|
|
|
5215 |
|
|
/* Similar, but used for .cfi_escape. */
|
5216 |
|
|
|
5217 |
|
|
static void
|
5218 |
|
|
output_cfa_loc_raw (dw_cfi_ref cfi)
|
5219 |
|
|
{
|
5220 |
|
|
dw_loc_descr_ref loc;
|
5221 |
|
|
unsigned long size;
|
5222 |
|
|
|
5223 |
|
|
if (cfi->dw_cfi_opc == DW_CFA_expression)
|
5224 |
|
|
{
|
5225 |
|
|
fprintf (asm_out_file, "0x%x,", cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
|
5226 |
|
|
loc = cfi->dw_cfi_oprnd2.dw_cfi_loc;
|
5227 |
|
|
}
|
5228 |
|
|
else
|
5229 |
|
|
loc = cfi->dw_cfi_oprnd1.dw_cfi_loc;
|
5230 |
|
|
|
5231 |
|
|
/* Output the size of the block. */
|
5232 |
|
|
size = size_of_locs (loc);
|
5233 |
|
|
dw2_asm_output_data_uleb128_raw (size);
|
5234 |
|
|
fputc (',', asm_out_file);
|
5235 |
|
|
|
5236 |
|
|
/* Now output the operations themselves. */
|
5237 |
|
|
output_loc_sequence_raw (loc);
|
5238 |
|
|
}
|
5239 |
|
|
|
5240 |
|
|
/* This function builds a dwarf location descriptor sequence from a
|
5241 |
|
|
dw_cfa_location, adding the given OFFSET to the result of the
|
5242 |
|
|
expression. */
|
5243 |
|
|
|
5244 |
|
|
static struct dw_loc_descr_struct *
|
5245 |
|
|
build_cfa_loc (dw_cfa_location *cfa, HOST_WIDE_INT offset)
|
5246 |
|
|
{
|
5247 |
|
|
struct dw_loc_descr_struct *head, *tmp;
|
5248 |
|
|
|
5249 |
|
|
offset += cfa->offset;
|
5250 |
|
|
|
5251 |
|
|
if (cfa->indirect)
|
5252 |
|
|
{
|
5253 |
|
|
head = new_reg_loc_descr (cfa->reg, cfa->base_offset);
|
5254 |
|
|
head->dw_loc_oprnd1.val_class = dw_val_class_const;
|
5255 |
|
|
tmp = new_loc_descr (DW_OP_deref, 0, 0);
|
5256 |
|
|
add_loc_descr (&head, tmp);
|
5257 |
|
|
if (offset != 0)
|
5258 |
|
|
{
|
5259 |
|
|
tmp = new_loc_descr (DW_OP_plus_uconst, offset, 0);
|
5260 |
|
|
add_loc_descr (&head, tmp);
|
5261 |
|
|
}
|
5262 |
|
|
}
|
5263 |
|
|
else
|
5264 |
|
|
head = new_reg_loc_descr (cfa->reg, offset);
|
5265 |
|
|
|
5266 |
|
|
return head;
|
5267 |
|
|
}
|
5268 |
|
|
|
5269 |
|
|
/* This function builds a dwarf location descriptor sequence for
|
5270 |
|
|
the address at OFFSET from the CFA when stack is aligned to
|
5271 |
|
|
ALIGNMENT byte. */
|
5272 |
|
|
|
5273 |
|
|
static struct dw_loc_descr_struct *
|
5274 |
|
|
build_cfa_aligned_loc (HOST_WIDE_INT offset, HOST_WIDE_INT alignment)
|
5275 |
|
|
{
|
5276 |
|
|
struct dw_loc_descr_struct *head;
|
5277 |
|
|
unsigned int dwarf_fp
|
5278 |
|
|
= DWARF_FRAME_REGNUM (HARD_FRAME_POINTER_REGNUM);
|
5279 |
|
|
|
5280 |
|
|
/* When CFA is defined as FP+OFFSET, emulate stack alignment. */
|
5281 |
|
|
if (cfa.reg == HARD_FRAME_POINTER_REGNUM && cfa.indirect == 0)
|
5282 |
|
|
{
|
5283 |
|
|
head = new_reg_loc_descr (dwarf_fp, 0);
|
5284 |
|
|
add_loc_descr (&head, int_loc_descriptor (alignment));
|
5285 |
|
|
add_loc_descr (&head, new_loc_descr (DW_OP_and, 0, 0));
|
5286 |
|
|
loc_descr_plus_const (&head, offset);
|
5287 |
|
|
}
|
5288 |
|
|
else
|
5289 |
|
|
head = new_reg_loc_descr (dwarf_fp, offset);
|
5290 |
|
|
return head;
|
5291 |
|
|
}
|
5292 |
|
|
|
5293 |
|
|
/* This function fills in aa dw_cfa_location structure from a dwarf location
|
5294 |
|
|
descriptor sequence. */
|
5295 |
|
|
|
5296 |
|
|
static void
|
5297 |
|
|
get_cfa_from_loc_descr (dw_cfa_location *cfa, struct dw_loc_descr_struct *loc)
|
5298 |
|
|
{
|
5299 |
|
|
struct dw_loc_descr_struct *ptr;
|
5300 |
|
|
cfa->offset = 0;
|
5301 |
|
|
cfa->base_offset = 0;
|
5302 |
|
|
cfa->indirect = 0;
|
5303 |
|
|
cfa->reg = -1;
|
5304 |
|
|
|
5305 |
|
|
for (ptr = loc; ptr != NULL; ptr = ptr->dw_loc_next)
|
5306 |
|
|
{
|
5307 |
|
|
enum dwarf_location_atom op = ptr->dw_loc_opc;
|
5308 |
|
|
|
5309 |
|
|
switch (op)
|
5310 |
|
|
{
|
5311 |
|
|
case DW_OP_reg0:
|
5312 |
|
|
case DW_OP_reg1:
|
5313 |
|
|
case DW_OP_reg2:
|
5314 |
|
|
case DW_OP_reg3:
|
5315 |
|
|
case DW_OP_reg4:
|
5316 |
|
|
case DW_OP_reg5:
|
5317 |
|
|
case DW_OP_reg6:
|
5318 |
|
|
case DW_OP_reg7:
|
5319 |
|
|
case DW_OP_reg8:
|
5320 |
|
|
case DW_OP_reg9:
|
5321 |
|
|
case DW_OP_reg10:
|
5322 |
|
|
case DW_OP_reg11:
|
5323 |
|
|
case DW_OP_reg12:
|
5324 |
|
|
case DW_OP_reg13:
|
5325 |
|
|
case DW_OP_reg14:
|
5326 |
|
|
case DW_OP_reg15:
|
5327 |
|
|
case DW_OP_reg16:
|
5328 |
|
|
case DW_OP_reg17:
|
5329 |
|
|
case DW_OP_reg18:
|
5330 |
|
|
case DW_OP_reg19:
|
5331 |
|
|
case DW_OP_reg20:
|
5332 |
|
|
case DW_OP_reg21:
|
5333 |
|
|
case DW_OP_reg22:
|
5334 |
|
|
case DW_OP_reg23:
|
5335 |
|
|
case DW_OP_reg24:
|
5336 |
|
|
case DW_OP_reg25:
|
5337 |
|
|
case DW_OP_reg26:
|
5338 |
|
|
case DW_OP_reg27:
|
5339 |
|
|
case DW_OP_reg28:
|
5340 |
|
|
case DW_OP_reg29:
|
5341 |
|
|
case DW_OP_reg30:
|
5342 |
|
|
case DW_OP_reg31:
|
5343 |
|
|
cfa->reg = op - DW_OP_reg0;
|
5344 |
|
|
break;
|
5345 |
|
|
case DW_OP_regx:
|
5346 |
|
|
cfa->reg = ptr->dw_loc_oprnd1.v.val_int;
|
5347 |
|
|
break;
|
5348 |
|
|
case DW_OP_breg0:
|
5349 |
|
|
case DW_OP_breg1:
|
5350 |
|
|
case DW_OP_breg2:
|
5351 |
|
|
case DW_OP_breg3:
|
5352 |
|
|
case DW_OP_breg4:
|
5353 |
|
|
case DW_OP_breg5:
|
5354 |
|
|
case DW_OP_breg6:
|
5355 |
|
|
case DW_OP_breg7:
|
5356 |
|
|
case DW_OP_breg8:
|
5357 |
|
|
case DW_OP_breg9:
|
5358 |
|
|
case DW_OP_breg10:
|
5359 |
|
|
case DW_OP_breg11:
|
5360 |
|
|
case DW_OP_breg12:
|
5361 |
|
|
case DW_OP_breg13:
|
5362 |
|
|
case DW_OP_breg14:
|
5363 |
|
|
case DW_OP_breg15:
|
5364 |
|
|
case DW_OP_breg16:
|
5365 |
|
|
case DW_OP_breg17:
|
5366 |
|
|
case DW_OP_breg18:
|
5367 |
|
|
case DW_OP_breg19:
|
5368 |
|
|
case DW_OP_breg20:
|
5369 |
|
|
case DW_OP_breg21:
|
5370 |
|
|
case DW_OP_breg22:
|
5371 |
|
|
case DW_OP_breg23:
|
5372 |
|
|
case DW_OP_breg24:
|
5373 |
|
|
case DW_OP_breg25:
|
5374 |
|
|
case DW_OP_breg26:
|
5375 |
|
|
case DW_OP_breg27:
|
5376 |
|
|
case DW_OP_breg28:
|
5377 |
|
|
case DW_OP_breg29:
|
5378 |
|
|
case DW_OP_breg30:
|
5379 |
|
|
case DW_OP_breg31:
|
5380 |
|
|
cfa->reg = op - DW_OP_breg0;
|
5381 |
|
|
cfa->base_offset = ptr->dw_loc_oprnd1.v.val_int;
|
5382 |
|
|
break;
|
5383 |
|
|
case DW_OP_bregx:
|
5384 |
|
|
cfa->reg = ptr->dw_loc_oprnd1.v.val_int;
|
5385 |
|
|
cfa->base_offset = ptr->dw_loc_oprnd2.v.val_int;
|
5386 |
|
|
break;
|
5387 |
|
|
case DW_OP_deref:
|
5388 |
|
|
cfa->indirect = 1;
|
5389 |
|
|
break;
|
5390 |
|
|
case DW_OP_plus_uconst:
|
5391 |
|
|
cfa->offset = ptr->dw_loc_oprnd1.v.val_unsigned;
|
5392 |
|
|
break;
|
5393 |
|
|
default:
|
5394 |
|
|
internal_error ("DW_LOC_OP %s not implemented",
|
5395 |
|
|
dwarf_stack_op_name (ptr->dw_loc_opc));
|
5396 |
|
|
}
|
5397 |
|
|
}
|
5398 |
|
|
}
|
5399 |
|
|
#endif /* .debug_frame support */
|
5400 |
|
|
|
5401 |
|
|
/* And now, the support for symbolic debugging information. */
|
5402 |
|
|
#ifdef DWARF2_DEBUGGING_INFO
|
5403 |
|
|
|
5404 |
|
|
/* .debug_str support. */
|
5405 |
|
|
static int output_indirect_string (void **, void *);
|
5406 |
|
|
|
5407 |
|
|
static void dwarf2out_init (const char *);
|
5408 |
|
|
static void dwarf2out_finish (const char *);
|
5409 |
|
|
static void dwarf2out_assembly_start (void);
|
5410 |
|
|
static void dwarf2out_define (unsigned int, const char *);
|
5411 |
|
|
static void dwarf2out_undef (unsigned int, const char *);
|
5412 |
|
|
static void dwarf2out_start_source_file (unsigned, const char *);
|
5413 |
|
|
static void dwarf2out_end_source_file (unsigned);
|
5414 |
|
|
static void dwarf2out_function_decl (tree);
|
5415 |
|
|
static void dwarf2out_begin_block (unsigned, unsigned);
|
5416 |
|
|
static void dwarf2out_end_block (unsigned, unsigned);
|
5417 |
|
|
static bool dwarf2out_ignore_block (const_tree);
|
5418 |
|
|
static void dwarf2out_global_decl (tree);
|
5419 |
|
|
static void dwarf2out_type_decl (tree, int);
|
5420 |
|
|
static void dwarf2out_imported_module_or_decl (tree, tree, tree, bool);
|
5421 |
|
|
static void dwarf2out_imported_module_or_decl_1 (tree, tree, tree,
|
5422 |
|
|
dw_die_ref);
|
5423 |
|
|
static void dwarf2out_abstract_function (tree);
|
5424 |
|
|
static void dwarf2out_var_location (rtx);
|
5425 |
|
|
static void dwarf2out_direct_call (tree);
|
5426 |
|
|
static void dwarf2out_virtual_call_token (tree, int);
|
5427 |
|
|
static void dwarf2out_copy_call_info (rtx, rtx);
|
5428 |
|
|
static void dwarf2out_virtual_call (int);
|
5429 |
|
|
static void dwarf2out_begin_function (tree);
|
5430 |
|
|
static void dwarf2out_set_name (tree, tree);
|
5431 |
|
|
|
5432 |
|
|
/* The debug hooks structure. */
|
5433 |
|
|
|
5434 |
|
|
const struct gcc_debug_hooks dwarf2_debug_hooks =
|
5435 |
|
|
{
|
5436 |
|
|
dwarf2out_init,
|
5437 |
|
|
dwarf2out_finish,
|
5438 |
|
|
dwarf2out_assembly_start,
|
5439 |
|
|
dwarf2out_define,
|
5440 |
|
|
dwarf2out_undef,
|
5441 |
|
|
dwarf2out_start_source_file,
|
5442 |
|
|
dwarf2out_end_source_file,
|
5443 |
|
|
dwarf2out_begin_block,
|
5444 |
|
|
dwarf2out_end_block,
|
5445 |
|
|
dwarf2out_ignore_block,
|
5446 |
|
|
dwarf2out_source_line,
|
5447 |
|
|
dwarf2out_begin_prologue,
|
5448 |
|
|
debug_nothing_int_charstar, /* end_prologue */
|
5449 |
|
|
dwarf2out_end_epilogue,
|
5450 |
|
|
dwarf2out_begin_function,
|
5451 |
|
|
debug_nothing_int, /* end_function */
|
5452 |
|
|
dwarf2out_function_decl, /* function_decl */
|
5453 |
|
|
dwarf2out_global_decl,
|
5454 |
|
|
dwarf2out_type_decl, /* type_decl */
|
5455 |
|
|
dwarf2out_imported_module_or_decl,
|
5456 |
|
|
debug_nothing_tree, /* deferred_inline_function */
|
5457 |
|
|
/* The DWARF 2 backend tries to reduce debugging bloat by not
|
5458 |
|
|
emitting the abstract description of inline functions until
|
5459 |
|
|
something tries to reference them. */
|
5460 |
|
|
dwarf2out_abstract_function, /* outlining_inline_function */
|
5461 |
|
|
debug_nothing_rtx, /* label */
|
5462 |
|
|
debug_nothing_int, /* handle_pch */
|
5463 |
|
|
dwarf2out_var_location,
|
5464 |
|
|
dwarf2out_switch_text_section,
|
5465 |
|
|
dwarf2out_direct_call,
|
5466 |
|
|
dwarf2out_virtual_call_token,
|
5467 |
|
|
dwarf2out_copy_call_info,
|
5468 |
|
|
dwarf2out_virtual_call,
|
5469 |
|
|
dwarf2out_set_name,
|
5470 |
|
|
1 /* start_end_main_source_file */
|
5471 |
|
|
};
|
5472 |
|
|
#endif
|
5473 |
|
|
|
5474 |
|
|
/* NOTE: In the comments in this file, many references are made to
|
5475 |
|
|
"Debugging Information Entries". This term is abbreviated as `DIE'
|
5476 |
|
|
throughout the remainder of this file. */
|
5477 |
|
|
|
5478 |
|
|
/* An internal representation of the DWARF output is built, and then
|
5479 |
|
|
walked to generate the DWARF debugging info. The walk of the internal
|
5480 |
|
|
representation is done after the entire program has been compiled.
|
5481 |
|
|
The types below are used to describe the internal representation. */
|
5482 |
|
|
|
5483 |
|
|
/* Various DIE's use offsets relative to the beginning of the
|
5484 |
|
|
.debug_info section to refer to each other. */
|
5485 |
|
|
|
5486 |
|
|
typedef long int dw_offset;
|
5487 |
|
|
|
5488 |
|
|
/* Define typedefs here to avoid circular dependencies. */
|
5489 |
|
|
|
5490 |
|
|
typedef struct dw_attr_struct *dw_attr_ref;
|
5491 |
|
|
typedef struct dw_line_info_struct *dw_line_info_ref;
|
5492 |
|
|
typedef struct dw_separate_line_info_struct *dw_separate_line_info_ref;
|
5493 |
|
|
typedef struct pubname_struct *pubname_ref;
|
5494 |
|
|
typedef struct dw_ranges_struct *dw_ranges_ref;
|
5495 |
|
|
typedef struct dw_ranges_by_label_struct *dw_ranges_by_label_ref;
|
5496 |
|
|
typedef struct comdat_type_struct *comdat_type_node_ref;
|
5497 |
|
|
|
5498 |
|
|
/* Each entry in the line_info_table maintains the file and
|
5499 |
|
|
line number associated with the label generated for that
|
5500 |
|
|
entry. The label gives the PC value associated with
|
5501 |
|
|
the line number entry. */
|
5502 |
|
|
|
5503 |
|
|
typedef struct GTY(()) dw_line_info_struct {
|
5504 |
|
|
unsigned long dw_file_num;
|
5505 |
|
|
unsigned long dw_line_num;
|
5506 |
|
|
}
|
5507 |
|
|
dw_line_info_entry;
|
5508 |
|
|
|
5509 |
|
|
/* Line information for functions in separate sections; each one gets its
|
5510 |
|
|
own sequence. */
|
5511 |
|
|
typedef struct GTY(()) dw_separate_line_info_struct {
|
5512 |
|
|
unsigned long dw_file_num;
|
5513 |
|
|
unsigned long dw_line_num;
|
5514 |
|
|
unsigned long function;
|
5515 |
|
|
}
|
5516 |
|
|
dw_separate_line_info_entry;
|
5517 |
|
|
|
5518 |
|
|
/* Each DIE attribute has a field specifying the attribute kind,
|
5519 |
|
|
a link to the next attribute in the chain, and an attribute value.
|
5520 |
|
|
Attributes are typically linked below the DIE they modify. */
|
5521 |
|
|
|
5522 |
|
|
typedef struct GTY(()) dw_attr_struct {
|
5523 |
|
|
enum dwarf_attribute dw_attr;
|
5524 |
|
|
dw_val_node dw_attr_val;
|
5525 |
|
|
}
|
5526 |
|
|
dw_attr_node;
|
5527 |
|
|
|
5528 |
|
|
DEF_VEC_O(dw_attr_node);
|
5529 |
|
|
DEF_VEC_ALLOC_O(dw_attr_node,gc);
|
5530 |
|
|
|
5531 |
|
|
/* The Debugging Information Entry (DIE) structure. DIEs form a tree.
|
5532 |
|
|
The children of each node form a circular list linked by
|
5533 |
|
|
die_sib. die_child points to the node *before* the "first" child node. */
|
5534 |
|
|
|
5535 |
|
|
typedef struct GTY((chain_circular ("%h.die_sib"))) die_struct {
|
5536 |
|
|
enum dwarf_tag die_tag;
|
5537 |
|
|
union die_symbol_or_type_node
|
5538 |
|
|
{
|
5539 |
|
|
char * GTY ((tag ("0"))) die_symbol;
|
5540 |
|
|
comdat_type_node_ref GTY ((tag ("1"))) die_type_node;
|
5541 |
|
|
}
|
5542 |
|
|
GTY ((desc ("dwarf_version >= 4"))) die_id;
|
5543 |
|
|
VEC(dw_attr_node,gc) * die_attr;
|
5544 |
|
|
dw_die_ref die_parent;
|
5545 |
|
|
dw_die_ref die_child;
|
5546 |
|
|
dw_die_ref die_sib;
|
5547 |
|
|
dw_die_ref die_definition; /* ref from a specification to its definition */
|
5548 |
|
|
dw_offset die_offset;
|
5549 |
|
|
unsigned long die_abbrev;
|
5550 |
|
|
int die_mark;
|
5551 |
|
|
/* Die is used and must not be pruned as unused. */
|
5552 |
|
|
int die_perennial_p;
|
5553 |
|
|
unsigned int decl_id;
|
5554 |
|
|
}
|
5555 |
|
|
die_node;
|
5556 |
|
|
|
5557 |
|
|
/* Evaluate 'expr' while 'c' is set to each child of DIE in order. */
|
5558 |
|
|
#define FOR_EACH_CHILD(die, c, expr) do { \
|
5559 |
|
|
c = die->die_child; \
|
5560 |
|
|
if (c) do { \
|
5561 |
|
|
c = c->die_sib; \
|
5562 |
|
|
expr; \
|
5563 |
|
|
} while (c != die->die_child); \
|
5564 |
|
|
} while (0)
|
5565 |
|
|
|
5566 |
|
|
/* The pubname structure */
|
5567 |
|
|
|
5568 |
|
|
typedef struct GTY(()) pubname_struct {
|
5569 |
|
|
dw_die_ref die;
|
5570 |
|
|
const char *name;
|
5571 |
|
|
}
|
5572 |
|
|
pubname_entry;
|
5573 |
|
|
|
5574 |
|
|
DEF_VEC_O(pubname_entry);
|
5575 |
|
|
DEF_VEC_ALLOC_O(pubname_entry, gc);
|
5576 |
|
|
|
5577 |
|
|
struct GTY(()) dw_ranges_struct {
|
5578 |
|
|
/* If this is positive, it's a block number, otherwise it's a
|
5579 |
|
|
bitwise-negated index into dw_ranges_by_label. */
|
5580 |
|
|
int num;
|
5581 |
|
|
};
|
5582 |
|
|
|
5583 |
|
|
struct GTY(()) dw_ranges_by_label_struct {
|
5584 |
|
|
const char *begin;
|
5585 |
|
|
const char *end;
|
5586 |
|
|
};
|
5587 |
|
|
|
5588 |
|
|
/* The comdat type node structure. */
|
5589 |
|
|
typedef struct GTY(()) comdat_type_struct
|
5590 |
|
|
{
|
5591 |
|
|
dw_die_ref root_die;
|
5592 |
|
|
dw_die_ref type_die;
|
5593 |
|
|
char signature[DWARF_TYPE_SIGNATURE_SIZE];
|
5594 |
|
|
struct comdat_type_struct *next;
|
5595 |
|
|
}
|
5596 |
|
|
comdat_type_node;
|
5597 |
|
|
|
5598 |
|
|
/* The limbo die list structure. */
|
5599 |
|
|
typedef struct GTY(()) limbo_die_struct {
|
5600 |
|
|
dw_die_ref die;
|
5601 |
|
|
tree created_for;
|
5602 |
|
|
struct limbo_die_struct *next;
|
5603 |
|
|
}
|
5604 |
|
|
limbo_die_node;
|
5605 |
|
|
|
5606 |
|
|
typedef struct GTY(()) skeleton_chain_struct
|
5607 |
|
|
{
|
5608 |
|
|
dw_die_ref old_die;
|
5609 |
|
|
dw_die_ref new_die;
|
5610 |
|
|
struct skeleton_chain_struct *parent;
|
5611 |
|
|
}
|
5612 |
|
|
skeleton_chain_node;
|
5613 |
|
|
|
5614 |
|
|
/* How to start an assembler comment. */
|
5615 |
|
|
#ifndef ASM_COMMENT_START
|
5616 |
|
|
#define ASM_COMMENT_START ";#"
|
5617 |
|
|
#endif
|
5618 |
|
|
|
5619 |
|
|
/* Define a macro which returns nonzero for a TYPE_DECL which was
|
5620 |
|
|
implicitly generated for a tagged type.
|
5621 |
|
|
|
5622 |
|
|
Note that unlike the gcc front end (which generates a NULL named
|
5623 |
|
|
TYPE_DECL node for each complete tagged type, each array type, and
|
5624 |
|
|
each function type node created) the g++ front end generates a
|
5625 |
|
|
_named_ TYPE_DECL node for each tagged type node created.
|
5626 |
|
|
These TYPE_DECLs have DECL_ARTIFICIAL set, so we know not to
|
5627 |
|
|
generate a DW_TAG_typedef DIE for them. */
|
5628 |
|
|
|
5629 |
|
|
#define TYPE_DECL_IS_STUB(decl) \
|
5630 |
|
|
(DECL_NAME (decl) == NULL_TREE \
|
5631 |
|
|
|| (DECL_ARTIFICIAL (decl) \
|
5632 |
|
|
&& is_tagged_type (TREE_TYPE (decl)) \
|
5633 |
|
|
&& ((decl == TYPE_STUB_DECL (TREE_TYPE (decl))) \
|
5634 |
|
|
/* This is necessary for stub decls that \
|
5635 |
|
|
appear in nested inline functions. */ \
|
5636 |
|
|
|| (DECL_ABSTRACT_ORIGIN (decl) != NULL_TREE \
|
5637 |
|
|
&& (decl_ultimate_origin (decl) \
|
5638 |
|
|
== TYPE_STUB_DECL (TREE_TYPE (decl)))))))
|
5639 |
|
|
|
5640 |
|
|
/* Information concerning the compilation unit's programming
|
5641 |
|
|
language, and compiler version. */
|
5642 |
|
|
|
5643 |
|
|
/* Fixed size portion of the DWARF compilation unit header. */
|
5644 |
|
|
#define DWARF_COMPILE_UNIT_HEADER_SIZE \
|
5645 |
|
|
(DWARF_INITIAL_LENGTH_SIZE + DWARF_OFFSET_SIZE + 3)
|
5646 |
|
|
|
5647 |
|
|
/* Fixed size portion of the DWARF comdat type unit header. */
|
5648 |
|
|
#define DWARF_COMDAT_TYPE_UNIT_HEADER_SIZE \
|
5649 |
|
|
(DWARF_COMPILE_UNIT_HEADER_SIZE + DWARF_TYPE_SIGNATURE_SIZE \
|
5650 |
|
|
+ DWARF_OFFSET_SIZE)
|
5651 |
|
|
|
5652 |
|
|
/* Fixed size portion of public names info. */
|
5653 |
|
|
#define DWARF_PUBNAMES_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 2)
|
5654 |
|
|
|
5655 |
|
|
/* Fixed size portion of the address range info. */
|
5656 |
|
|
#define DWARF_ARANGES_HEADER_SIZE \
|
5657 |
|
|
(DWARF_ROUND (DWARF_INITIAL_LENGTH_SIZE + DWARF_OFFSET_SIZE + 4, \
|
5658 |
|
|
DWARF2_ADDR_SIZE * 2) \
|
5659 |
|
|
- DWARF_INITIAL_LENGTH_SIZE)
|
5660 |
|
|
|
5661 |
|
|
/* Size of padding portion in the address range info. It must be
|
5662 |
|
|
aligned to twice the pointer size. */
|
5663 |
|
|
#define DWARF_ARANGES_PAD_SIZE \
|
5664 |
|
|
(DWARF_ROUND (DWARF_INITIAL_LENGTH_SIZE + DWARF_OFFSET_SIZE + 4, \
|
5665 |
|
|
DWARF2_ADDR_SIZE * 2) \
|
5666 |
|
|
- (DWARF_INITIAL_LENGTH_SIZE + DWARF_OFFSET_SIZE + 4))
|
5667 |
|
|
|
5668 |
|
|
/* Use assembler line directives if available. */
|
5669 |
|
|
#ifndef DWARF2_ASM_LINE_DEBUG_INFO
|
5670 |
|
|
#ifdef HAVE_AS_DWARF2_DEBUG_LINE
|
5671 |
|
|
#define DWARF2_ASM_LINE_DEBUG_INFO 1
|
5672 |
|
|
#else
|
5673 |
|
|
#define DWARF2_ASM_LINE_DEBUG_INFO 0
|
5674 |
|
|
#endif
|
5675 |
|
|
#endif
|
5676 |
|
|
|
5677 |
|
|
/* Minimum line offset in a special line info. opcode.
|
5678 |
|
|
This value was chosen to give a reasonable range of values. */
|
5679 |
|
|
#define DWARF_LINE_BASE -10
|
5680 |
|
|
|
5681 |
|
|
/* First special line opcode - leave room for the standard opcodes. */
|
5682 |
|
|
#define DWARF_LINE_OPCODE_BASE 10
|
5683 |
|
|
|
5684 |
|
|
/* Range of line offsets in a special line info. opcode. */
|
5685 |
|
|
#define DWARF_LINE_RANGE (254-DWARF_LINE_OPCODE_BASE+1)
|
5686 |
|
|
|
5687 |
|
|
/* Flag that indicates the initial value of the is_stmt_start flag.
|
5688 |
|
|
In the present implementation, we do not mark any lines as
|
5689 |
|
|
the beginning of a source statement, because that information
|
5690 |
|
|
is not made available by the GCC front-end. */
|
5691 |
|
|
#define DWARF_LINE_DEFAULT_IS_STMT_START 1
|
5692 |
|
|
|
5693 |
|
|
/* Maximum number of operations per instruction bundle. */
|
5694 |
|
|
#ifndef DWARF_LINE_DEFAULT_MAX_OPS_PER_INSN
|
5695 |
|
|
#define DWARF_LINE_DEFAULT_MAX_OPS_PER_INSN 1
|
5696 |
|
|
#endif
|
5697 |
|
|
|
5698 |
|
|
#ifdef DWARF2_DEBUGGING_INFO
|
5699 |
|
|
/* This location is used by calc_die_sizes() to keep track
|
5700 |
|
|
the offset of each DIE within the .debug_info section. */
|
5701 |
|
|
static unsigned long next_die_offset;
|
5702 |
|
|
#endif
|
5703 |
|
|
|
5704 |
|
|
/* Record the root of the DIE's built for the current compilation unit. */
|
5705 |
|
|
static GTY(()) dw_die_ref comp_unit_die;
|
5706 |
|
|
|
5707 |
|
|
/* A list of type DIEs that have been separated into comdat sections. */
|
5708 |
|
|
static GTY(()) comdat_type_node *comdat_type_list;
|
5709 |
|
|
|
5710 |
|
|
/* A list of DIEs with a NULL parent waiting to be relocated. */
|
5711 |
|
|
static GTY(()) limbo_die_node *limbo_die_list;
|
5712 |
|
|
|
5713 |
|
|
/* A list of DIEs for which we may have to generate
|
5714 |
|
|
DW_AT_MIPS_linkage_name once their DECL_ASSEMBLER_NAMEs are
|
5715 |
|
|
set. */
|
5716 |
|
|
static GTY(()) limbo_die_node *deferred_asm_name;
|
5717 |
|
|
|
5718 |
|
|
/* Filenames referenced by this compilation unit. */
|
5719 |
|
|
static GTY((param_is (struct dwarf_file_data))) htab_t file_table;
|
5720 |
|
|
|
5721 |
|
|
/* A hash table of references to DIE's that describe declarations.
|
5722 |
|
|
The key is a DECL_UID() which is a unique number identifying each decl. */
|
5723 |
|
|
static GTY ((param_is (struct die_struct))) htab_t decl_die_table;
|
5724 |
|
|
|
5725 |
|
|
/* A hash table of references to DIE's that describe COMMON blocks.
|
5726 |
|
|
The key is DECL_UID() ^ die_parent. */
|
5727 |
|
|
static GTY ((param_is (struct die_struct))) htab_t common_block_die_table;
|
5728 |
|
|
|
5729 |
|
|
typedef struct GTY(()) die_arg_entry_struct {
|
5730 |
|
|
dw_die_ref die;
|
5731 |
|
|
tree arg;
|
5732 |
|
|
} die_arg_entry;
|
5733 |
|
|
|
5734 |
|
|
DEF_VEC_O(die_arg_entry);
|
5735 |
|
|
DEF_VEC_ALLOC_O(die_arg_entry,gc);
|
5736 |
|
|
|
5737 |
|
|
/* Node of the variable location list. */
|
5738 |
|
|
struct GTY ((chain_next ("%h.next"))) var_loc_node {
|
5739 |
|
|
rtx GTY (()) var_loc_note;
|
5740 |
|
|
const char * GTY (()) label;
|
5741 |
|
|
struct var_loc_node * GTY (()) next;
|
5742 |
|
|
};
|
5743 |
|
|
|
5744 |
|
|
/* Variable location list. */
|
5745 |
|
|
struct GTY (()) var_loc_list_def {
|
5746 |
|
|
struct var_loc_node * GTY (()) first;
|
5747 |
|
|
|
5748 |
|
|
/* Do not mark the last element of the chained list because
|
5749 |
|
|
it is marked through the chain. */
|
5750 |
|
|
struct var_loc_node * GTY ((skip ("%h"))) last;
|
5751 |
|
|
|
5752 |
|
|
/* DECL_UID of the variable decl. */
|
5753 |
|
|
unsigned int decl_id;
|
5754 |
|
|
};
|
5755 |
|
|
typedef struct var_loc_list_def var_loc_list;
|
5756 |
|
|
|
5757 |
|
|
|
5758 |
|
|
/* Table of decl location linked lists. */
|
5759 |
|
|
static GTY ((param_is (var_loc_list))) htab_t decl_loc_table;
|
5760 |
|
|
|
5761 |
|
|
/* A pointer to the base of a list of references to DIE's that
|
5762 |
|
|
are uniquely identified by their tag, presence/absence of
|
5763 |
|
|
children DIE's, and list of attribute/value pairs. */
|
5764 |
|
|
static GTY((length ("abbrev_die_table_allocated")))
|
5765 |
|
|
dw_die_ref *abbrev_die_table;
|
5766 |
|
|
|
5767 |
|
|
/* Number of elements currently allocated for abbrev_die_table. */
|
5768 |
|
|
static GTY(()) unsigned abbrev_die_table_allocated;
|
5769 |
|
|
|
5770 |
|
|
/* Number of elements in type_die_table currently in use. */
|
5771 |
|
|
static GTY(()) unsigned abbrev_die_table_in_use;
|
5772 |
|
|
|
5773 |
|
|
/* Size (in elements) of increments by which we may expand the
|
5774 |
|
|
abbrev_die_table. */
|
5775 |
|
|
#define ABBREV_DIE_TABLE_INCREMENT 256
|
5776 |
|
|
|
5777 |
|
|
/* A pointer to the base of a table that contains line information
|
5778 |
|
|
for each source code line in .text in the compilation unit. */
|
5779 |
|
|
static GTY((length ("line_info_table_allocated")))
|
5780 |
|
|
dw_line_info_ref line_info_table;
|
5781 |
|
|
|
5782 |
|
|
/* Number of elements currently allocated for line_info_table. */
|
5783 |
|
|
static GTY(()) unsigned line_info_table_allocated;
|
5784 |
|
|
|
5785 |
|
|
/* Number of elements in line_info_table currently in use. */
|
5786 |
|
|
static GTY(()) unsigned line_info_table_in_use;
|
5787 |
|
|
|
5788 |
|
|
/* A pointer to the base of a table that contains line information
|
5789 |
|
|
for each source code line outside of .text in the compilation unit. */
|
5790 |
|
|
static GTY ((length ("separate_line_info_table_allocated")))
|
5791 |
|
|
dw_separate_line_info_ref separate_line_info_table;
|
5792 |
|
|
|
5793 |
|
|
/* Number of elements currently allocated for separate_line_info_table. */
|
5794 |
|
|
static GTY(()) unsigned separate_line_info_table_allocated;
|
5795 |
|
|
|
5796 |
|
|
/* Number of elements in separate_line_info_table currently in use. */
|
5797 |
|
|
static GTY(()) unsigned separate_line_info_table_in_use;
|
5798 |
|
|
|
5799 |
|
|
/* Size (in elements) of increments by which we may expand the
|
5800 |
|
|
line_info_table. */
|
5801 |
|
|
#define LINE_INFO_TABLE_INCREMENT 1024
|
5802 |
|
|
|
5803 |
|
|
/* A pointer to the base of a table that contains a list of publicly
|
5804 |
|
|
accessible names. */
|
5805 |
|
|
static GTY (()) VEC (pubname_entry, gc) * pubname_table;
|
5806 |
|
|
|
5807 |
|
|
/* A pointer to the base of a table that contains a list of publicly
|
5808 |
|
|
accessible types. */
|
5809 |
|
|
static GTY (()) VEC (pubname_entry, gc) * pubtype_table;
|
5810 |
|
|
|
5811 |
|
|
/* Array of dies for which we should generate .debug_arange info. */
|
5812 |
|
|
static GTY((length ("arange_table_allocated"))) dw_die_ref *arange_table;
|
5813 |
|
|
|
5814 |
|
|
/* Number of elements currently allocated for arange_table. */
|
5815 |
|
|
static GTY(()) unsigned arange_table_allocated;
|
5816 |
|
|
|
5817 |
|
|
/* Number of elements in arange_table currently in use. */
|
5818 |
|
|
static GTY(()) unsigned arange_table_in_use;
|
5819 |
|
|
|
5820 |
|
|
/* Size (in elements) of increments by which we may expand the
|
5821 |
|
|
arange_table. */
|
5822 |
|
|
#define ARANGE_TABLE_INCREMENT 64
|
5823 |
|
|
|
5824 |
|
|
/* Array of dies for which we should generate .debug_ranges info. */
|
5825 |
|
|
static GTY ((length ("ranges_table_allocated"))) dw_ranges_ref ranges_table;
|
5826 |
|
|
|
5827 |
|
|
/* Number of elements currently allocated for ranges_table. */
|
5828 |
|
|
static GTY(()) unsigned ranges_table_allocated;
|
5829 |
|
|
|
5830 |
|
|
/* Number of elements in ranges_table currently in use. */
|
5831 |
|
|
static GTY(()) unsigned ranges_table_in_use;
|
5832 |
|
|
|
5833 |
|
|
/* Array of pairs of labels referenced in ranges_table. */
|
5834 |
|
|
static GTY ((length ("ranges_by_label_allocated")))
|
5835 |
|
|
dw_ranges_by_label_ref ranges_by_label;
|
5836 |
|
|
|
5837 |
|
|
/* Number of elements currently allocated for ranges_by_label. */
|
5838 |
|
|
static GTY(()) unsigned ranges_by_label_allocated;
|
5839 |
|
|
|
5840 |
|
|
/* Number of elements in ranges_by_label currently in use. */
|
5841 |
|
|
static GTY(()) unsigned ranges_by_label_in_use;
|
5842 |
|
|
|
5843 |
|
|
/* Size (in elements) of increments by which we may expand the
|
5844 |
|
|
ranges_table. */
|
5845 |
|
|
#define RANGES_TABLE_INCREMENT 64
|
5846 |
|
|
|
5847 |
|
|
/* Whether we have location lists that need outputting */
|
5848 |
|
|
static GTY(()) bool have_location_lists;
|
5849 |
|
|
|
5850 |
|
|
/* Unique label counter. */
|
5851 |
|
|
static GTY(()) unsigned int loclabel_num;
|
5852 |
|
|
|
5853 |
|
|
/* Unique label counter for point-of-call tables. */
|
5854 |
|
|
static GTY(()) unsigned int poc_label_num;
|
5855 |
|
|
|
5856 |
|
|
/* The direct call table structure. */
|
5857 |
|
|
|
5858 |
|
|
typedef struct GTY(()) dcall_struct {
|
5859 |
|
|
unsigned int poc_label_num;
|
5860 |
|
|
tree poc_decl;
|
5861 |
|
|
dw_die_ref targ_die;
|
5862 |
|
|
}
|
5863 |
|
|
dcall_entry;
|
5864 |
|
|
|
5865 |
|
|
DEF_VEC_O(dcall_entry);
|
5866 |
|
|
DEF_VEC_ALLOC_O(dcall_entry, gc);
|
5867 |
|
|
|
5868 |
|
|
/* The virtual call table structure. */
|
5869 |
|
|
|
5870 |
|
|
typedef struct GTY(()) vcall_struct {
|
5871 |
|
|
unsigned int poc_label_num;
|
5872 |
|
|
unsigned int vtable_slot;
|
5873 |
|
|
}
|
5874 |
|
|
vcall_entry;
|
5875 |
|
|
|
5876 |
|
|
DEF_VEC_O(vcall_entry);
|
5877 |
|
|
DEF_VEC_ALLOC_O(vcall_entry, gc);
|
5878 |
|
|
|
5879 |
|
|
/* Pointers to the direct and virtual call tables. */
|
5880 |
|
|
static GTY (()) VEC (dcall_entry, gc) * dcall_table = NULL;
|
5881 |
|
|
static GTY (()) VEC (vcall_entry, gc) * vcall_table = NULL;
|
5882 |
|
|
|
5883 |
|
|
/* A hash table to map INSN_UIDs to vtable slot indexes. */
|
5884 |
|
|
|
5885 |
|
|
struct GTY (()) vcall_insn {
|
5886 |
|
|
int insn_uid;
|
5887 |
|
|
unsigned int vtable_slot;
|
5888 |
|
|
};
|
5889 |
|
|
|
5890 |
|
|
static GTY ((param_is (struct vcall_insn))) htab_t vcall_insn_table;
|
5891 |
|
|
|
5892 |
|
|
#ifdef DWARF2_DEBUGGING_INFO
|
5893 |
|
|
/* Record whether the function being analyzed contains inlined functions. */
|
5894 |
|
|
static int current_function_has_inlines;
|
5895 |
|
|
#endif
|
5896 |
|
|
#if 0 && defined (MIPS_DEBUGGING_INFO)
|
5897 |
|
|
static int comp_unit_has_inlines;
|
5898 |
|
|
#endif
|
5899 |
|
|
|
5900 |
|
|
/* The last file entry emitted by maybe_emit_file(). */
|
5901 |
|
|
static GTY(()) struct dwarf_file_data * last_emitted_file;
|
5902 |
|
|
|
5903 |
|
|
/* Number of internal labels generated by gen_internal_sym(). */
|
5904 |
|
|
static GTY(()) int label_num;
|
5905 |
|
|
|
5906 |
|
|
/* Cached result of previous call to lookup_filename. */
|
5907 |
|
|
static GTY(()) struct dwarf_file_data * file_table_last_lookup;
|
5908 |
|
|
|
5909 |
|
|
static GTY(()) VEC(die_arg_entry,gc) *tmpl_value_parm_die_table;
|
5910 |
|
|
|
5911 |
|
|
#ifdef DWARF2_DEBUGGING_INFO
|
5912 |
|
|
|
5913 |
|
|
/* Offset from the "steady-state frame pointer" to the frame base,
|
5914 |
|
|
within the current function. */
|
5915 |
|
|
static HOST_WIDE_INT frame_pointer_fb_offset;
|
5916 |
|
|
|
5917 |
|
|
/* Forward declarations for functions defined in this file. */
|
5918 |
|
|
|
5919 |
|
|
static int is_pseudo_reg (const_rtx);
|
5920 |
|
|
static tree type_main_variant (tree);
|
5921 |
|
|
static int is_tagged_type (const_tree);
|
5922 |
|
|
static const char *dwarf_tag_name (unsigned);
|
5923 |
|
|
static const char *dwarf_attr_name (unsigned);
|
5924 |
|
|
static const char *dwarf_form_name (unsigned);
|
5925 |
|
|
static tree decl_ultimate_origin (const_tree);
|
5926 |
|
|
static tree decl_class_context (tree);
|
5927 |
|
|
static void add_dwarf_attr (dw_die_ref, dw_attr_ref);
|
5928 |
|
|
static inline enum dw_val_class AT_class (dw_attr_ref);
|
5929 |
|
|
static void add_AT_flag (dw_die_ref, enum dwarf_attribute, unsigned);
|
5930 |
|
|
static inline unsigned AT_flag (dw_attr_ref);
|
5931 |
|
|
static void add_AT_int (dw_die_ref, enum dwarf_attribute, HOST_WIDE_INT);
|
5932 |
|
|
static inline HOST_WIDE_INT AT_int (dw_attr_ref);
|
5933 |
|
|
static void add_AT_unsigned (dw_die_ref, enum dwarf_attribute, unsigned HOST_WIDE_INT);
|
5934 |
|
|
static inline unsigned HOST_WIDE_INT AT_unsigned (dw_attr_ref);
|
5935 |
|
|
static void add_AT_double (dw_die_ref, enum dwarf_attribute,
|
5936 |
|
|
HOST_WIDE_INT, unsigned HOST_WIDE_INT);
|
5937 |
|
|
static inline void add_AT_vec (dw_die_ref, enum dwarf_attribute, unsigned int,
|
5938 |
|
|
unsigned int, unsigned char *);
|
5939 |
|
|
static void add_AT_data8 (dw_die_ref, enum dwarf_attribute, unsigned char *);
|
5940 |
|
|
static hashval_t debug_str_do_hash (const void *);
|
5941 |
|
|
static int debug_str_eq (const void *, const void *);
|
5942 |
|
|
static void add_AT_string (dw_die_ref, enum dwarf_attribute, const char *);
|
5943 |
|
|
static inline const char *AT_string (dw_attr_ref);
|
5944 |
|
|
static enum dwarf_form AT_string_form (dw_attr_ref);
|
5945 |
|
|
static void add_AT_die_ref (dw_die_ref, enum dwarf_attribute, dw_die_ref);
|
5946 |
|
|
static void add_AT_specification (dw_die_ref, dw_die_ref);
|
5947 |
|
|
static inline dw_die_ref AT_ref (dw_attr_ref);
|
5948 |
|
|
static inline int AT_ref_external (dw_attr_ref);
|
5949 |
|
|
static inline void set_AT_ref_external (dw_attr_ref, int);
|
5950 |
|
|
static void add_AT_fde_ref (dw_die_ref, enum dwarf_attribute, unsigned);
|
5951 |
|
|
static void add_AT_loc (dw_die_ref, enum dwarf_attribute, dw_loc_descr_ref);
|
5952 |
|
|
static inline dw_loc_descr_ref AT_loc (dw_attr_ref);
|
5953 |
|
|
static void add_AT_loc_list (dw_die_ref, enum dwarf_attribute,
|
5954 |
|
|
dw_loc_list_ref);
|
5955 |
|
|
static inline dw_loc_list_ref AT_loc_list (dw_attr_ref);
|
5956 |
|
|
static void add_AT_addr (dw_die_ref, enum dwarf_attribute, rtx);
|
5957 |
|
|
static inline rtx AT_addr (dw_attr_ref);
|
5958 |
|
|
static void add_AT_lbl_id (dw_die_ref, enum dwarf_attribute, const char *);
|
5959 |
|
|
static void add_AT_lineptr (dw_die_ref, enum dwarf_attribute, const char *);
|
5960 |
|
|
static void add_AT_macptr (dw_die_ref, enum dwarf_attribute, const char *);
|
5961 |
|
|
static void add_AT_offset (dw_die_ref, enum dwarf_attribute,
|
5962 |
|
|
unsigned HOST_WIDE_INT);
|
5963 |
|
|
static void add_AT_range_list (dw_die_ref, enum dwarf_attribute,
|
5964 |
|
|
unsigned long);
|
5965 |
|
|
static inline const char *AT_lbl (dw_attr_ref);
|
5966 |
|
|
static dw_attr_ref get_AT (dw_die_ref, enum dwarf_attribute);
|
5967 |
|
|
static const char *get_AT_low_pc (dw_die_ref);
|
5968 |
|
|
static const char *get_AT_hi_pc (dw_die_ref);
|
5969 |
|
|
static const char *get_AT_string (dw_die_ref, enum dwarf_attribute);
|
5970 |
|
|
static int get_AT_flag (dw_die_ref, enum dwarf_attribute);
|
5971 |
|
|
static unsigned get_AT_unsigned (dw_die_ref, enum dwarf_attribute);
|
5972 |
|
|
static inline dw_die_ref get_AT_ref (dw_die_ref, enum dwarf_attribute);
|
5973 |
|
|
static bool is_cxx (void);
|
5974 |
|
|
static bool is_fortran (void);
|
5975 |
|
|
static bool is_ada (void);
|
5976 |
|
|
static void remove_AT (dw_die_ref, enum dwarf_attribute);
|
5977 |
|
|
static void remove_child_TAG (dw_die_ref, enum dwarf_tag);
|
5978 |
|
|
static void add_child_die (dw_die_ref, dw_die_ref);
|
5979 |
|
|
static dw_die_ref new_die (enum dwarf_tag, dw_die_ref, tree);
|
5980 |
|
|
static dw_die_ref lookup_type_die (tree);
|
5981 |
|
|
static void equate_type_number_to_die (tree, dw_die_ref);
|
5982 |
|
|
static hashval_t decl_die_table_hash (const void *);
|
5983 |
|
|
static int decl_die_table_eq (const void *, const void *);
|
5984 |
|
|
static dw_die_ref lookup_decl_die (tree);
|
5985 |
|
|
static hashval_t common_block_die_table_hash (const void *);
|
5986 |
|
|
static int common_block_die_table_eq (const void *, const void *);
|
5987 |
|
|
static hashval_t decl_loc_table_hash (const void *);
|
5988 |
|
|
static int decl_loc_table_eq (const void *, const void *);
|
5989 |
|
|
static var_loc_list *lookup_decl_loc (const_tree);
|
5990 |
|
|
static void equate_decl_number_to_die (tree, dw_die_ref);
|
5991 |
|
|
static struct var_loc_node *add_var_loc_to_decl (tree, rtx);
|
5992 |
|
|
static void print_spaces (FILE *);
|
5993 |
|
|
static void print_die (dw_die_ref, FILE *);
|
5994 |
|
|
static void print_dwarf_line_table (FILE *);
|
5995 |
|
|
static dw_die_ref push_new_compile_unit (dw_die_ref, dw_die_ref);
|
5996 |
|
|
static dw_die_ref pop_compile_unit (dw_die_ref);
|
5997 |
|
|
static void loc_checksum (dw_loc_descr_ref, struct md5_ctx *);
|
5998 |
|
|
static void attr_checksum (dw_attr_ref, struct md5_ctx *, int *);
|
5999 |
|
|
static void die_checksum (dw_die_ref, struct md5_ctx *, int *);
|
6000 |
|
|
static void checksum_sleb128 (HOST_WIDE_INT, struct md5_ctx *);
|
6001 |
|
|
static void checksum_uleb128 (unsigned HOST_WIDE_INT, struct md5_ctx *);
|
6002 |
|
|
static void loc_checksum_ordered (dw_loc_descr_ref, struct md5_ctx *);
|
6003 |
|
|
static void attr_checksum_ordered (enum dwarf_tag, dw_attr_ref,
|
6004 |
|
|
struct md5_ctx *, int *);
|
6005 |
|
|
struct checksum_attributes;
|
6006 |
|
|
static void collect_checksum_attributes (struct checksum_attributes *, dw_die_ref);
|
6007 |
|
|
static void die_checksum_ordered (dw_die_ref, struct md5_ctx *, int *);
|
6008 |
|
|
static void checksum_die_context (dw_die_ref, struct md5_ctx *);
|
6009 |
|
|
static void generate_type_signature (dw_die_ref, comdat_type_node *);
|
6010 |
|
|
static int same_loc_p (dw_loc_descr_ref, dw_loc_descr_ref, int *);
|
6011 |
|
|
static int same_dw_val_p (const dw_val_node *, const dw_val_node *, int *);
|
6012 |
|
|
static int same_attr_p (dw_attr_ref, dw_attr_ref, int *);
|
6013 |
|
|
static int same_die_p (dw_die_ref, dw_die_ref, int *);
|
6014 |
|
|
static int same_die_p_wrap (dw_die_ref, dw_die_ref);
|
6015 |
|
|
static void compute_section_prefix (dw_die_ref);
|
6016 |
|
|
static int is_type_die (dw_die_ref);
|
6017 |
|
|
static int is_comdat_die (dw_die_ref);
|
6018 |
|
|
static int is_symbol_die (dw_die_ref);
|
6019 |
|
|
static void assign_symbol_names (dw_die_ref);
|
6020 |
|
|
static void break_out_includes (dw_die_ref);
|
6021 |
|
|
static int is_declaration_die (dw_die_ref);
|
6022 |
|
|
static int should_move_die_to_comdat (dw_die_ref);
|
6023 |
|
|
static dw_die_ref clone_as_declaration (dw_die_ref);
|
6024 |
|
|
static dw_die_ref clone_die (dw_die_ref);
|
6025 |
|
|
static dw_die_ref clone_tree (dw_die_ref);
|
6026 |
|
|
static void copy_declaration_context (dw_die_ref, dw_die_ref);
|
6027 |
|
|
static void generate_skeleton_ancestor_tree (skeleton_chain_node *);
|
6028 |
|
|
static void generate_skeleton_bottom_up (skeleton_chain_node *);
|
6029 |
|
|
static dw_die_ref generate_skeleton (dw_die_ref);
|
6030 |
|
|
static dw_die_ref remove_child_or_replace_with_skeleton (dw_die_ref,
|
6031 |
|
|
dw_die_ref);
|
6032 |
|
|
static void break_out_comdat_types (dw_die_ref);
|
6033 |
|
|
static dw_die_ref copy_ancestor_tree (dw_die_ref, dw_die_ref, htab_t);
|
6034 |
|
|
static void copy_decls_walk (dw_die_ref, dw_die_ref, htab_t);
|
6035 |
|
|
static void copy_decls_for_unworthy_types (dw_die_ref);
|
6036 |
|
|
|
6037 |
|
|
static hashval_t htab_cu_hash (const void *);
|
6038 |
|
|
static int htab_cu_eq (const void *, const void *);
|
6039 |
|
|
static void htab_cu_del (void *);
|
6040 |
|
|
static int check_duplicate_cu (dw_die_ref, htab_t, unsigned *);
|
6041 |
|
|
static void record_comdat_symbol_number (dw_die_ref, htab_t, unsigned);
|
6042 |
|
|
static void add_sibling_attributes (dw_die_ref);
|
6043 |
|
|
static void build_abbrev_table (dw_die_ref);
|
6044 |
|
|
static void output_location_lists (dw_die_ref);
|
6045 |
|
|
static int constant_size (unsigned HOST_WIDE_INT);
|
6046 |
|
|
static unsigned long size_of_die (dw_die_ref);
|
6047 |
|
|
static void calc_die_sizes (dw_die_ref);
|
6048 |
|
|
static void mark_dies (dw_die_ref);
|
6049 |
|
|
static void unmark_dies (dw_die_ref);
|
6050 |
|
|
static void unmark_all_dies (dw_die_ref);
|
6051 |
|
|
static unsigned long size_of_pubnames (VEC (pubname_entry,gc) *);
|
6052 |
|
|
static unsigned long size_of_aranges (void);
|
6053 |
|
|
static enum dwarf_form value_format (dw_attr_ref);
|
6054 |
|
|
static void output_value_format (dw_attr_ref);
|
6055 |
|
|
static void output_abbrev_section (void);
|
6056 |
|
|
static void output_die_symbol (dw_die_ref);
|
6057 |
|
|
static void output_die (dw_die_ref);
|
6058 |
|
|
static void output_compilation_unit_header (void);
|
6059 |
|
|
static void output_comp_unit (dw_die_ref, int);
|
6060 |
|
|
static void output_comdat_type_unit (comdat_type_node *);
|
6061 |
|
|
static const char *dwarf2_name (tree, int);
|
6062 |
|
|
static void add_pubname (tree, dw_die_ref);
|
6063 |
|
|
static void add_pubname_string (const char *, dw_die_ref);
|
6064 |
|
|
static void add_pubtype (tree, dw_die_ref);
|
6065 |
|
|
static void output_pubnames (VEC (pubname_entry,gc) *);
|
6066 |
|
|
static void add_arange (tree, dw_die_ref);
|
6067 |
|
|
static void output_aranges (void);
|
6068 |
|
|
static unsigned int add_ranges_num (int);
|
6069 |
|
|
static unsigned int add_ranges (const_tree);
|
6070 |
|
|
static void add_ranges_by_labels (dw_die_ref, const char *, const char *,
|
6071 |
|
|
bool *);
|
6072 |
|
|
static void output_ranges (void);
|
6073 |
|
|
static void output_line_info (void);
|
6074 |
|
|
static void output_file_names (void);
|
6075 |
|
|
static dw_die_ref base_type_die (tree);
|
6076 |
|
|
static int is_base_type (tree);
|
6077 |
|
|
static dw_die_ref subrange_type_die (tree, tree, tree, dw_die_ref);
|
6078 |
|
|
static dw_die_ref modified_type_die (tree, int, int, dw_die_ref);
|
6079 |
|
|
static dw_die_ref generic_parameter_die (tree, tree, bool, dw_die_ref);
|
6080 |
|
|
static dw_die_ref template_parameter_pack_die (tree, tree, dw_die_ref);
|
6081 |
|
|
static int type_is_enum (const_tree);
|
6082 |
|
|
static unsigned int dbx_reg_number (const_rtx);
|
6083 |
|
|
static void add_loc_descr_op_piece (dw_loc_descr_ref *, int);
|
6084 |
|
|
static dw_loc_descr_ref reg_loc_descriptor (rtx, enum var_init_status);
|
6085 |
|
|
static dw_loc_descr_ref one_reg_loc_descriptor (unsigned int,
|
6086 |
|
|
enum var_init_status);
|
6087 |
|
|
static dw_loc_descr_ref multiple_reg_loc_descriptor (rtx, rtx,
|
6088 |
|
|
enum var_init_status);
|
6089 |
|
|
static dw_loc_descr_ref based_loc_descr (rtx, HOST_WIDE_INT,
|
6090 |
|
|
enum var_init_status);
|
6091 |
|
|
static int is_based_loc (const_rtx);
|
6092 |
|
|
static int resolve_one_addr (rtx *, void *);
|
6093 |
|
|
static dw_loc_descr_ref mem_loc_descriptor (rtx, enum machine_mode mode,
|
6094 |
|
|
enum var_init_status);
|
6095 |
|
|
static dw_loc_descr_ref concat_loc_descriptor (rtx, rtx,
|
6096 |
|
|
enum var_init_status);
|
6097 |
|
|
static dw_loc_descr_ref loc_descriptor (rtx, enum machine_mode mode,
|
6098 |
|
|
enum var_init_status);
|
6099 |
|
|
static dw_loc_list_ref loc_list_from_tree (tree, int);
|
6100 |
|
|
static dw_loc_descr_ref loc_descriptor_from_tree (tree, int);
|
6101 |
|
|
static HOST_WIDE_INT ceiling (HOST_WIDE_INT, unsigned int);
|
6102 |
|
|
static tree field_type (const_tree);
|
6103 |
|
|
static unsigned int simple_type_align_in_bits (const_tree);
|
6104 |
|
|
static unsigned int simple_decl_align_in_bits (const_tree);
|
6105 |
|
|
static unsigned HOST_WIDE_INT simple_type_size_in_bits (const_tree);
|
6106 |
|
|
static HOST_WIDE_INT field_byte_offset (const_tree);
|
6107 |
|
|
static void add_AT_location_description (dw_die_ref, enum dwarf_attribute,
|
6108 |
|
|
dw_loc_list_ref);
|
6109 |
|
|
static void add_data_member_location_attribute (dw_die_ref, tree);
|
6110 |
|
|
static bool add_const_value_attribute (dw_die_ref, rtx);
|
6111 |
|
|
static void insert_int (HOST_WIDE_INT, unsigned, unsigned char *);
|
6112 |
|
|
static void insert_float (const_rtx, unsigned char *);
|
6113 |
|
|
static rtx rtl_for_decl_location (tree);
|
6114 |
|
|
static bool add_location_or_const_value_attribute (dw_die_ref, tree,
|
6115 |
|
|
enum dwarf_attribute);
|
6116 |
|
|
static bool tree_add_const_value_attribute (dw_die_ref, tree);
|
6117 |
|
|
static bool tree_add_const_value_attribute_for_decl (dw_die_ref, tree);
|
6118 |
|
|
static void add_name_attribute (dw_die_ref, const char *);
|
6119 |
|
|
static void add_comp_dir_attribute (dw_die_ref);
|
6120 |
|
|
static void add_bound_info (dw_die_ref, enum dwarf_attribute, tree);
|
6121 |
|
|
static void add_subscript_info (dw_die_ref, tree, bool);
|
6122 |
|
|
static void add_byte_size_attribute (dw_die_ref, tree);
|
6123 |
|
|
static void add_bit_offset_attribute (dw_die_ref, tree);
|
6124 |
|
|
static void add_bit_size_attribute (dw_die_ref, tree);
|
6125 |
|
|
static void add_prototyped_attribute (dw_die_ref, tree);
|
6126 |
|
|
static dw_die_ref add_abstract_origin_attribute (dw_die_ref, tree);
|
6127 |
|
|
static void add_pure_or_virtual_attribute (dw_die_ref, tree);
|
6128 |
|
|
static void add_src_coords_attributes (dw_die_ref, tree);
|
6129 |
|
|
static void add_name_and_src_coords_attributes (dw_die_ref, tree);
|
6130 |
|
|
static void push_decl_scope (tree);
|
6131 |
|
|
static void pop_decl_scope (void);
|
6132 |
|
|
static dw_die_ref scope_die_for (tree, dw_die_ref);
|
6133 |
|
|
static inline int local_scope_p (dw_die_ref);
|
6134 |
|
|
static inline int class_scope_p (dw_die_ref);
|
6135 |
|
|
static inline int class_or_namespace_scope_p (dw_die_ref);
|
6136 |
|
|
static void add_type_attribute (dw_die_ref, tree, int, int, dw_die_ref);
|
6137 |
|
|
static void add_calling_convention_attribute (dw_die_ref, tree);
|
6138 |
|
|
static const char *type_tag (const_tree);
|
6139 |
|
|
static tree member_declared_type (const_tree);
|
6140 |
|
|
#if 0
|
6141 |
|
|
static const char *decl_start_label (tree);
|
6142 |
|
|
#endif
|
6143 |
|
|
static void gen_array_type_die (tree, dw_die_ref);
|
6144 |
|
|
static void gen_descr_array_type_die (tree, struct array_descr_info *, dw_die_ref);
|
6145 |
|
|
#if 0
|
6146 |
|
|
static void gen_entry_point_die (tree, dw_die_ref);
|
6147 |
|
|
#endif
|
6148 |
|
|
static dw_die_ref gen_enumeration_type_die (tree, dw_die_ref);
|
6149 |
|
|
static dw_die_ref gen_formal_parameter_die (tree, tree, bool, dw_die_ref);
|
6150 |
|
|
static dw_die_ref gen_formal_parameter_pack_die (tree, tree, dw_die_ref, tree*);
|
6151 |
|
|
static void gen_unspecified_parameters_die (tree, dw_die_ref);
|
6152 |
|
|
static void gen_formal_types_die (tree, dw_die_ref);
|
6153 |
|
|
static void gen_subprogram_die (tree, dw_die_ref);
|
6154 |
|
|
static void gen_variable_die (tree, tree, dw_die_ref);
|
6155 |
|
|
static void gen_const_die (tree, dw_die_ref);
|
6156 |
|
|
static void gen_label_die (tree, dw_die_ref);
|
6157 |
|
|
static void gen_lexical_block_die (tree, dw_die_ref, int);
|
6158 |
|
|
static void gen_inlined_subroutine_die (tree, dw_die_ref, int);
|
6159 |
|
|
static void gen_field_die (tree, dw_die_ref);
|
6160 |
|
|
static void gen_ptr_to_mbr_type_die (tree, dw_die_ref);
|
6161 |
|
|
static dw_die_ref gen_compile_unit_die (const char *);
|
6162 |
|
|
static void gen_inheritance_die (tree, tree, dw_die_ref);
|
6163 |
|
|
static void gen_member_die (tree, dw_die_ref);
|
6164 |
|
|
static void gen_struct_or_union_type_die (tree, dw_die_ref,
|
6165 |
|
|
enum debug_info_usage);
|
6166 |
|
|
static void gen_subroutine_type_die (tree, dw_die_ref);
|
6167 |
|
|
static void gen_typedef_die (tree, dw_die_ref);
|
6168 |
|
|
static void gen_type_die (tree, dw_die_ref);
|
6169 |
|
|
static void gen_block_die (tree, dw_die_ref, int);
|
6170 |
|
|
static void decls_for_scope (tree, dw_die_ref, int);
|
6171 |
|
|
static int is_redundant_typedef (const_tree);
|
6172 |
|
|
static inline dw_die_ref get_context_die (tree);
|
6173 |
|
|
static void gen_namespace_die (tree, dw_die_ref);
|
6174 |
|
|
static void gen_decl_die (tree, tree, dw_die_ref);
|
6175 |
|
|
static dw_die_ref force_decl_die (tree);
|
6176 |
|
|
static dw_die_ref force_type_die (tree);
|
6177 |
|
|
static dw_die_ref setup_namespace_context (tree, dw_die_ref);
|
6178 |
|
|
static dw_die_ref declare_in_namespace (tree, dw_die_ref);
|
6179 |
|
|
static struct dwarf_file_data * lookup_filename (const char *);
|
6180 |
|
|
static void retry_incomplete_types (void);
|
6181 |
|
|
static void gen_type_die_for_member (tree, tree, dw_die_ref);
|
6182 |
|
|
static void gen_generic_params_dies (tree);
|
6183 |
|
|
static void splice_child_die (dw_die_ref, dw_die_ref);
|
6184 |
|
|
static int file_info_cmp (const void *, const void *);
|
6185 |
|
|
static dw_loc_list_ref new_loc_list (dw_loc_descr_ref, const char *,
|
6186 |
|
|
const char *, const char *);
|
6187 |
|
|
static void output_loc_list (dw_loc_list_ref);
|
6188 |
|
|
static char *gen_internal_sym (const char *);
|
6189 |
|
|
|
6190 |
|
|
static void prune_unmark_dies (dw_die_ref);
|
6191 |
|
|
static void prune_unused_types_mark (dw_die_ref, int);
|
6192 |
|
|
static void prune_unused_types_walk (dw_die_ref);
|
6193 |
|
|
static void prune_unused_types_walk_attribs (dw_die_ref);
|
6194 |
|
|
static void prune_unused_types_prune (dw_die_ref);
|
6195 |
|
|
static void prune_unused_types (void);
|
6196 |
|
|
static int maybe_emit_file (struct dwarf_file_data *fd);
|
6197 |
|
|
static void append_entry_to_tmpl_value_parm_die_table (dw_die_ref, tree);
|
6198 |
|
|
static void gen_remaining_tmpl_value_param_die_attribute (void);
|
6199 |
|
|
|
6200 |
|
|
/* Section names used to hold DWARF debugging information. */
|
6201 |
|
|
#ifndef DEBUG_INFO_SECTION
|
6202 |
|
|
#define DEBUG_INFO_SECTION ".debug_info"
|
6203 |
|
|
#endif
|
6204 |
|
|
#ifndef DEBUG_ABBREV_SECTION
|
6205 |
|
|
#define DEBUG_ABBREV_SECTION ".debug_abbrev"
|
6206 |
|
|
#endif
|
6207 |
|
|
#ifndef DEBUG_ARANGES_SECTION
|
6208 |
|
|
#define DEBUG_ARANGES_SECTION ".debug_aranges"
|
6209 |
|
|
#endif
|
6210 |
|
|
#ifndef DEBUG_MACINFO_SECTION
|
6211 |
|
|
#define DEBUG_MACINFO_SECTION ".debug_macinfo"
|
6212 |
|
|
#endif
|
6213 |
|
|
#ifndef DEBUG_LINE_SECTION
|
6214 |
|
|
#define DEBUG_LINE_SECTION ".debug_line"
|
6215 |
|
|
#endif
|
6216 |
|
|
#ifndef DEBUG_LOC_SECTION
|
6217 |
|
|
#define DEBUG_LOC_SECTION ".debug_loc"
|
6218 |
|
|
#endif
|
6219 |
|
|
#ifndef DEBUG_PUBNAMES_SECTION
|
6220 |
|
|
#define DEBUG_PUBNAMES_SECTION ".debug_pubnames"
|
6221 |
|
|
#endif
|
6222 |
|
|
#ifndef DEBUG_PUBTYPES_SECTION
|
6223 |
|
|
#define DEBUG_PUBTYPES_SECTION ".debug_pubtypes"
|
6224 |
|
|
#endif
|
6225 |
|
|
#ifndef DEBUG_DCALL_SECTION
|
6226 |
|
|
#define DEBUG_DCALL_SECTION ".debug_dcall"
|
6227 |
|
|
#endif
|
6228 |
|
|
#ifndef DEBUG_VCALL_SECTION
|
6229 |
|
|
#define DEBUG_VCALL_SECTION ".debug_vcall"
|
6230 |
|
|
#endif
|
6231 |
|
|
#ifndef DEBUG_STR_SECTION
|
6232 |
|
|
#define DEBUG_STR_SECTION ".debug_str"
|
6233 |
|
|
#endif
|
6234 |
|
|
#ifndef DEBUG_RANGES_SECTION
|
6235 |
|
|
#define DEBUG_RANGES_SECTION ".debug_ranges"
|
6236 |
|
|
#endif
|
6237 |
|
|
|
6238 |
|
|
/* Standard ELF section names for compiled code and data. */
|
6239 |
|
|
#ifndef TEXT_SECTION_NAME
|
6240 |
|
|
#define TEXT_SECTION_NAME ".text"
|
6241 |
|
|
#endif
|
6242 |
|
|
|
6243 |
|
|
/* Section flags for .debug_str section. */
|
6244 |
|
|
#define DEBUG_STR_SECTION_FLAGS \
|
6245 |
|
|
(HAVE_GAS_SHF_MERGE && flag_merge_debug_strings \
|
6246 |
|
|
? SECTION_DEBUG | SECTION_MERGE | SECTION_STRINGS | 1 \
|
6247 |
|
|
: SECTION_DEBUG)
|
6248 |
|
|
|
6249 |
|
|
/* Labels we insert at beginning sections we can reference instead of
|
6250 |
|
|
the section names themselves. */
|
6251 |
|
|
|
6252 |
|
|
#ifndef TEXT_SECTION_LABEL
|
6253 |
|
|
#define TEXT_SECTION_LABEL "Ltext"
|
6254 |
|
|
#endif
|
6255 |
|
|
#ifndef COLD_TEXT_SECTION_LABEL
|
6256 |
|
|
#define COLD_TEXT_SECTION_LABEL "Ltext_cold"
|
6257 |
|
|
#endif
|
6258 |
|
|
#ifndef DEBUG_LINE_SECTION_LABEL
|
6259 |
|
|
#define DEBUG_LINE_SECTION_LABEL "Ldebug_line"
|
6260 |
|
|
#endif
|
6261 |
|
|
#ifndef DEBUG_INFO_SECTION_LABEL
|
6262 |
|
|
#define DEBUG_INFO_SECTION_LABEL "Ldebug_info"
|
6263 |
|
|
#endif
|
6264 |
|
|
#ifndef DEBUG_ABBREV_SECTION_LABEL
|
6265 |
|
|
#define DEBUG_ABBREV_SECTION_LABEL "Ldebug_abbrev"
|
6266 |
|
|
#endif
|
6267 |
|
|
#ifndef DEBUG_LOC_SECTION_LABEL
|
6268 |
|
|
#define DEBUG_LOC_SECTION_LABEL "Ldebug_loc"
|
6269 |
|
|
#endif
|
6270 |
|
|
#ifndef DEBUG_RANGES_SECTION_LABEL
|
6271 |
|
|
#define DEBUG_RANGES_SECTION_LABEL "Ldebug_ranges"
|
6272 |
|
|
#endif
|
6273 |
|
|
#ifndef DEBUG_MACINFO_SECTION_LABEL
|
6274 |
|
|
#define DEBUG_MACINFO_SECTION_LABEL "Ldebug_macinfo"
|
6275 |
|
|
#endif
|
6276 |
|
|
|
6277 |
|
|
/* Definitions of defaults for formats and names of various special
|
6278 |
|
|
(artificial) labels which may be generated within this file (when the -g
|
6279 |
|
|
options is used and DWARF2_DEBUGGING_INFO is in effect.
|
6280 |
|
|
If necessary, these may be overridden from within the tm.h file, but
|
6281 |
|
|
typically, overriding these defaults is unnecessary. */
|
6282 |
|
|
|
6283 |
|
|
static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
|
6284 |
|
|
static char text_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
|
6285 |
|
|
static char cold_text_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
|
6286 |
|
|
static char cold_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
|
6287 |
|
|
static char abbrev_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
|
6288 |
|
|
static char debug_info_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
|
6289 |
|
|
static char debug_line_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
|
6290 |
|
|
static char macinfo_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
|
6291 |
|
|
static char loc_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
|
6292 |
|
|
static char ranges_section_label[2 * MAX_ARTIFICIAL_LABEL_BYTES];
|
6293 |
|
|
|
6294 |
|
|
#ifndef TEXT_END_LABEL
|
6295 |
|
|
#define TEXT_END_LABEL "Letext"
|
6296 |
|
|
#endif
|
6297 |
|
|
#ifndef COLD_END_LABEL
|
6298 |
|
|
#define COLD_END_LABEL "Letext_cold"
|
6299 |
|
|
#endif
|
6300 |
|
|
#ifndef BLOCK_BEGIN_LABEL
|
6301 |
|
|
#define BLOCK_BEGIN_LABEL "LBB"
|
6302 |
|
|
#endif
|
6303 |
|
|
#ifndef BLOCK_END_LABEL
|
6304 |
|
|
#define BLOCK_END_LABEL "LBE"
|
6305 |
|
|
#endif
|
6306 |
|
|
#ifndef LINE_CODE_LABEL
|
6307 |
|
|
#define LINE_CODE_LABEL "LM"
|
6308 |
|
|
#endif
|
6309 |
|
|
#ifndef SEPARATE_LINE_CODE_LABEL
|
6310 |
|
|
#define SEPARATE_LINE_CODE_LABEL "LSM"
|
6311 |
|
|
#endif
|
6312 |
|
|
|
6313 |
|
|
|
6314 |
|
|
/* We allow a language front-end to designate a function that is to be
|
6315 |
|
|
called to "demangle" any name before it is put into a DIE. */
|
6316 |
|
|
|
6317 |
|
|
static const char *(*demangle_name_func) (const char *);
|
6318 |
|
|
|
6319 |
|
|
void
|
6320 |
|
|
dwarf2out_set_demangle_name_func (const char *(*func) (const char *))
|
6321 |
|
|
{
|
6322 |
|
|
demangle_name_func = func;
|
6323 |
|
|
}
|
6324 |
|
|
|
6325 |
|
|
/* Test if rtl node points to a pseudo register. */
|
6326 |
|
|
|
6327 |
|
|
static inline int
|
6328 |
|
|
is_pseudo_reg (const_rtx rtl)
|
6329 |
|
|
{
|
6330 |
|
|
return ((REG_P (rtl) && REGNO (rtl) >= FIRST_PSEUDO_REGISTER)
|
6331 |
|
|
|| (GET_CODE (rtl) == SUBREG
|
6332 |
|
|
&& REGNO (SUBREG_REG (rtl)) >= FIRST_PSEUDO_REGISTER));
|
6333 |
|
|
}
|
6334 |
|
|
|
6335 |
|
|
/* Return a reference to a type, with its const and volatile qualifiers
|
6336 |
|
|
removed. */
|
6337 |
|
|
|
6338 |
|
|
static inline tree
|
6339 |
|
|
type_main_variant (tree type)
|
6340 |
|
|
{
|
6341 |
|
|
type = TYPE_MAIN_VARIANT (type);
|
6342 |
|
|
|
6343 |
|
|
/* ??? There really should be only one main variant among any group of
|
6344 |
|
|
variants of a given type (and all of the MAIN_VARIANT values for all
|
6345 |
|
|
members of the group should point to that one type) but sometimes the C
|
6346 |
|
|
front-end messes this up for array types, so we work around that bug
|
6347 |
|
|
here. */
|
6348 |
|
|
if (TREE_CODE (type) == ARRAY_TYPE)
|
6349 |
|
|
while (type != TYPE_MAIN_VARIANT (type))
|
6350 |
|
|
type = TYPE_MAIN_VARIANT (type);
|
6351 |
|
|
|
6352 |
|
|
return type;
|
6353 |
|
|
}
|
6354 |
|
|
|
6355 |
|
|
/* Return nonzero if the given type node represents a tagged type. */
|
6356 |
|
|
|
6357 |
|
|
static inline int
|
6358 |
|
|
is_tagged_type (const_tree type)
|
6359 |
|
|
{
|
6360 |
|
|
enum tree_code code = TREE_CODE (type);
|
6361 |
|
|
|
6362 |
|
|
return (code == RECORD_TYPE || code == UNION_TYPE
|
6363 |
|
|
|| code == QUAL_UNION_TYPE || code == ENUMERAL_TYPE);
|
6364 |
|
|
}
|
6365 |
|
|
|
6366 |
|
|
/* Convert a DIE tag into its string name. */
|
6367 |
|
|
|
6368 |
|
|
static const char *
|
6369 |
|
|
dwarf_tag_name (unsigned int tag)
|
6370 |
|
|
{
|
6371 |
|
|
switch (tag)
|
6372 |
|
|
{
|
6373 |
|
|
case DW_TAG_padding:
|
6374 |
|
|
return "DW_TAG_padding";
|
6375 |
|
|
case DW_TAG_array_type:
|
6376 |
|
|
return "DW_TAG_array_type";
|
6377 |
|
|
case DW_TAG_class_type:
|
6378 |
|
|
return "DW_TAG_class_type";
|
6379 |
|
|
case DW_TAG_entry_point:
|
6380 |
|
|
return "DW_TAG_entry_point";
|
6381 |
|
|
case DW_TAG_enumeration_type:
|
6382 |
|
|
return "DW_TAG_enumeration_type";
|
6383 |
|
|
case DW_TAG_formal_parameter:
|
6384 |
|
|
return "DW_TAG_formal_parameter";
|
6385 |
|
|
case DW_TAG_imported_declaration:
|
6386 |
|
|
return "DW_TAG_imported_declaration";
|
6387 |
|
|
case DW_TAG_label:
|
6388 |
|
|
return "DW_TAG_label";
|
6389 |
|
|
case DW_TAG_lexical_block:
|
6390 |
|
|
return "DW_TAG_lexical_block";
|
6391 |
|
|
case DW_TAG_member:
|
6392 |
|
|
return "DW_TAG_member";
|
6393 |
|
|
case DW_TAG_pointer_type:
|
6394 |
|
|
return "DW_TAG_pointer_type";
|
6395 |
|
|
case DW_TAG_reference_type:
|
6396 |
|
|
return "DW_TAG_reference_type";
|
6397 |
|
|
case DW_TAG_compile_unit:
|
6398 |
|
|
return "DW_TAG_compile_unit";
|
6399 |
|
|
case DW_TAG_string_type:
|
6400 |
|
|
return "DW_TAG_string_type";
|
6401 |
|
|
case DW_TAG_structure_type:
|
6402 |
|
|
return "DW_TAG_structure_type";
|
6403 |
|
|
case DW_TAG_subroutine_type:
|
6404 |
|
|
return "DW_TAG_subroutine_type";
|
6405 |
|
|
case DW_TAG_typedef:
|
6406 |
|
|
return "DW_TAG_typedef";
|
6407 |
|
|
case DW_TAG_union_type:
|
6408 |
|
|
return "DW_TAG_union_type";
|
6409 |
|
|
case DW_TAG_unspecified_parameters:
|
6410 |
|
|
return "DW_TAG_unspecified_parameters";
|
6411 |
|
|
case DW_TAG_variant:
|
6412 |
|
|
return "DW_TAG_variant";
|
6413 |
|
|
case DW_TAG_common_block:
|
6414 |
|
|
return "DW_TAG_common_block";
|
6415 |
|
|
case DW_TAG_common_inclusion:
|
6416 |
|
|
return "DW_TAG_common_inclusion";
|
6417 |
|
|
case DW_TAG_inheritance:
|
6418 |
|
|
return "DW_TAG_inheritance";
|
6419 |
|
|
case DW_TAG_inlined_subroutine:
|
6420 |
|
|
return "DW_TAG_inlined_subroutine";
|
6421 |
|
|
case DW_TAG_module:
|
6422 |
|
|
return "DW_TAG_module";
|
6423 |
|
|
case DW_TAG_ptr_to_member_type:
|
6424 |
|
|
return "DW_TAG_ptr_to_member_type";
|
6425 |
|
|
case DW_TAG_set_type:
|
6426 |
|
|
return "DW_TAG_set_type";
|
6427 |
|
|
case DW_TAG_subrange_type:
|
6428 |
|
|
return "DW_TAG_subrange_type";
|
6429 |
|
|
case DW_TAG_with_stmt:
|
6430 |
|
|
return "DW_TAG_with_stmt";
|
6431 |
|
|
case DW_TAG_access_declaration:
|
6432 |
|
|
return "DW_TAG_access_declaration";
|
6433 |
|
|
case DW_TAG_base_type:
|
6434 |
|
|
return "DW_TAG_base_type";
|
6435 |
|
|
case DW_TAG_catch_block:
|
6436 |
|
|
return "DW_TAG_catch_block";
|
6437 |
|
|
case DW_TAG_const_type:
|
6438 |
|
|
return "DW_TAG_const_type";
|
6439 |
|
|
case DW_TAG_constant:
|
6440 |
|
|
return "DW_TAG_constant";
|
6441 |
|
|
case DW_TAG_enumerator:
|
6442 |
|
|
return "DW_TAG_enumerator";
|
6443 |
|
|
case DW_TAG_file_type:
|
6444 |
|
|
return "DW_TAG_file_type";
|
6445 |
|
|
case DW_TAG_friend:
|
6446 |
|
|
return "DW_TAG_friend";
|
6447 |
|
|
case DW_TAG_namelist:
|
6448 |
|
|
return "DW_TAG_namelist";
|
6449 |
|
|
case DW_TAG_namelist_item:
|
6450 |
|
|
return "DW_TAG_namelist_item";
|
6451 |
|
|
case DW_TAG_packed_type:
|
6452 |
|
|
return "DW_TAG_packed_type";
|
6453 |
|
|
case DW_TAG_subprogram:
|
6454 |
|
|
return "DW_TAG_subprogram";
|
6455 |
|
|
case DW_TAG_template_type_param:
|
6456 |
|
|
return "DW_TAG_template_type_param";
|
6457 |
|
|
case DW_TAG_template_value_param:
|
6458 |
|
|
return "DW_TAG_template_value_param";
|
6459 |
|
|
case DW_TAG_thrown_type:
|
6460 |
|
|
return "DW_TAG_thrown_type";
|
6461 |
|
|
case DW_TAG_try_block:
|
6462 |
|
|
return "DW_TAG_try_block";
|
6463 |
|
|
case DW_TAG_variant_part:
|
6464 |
|
|
return "DW_TAG_variant_part";
|
6465 |
|
|
case DW_TAG_variable:
|
6466 |
|
|
return "DW_TAG_variable";
|
6467 |
|
|
case DW_TAG_volatile_type:
|
6468 |
|
|
return "DW_TAG_volatile_type";
|
6469 |
|
|
case DW_TAG_dwarf_procedure:
|
6470 |
|
|
return "DW_TAG_dwarf_procedure";
|
6471 |
|
|
case DW_TAG_restrict_type:
|
6472 |
|
|
return "DW_TAG_restrict_type";
|
6473 |
|
|
case DW_TAG_interface_type:
|
6474 |
|
|
return "DW_TAG_interface_type";
|
6475 |
|
|
case DW_TAG_namespace:
|
6476 |
|
|
return "DW_TAG_namespace";
|
6477 |
|
|
case DW_TAG_imported_module:
|
6478 |
|
|
return "DW_TAG_imported_module";
|
6479 |
|
|
case DW_TAG_unspecified_type:
|
6480 |
|
|
return "DW_TAG_unspecified_type";
|
6481 |
|
|
case DW_TAG_partial_unit:
|
6482 |
|
|
return "DW_TAG_partial_unit";
|
6483 |
|
|
case DW_TAG_imported_unit:
|
6484 |
|
|
return "DW_TAG_imported_unit";
|
6485 |
|
|
case DW_TAG_condition:
|
6486 |
|
|
return "DW_TAG_condition";
|
6487 |
|
|
case DW_TAG_shared_type:
|
6488 |
|
|
return "DW_TAG_shared_type";
|
6489 |
|
|
case DW_TAG_type_unit:
|
6490 |
|
|
return "DW_TAG_type_unit";
|
6491 |
|
|
case DW_TAG_rvalue_reference_type:
|
6492 |
|
|
return "DW_TAG_rvalue_reference_type";
|
6493 |
|
|
case DW_TAG_template_alias:
|
6494 |
|
|
return "DW_TAG_template_alias";
|
6495 |
|
|
case DW_TAG_GNU_template_parameter_pack:
|
6496 |
|
|
return "DW_TAG_GNU_template_parameter_pack";
|
6497 |
|
|
case DW_TAG_GNU_formal_parameter_pack:
|
6498 |
|
|
return "DW_TAG_GNU_formal_parameter_pack";
|
6499 |
|
|
case DW_TAG_MIPS_loop:
|
6500 |
|
|
return "DW_TAG_MIPS_loop";
|
6501 |
|
|
case DW_TAG_format_label:
|
6502 |
|
|
return "DW_TAG_format_label";
|
6503 |
|
|
case DW_TAG_function_template:
|
6504 |
|
|
return "DW_TAG_function_template";
|
6505 |
|
|
case DW_TAG_class_template:
|
6506 |
|
|
return "DW_TAG_class_template";
|
6507 |
|
|
case DW_TAG_GNU_BINCL:
|
6508 |
|
|
return "DW_TAG_GNU_BINCL";
|
6509 |
|
|
case DW_TAG_GNU_EINCL:
|
6510 |
|
|
return "DW_TAG_GNU_EINCL";
|
6511 |
|
|
case DW_TAG_GNU_template_template_param:
|
6512 |
|
|
return "DW_TAG_GNU_template_template_param";
|
6513 |
|
|
default:
|
6514 |
|
|
return "DW_TAG_<unknown>";
|
6515 |
|
|
}
|
6516 |
|
|
}
|
6517 |
|
|
|
6518 |
|
|
/* Convert a DWARF attribute code into its string name. */
|
6519 |
|
|
|
6520 |
|
|
static const char *
|
6521 |
|
|
dwarf_attr_name (unsigned int attr)
|
6522 |
|
|
{
|
6523 |
|
|
switch (attr)
|
6524 |
|
|
{
|
6525 |
|
|
case DW_AT_sibling:
|
6526 |
|
|
return "DW_AT_sibling";
|
6527 |
|
|
case DW_AT_location:
|
6528 |
|
|
return "DW_AT_location";
|
6529 |
|
|
case DW_AT_name:
|
6530 |
|
|
return "DW_AT_name";
|
6531 |
|
|
case DW_AT_ordering:
|
6532 |
|
|
return "DW_AT_ordering";
|
6533 |
|
|
case DW_AT_subscr_data:
|
6534 |
|
|
return "DW_AT_subscr_data";
|
6535 |
|
|
case DW_AT_byte_size:
|
6536 |
|
|
return "DW_AT_byte_size";
|
6537 |
|
|
case DW_AT_bit_offset:
|
6538 |
|
|
return "DW_AT_bit_offset";
|
6539 |
|
|
case DW_AT_bit_size:
|
6540 |
|
|
return "DW_AT_bit_size";
|
6541 |
|
|
case DW_AT_element_list:
|
6542 |
|
|
return "DW_AT_element_list";
|
6543 |
|
|
case DW_AT_stmt_list:
|
6544 |
|
|
return "DW_AT_stmt_list";
|
6545 |
|
|
case DW_AT_low_pc:
|
6546 |
|
|
return "DW_AT_low_pc";
|
6547 |
|
|
case DW_AT_high_pc:
|
6548 |
|
|
return "DW_AT_high_pc";
|
6549 |
|
|
case DW_AT_language:
|
6550 |
|
|
return "DW_AT_language";
|
6551 |
|
|
case DW_AT_member:
|
6552 |
|
|
return "DW_AT_member";
|
6553 |
|
|
case DW_AT_discr:
|
6554 |
|
|
return "DW_AT_discr";
|
6555 |
|
|
case DW_AT_discr_value:
|
6556 |
|
|
return "DW_AT_discr_value";
|
6557 |
|
|
case DW_AT_visibility:
|
6558 |
|
|
return "DW_AT_visibility";
|
6559 |
|
|
case DW_AT_import:
|
6560 |
|
|
return "DW_AT_import";
|
6561 |
|
|
case DW_AT_string_length:
|
6562 |
|
|
return "DW_AT_string_length";
|
6563 |
|
|
case DW_AT_common_reference:
|
6564 |
|
|
return "DW_AT_common_reference";
|
6565 |
|
|
case DW_AT_comp_dir:
|
6566 |
|
|
return "DW_AT_comp_dir";
|
6567 |
|
|
case DW_AT_const_value:
|
6568 |
|
|
return "DW_AT_const_value";
|
6569 |
|
|
case DW_AT_containing_type:
|
6570 |
|
|
return "DW_AT_containing_type";
|
6571 |
|
|
case DW_AT_default_value:
|
6572 |
|
|
return "DW_AT_default_value";
|
6573 |
|
|
case DW_AT_inline:
|
6574 |
|
|
return "DW_AT_inline";
|
6575 |
|
|
case DW_AT_is_optional:
|
6576 |
|
|
return "DW_AT_is_optional";
|
6577 |
|
|
case DW_AT_lower_bound:
|
6578 |
|
|
return "DW_AT_lower_bound";
|
6579 |
|
|
case DW_AT_producer:
|
6580 |
|
|
return "DW_AT_producer";
|
6581 |
|
|
case DW_AT_prototyped:
|
6582 |
|
|
return "DW_AT_prototyped";
|
6583 |
|
|
case DW_AT_return_addr:
|
6584 |
|
|
return "DW_AT_return_addr";
|
6585 |
|
|
case DW_AT_start_scope:
|
6586 |
|
|
return "DW_AT_start_scope";
|
6587 |
|
|
case DW_AT_bit_stride:
|
6588 |
|
|
return "DW_AT_bit_stride";
|
6589 |
|
|
case DW_AT_upper_bound:
|
6590 |
|
|
return "DW_AT_upper_bound";
|
6591 |
|
|
case DW_AT_abstract_origin:
|
6592 |
|
|
return "DW_AT_abstract_origin";
|
6593 |
|
|
case DW_AT_accessibility:
|
6594 |
|
|
return "DW_AT_accessibility";
|
6595 |
|
|
case DW_AT_address_class:
|
6596 |
|
|
return "DW_AT_address_class";
|
6597 |
|
|
case DW_AT_artificial:
|
6598 |
|
|
return "DW_AT_artificial";
|
6599 |
|
|
case DW_AT_base_types:
|
6600 |
|
|
return "DW_AT_base_types";
|
6601 |
|
|
case DW_AT_calling_convention:
|
6602 |
|
|
return "DW_AT_calling_convention";
|
6603 |
|
|
case DW_AT_count:
|
6604 |
|
|
return "DW_AT_count";
|
6605 |
|
|
case DW_AT_data_member_location:
|
6606 |
|
|
return "DW_AT_data_member_location";
|
6607 |
|
|
case DW_AT_decl_column:
|
6608 |
|
|
return "DW_AT_decl_column";
|
6609 |
|
|
case DW_AT_decl_file:
|
6610 |
|
|
return "DW_AT_decl_file";
|
6611 |
|
|
case DW_AT_decl_line:
|
6612 |
|
|
return "DW_AT_decl_line";
|
6613 |
|
|
case DW_AT_declaration:
|
6614 |
|
|
return "DW_AT_declaration";
|
6615 |
|
|
case DW_AT_discr_list:
|
6616 |
|
|
return "DW_AT_discr_list";
|
6617 |
|
|
case DW_AT_encoding:
|
6618 |
|
|
return "DW_AT_encoding";
|
6619 |
|
|
case DW_AT_external:
|
6620 |
|
|
return "DW_AT_external";
|
6621 |
|
|
case DW_AT_explicit:
|
6622 |
|
|
return "DW_AT_explicit";
|
6623 |
|
|
case DW_AT_frame_base:
|
6624 |
|
|
return "DW_AT_frame_base";
|
6625 |
|
|
case DW_AT_friend:
|
6626 |
|
|
return "DW_AT_friend";
|
6627 |
|
|
case DW_AT_identifier_case:
|
6628 |
|
|
return "DW_AT_identifier_case";
|
6629 |
|
|
case DW_AT_macro_info:
|
6630 |
|
|
return "DW_AT_macro_info";
|
6631 |
|
|
case DW_AT_namelist_items:
|
6632 |
|
|
return "DW_AT_namelist_items";
|
6633 |
|
|
case DW_AT_priority:
|
6634 |
|
|
return "DW_AT_priority";
|
6635 |
|
|
case DW_AT_segment:
|
6636 |
|
|
return "DW_AT_segment";
|
6637 |
|
|
case DW_AT_specification:
|
6638 |
|
|
return "DW_AT_specification";
|
6639 |
|
|
case DW_AT_static_link:
|
6640 |
|
|
return "DW_AT_static_link";
|
6641 |
|
|
case DW_AT_type:
|
6642 |
|
|
return "DW_AT_type";
|
6643 |
|
|
case DW_AT_use_location:
|
6644 |
|
|
return "DW_AT_use_location";
|
6645 |
|
|
case DW_AT_variable_parameter:
|
6646 |
|
|
return "DW_AT_variable_parameter";
|
6647 |
|
|
case DW_AT_virtuality:
|
6648 |
|
|
return "DW_AT_virtuality";
|
6649 |
|
|
case DW_AT_vtable_elem_location:
|
6650 |
|
|
return "DW_AT_vtable_elem_location";
|
6651 |
|
|
|
6652 |
|
|
case DW_AT_allocated:
|
6653 |
|
|
return "DW_AT_allocated";
|
6654 |
|
|
case DW_AT_associated:
|
6655 |
|
|
return "DW_AT_associated";
|
6656 |
|
|
case DW_AT_data_location:
|
6657 |
|
|
return "DW_AT_data_location";
|
6658 |
|
|
case DW_AT_byte_stride:
|
6659 |
|
|
return "DW_AT_byte_stride";
|
6660 |
|
|
case DW_AT_entry_pc:
|
6661 |
|
|
return "DW_AT_entry_pc";
|
6662 |
|
|
case DW_AT_use_UTF8:
|
6663 |
|
|
return "DW_AT_use_UTF8";
|
6664 |
|
|
case DW_AT_extension:
|
6665 |
|
|
return "DW_AT_extension";
|
6666 |
|
|
case DW_AT_ranges:
|
6667 |
|
|
return "DW_AT_ranges";
|
6668 |
|
|
case DW_AT_trampoline:
|
6669 |
|
|
return "DW_AT_trampoline";
|
6670 |
|
|
case DW_AT_call_column:
|
6671 |
|
|
return "DW_AT_call_column";
|
6672 |
|
|
case DW_AT_call_file:
|
6673 |
|
|
return "DW_AT_call_file";
|
6674 |
|
|
case DW_AT_call_line:
|
6675 |
|
|
return "DW_AT_call_line";
|
6676 |
|
|
|
6677 |
|
|
case DW_AT_signature:
|
6678 |
|
|
return "DW_AT_signature";
|
6679 |
|
|
case DW_AT_main_subprogram:
|
6680 |
|
|
return "DW_AT_main_subprogram";
|
6681 |
|
|
case DW_AT_data_bit_offset:
|
6682 |
|
|
return "DW_AT_data_bit_offset";
|
6683 |
|
|
case DW_AT_const_expr:
|
6684 |
|
|
return "DW_AT_const_expr";
|
6685 |
|
|
case DW_AT_enum_class:
|
6686 |
|
|
return "DW_AT_enum_class";
|
6687 |
|
|
case DW_AT_linkage_name:
|
6688 |
|
|
return "DW_AT_linkage_name";
|
6689 |
|
|
|
6690 |
|
|
case DW_AT_MIPS_fde:
|
6691 |
|
|
return "DW_AT_MIPS_fde";
|
6692 |
|
|
case DW_AT_MIPS_loop_begin:
|
6693 |
|
|
return "DW_AT_MIPS_loop_begin";
|
6694 |
|
|
case DW_AT_MIPS_tail_loop_begin:
|
6695 |
|
|
return "DW_AT_MIPS_tail_loop_begin";
|
6696 |
|
|
case DW_AT_MIPS_epilog_begin:
|
6697 |
|
|
return "DW_AT_MIPS_epilog_begin";
|
6698 |
|
|
case DW_AT_MIPS_loop_unroll_factor:
|
6699 |
|
|
return "DW_AT_MIPS_loop_unroll_factor";
|
6700 |
|
|
case DW_AT_MIPS_software_pipeline_depth:
|
6701 |
|
|
return "DW_AT_MIPS_software_pipeline_depth";
|
6702 |
|
|
case DW_AT_MIPS_linkage_name:
|
6703 |
|
|
return "DW_AT_MIPS_linkage_name";
|
6704 |
|
|
case DW_AT_MIPS_stride:
|
6705 |
|
|
return "DW_AT_MIPS_stride";
|
6706 |
|
|
case DW_AT_MIPS_abstract_name:
|
6707 |
|
|
return "DW_AT_MIPS_abstract_name";
|
6708 |
|
|
case DW_AT_MIPS_clone_origin:
|
6709 |
|
|
return "DW_AT_MIPS_clone_origin";
|
6710 |
|
|
case DW_AT_MIPS_has_inlines:
|
6711 |
|
|
return "DW_AT_MIPS_has_inlines";
|
6712 |
|
|
|
6713 |
|
|
case DW_AT_sf_names:
|
6714 |
|
|
return "DW_AT_sf_names";
|
6715 |
|
|
case DW_AT_src_info:
|
6716 |
|
|
return "DW_AT_src_info";
|
6717 |
|
|
case DW_AT_mac_info:
|
6718 |
|
|
return "DW_AT_mac_info";
|
6719 |
|
|
case DW_AT_src_coords:
|
6720 |
|
|
return "DW_AT_src_coords";
|
6721 |
|
|
case DW_AT_body_begin:
|
6722 |
|
|
return "DW_AT_body_begin";
|
6723 |
|
|
case DW_AT_body_end:
|
6724 |
|
|
return "DW_AT_body_end";
|
6725 |
|
|
case DW_AT_GNU_vector:
|
6726 |
|
|
return "DW_AT_GNU_vector";
|
6727 |
|
|
case DW_AT_GNU_guarded_by:
|
6728 |
|
|
return "DW_AT_GNU_guarded_by";
|
6729 |
|
|
case DW_AT_GNU_pt_guarded_by:
|
6730 |
|
|
return "DW_AT_GNU_pt_guarded_by";
|
6731 |
|
|
case DW_AT_GNU_guarded:
|
6732 |
|
|
return "DW_AT_GNU_guarded";
|
6733 |
|
|
case DW_AT_GNU_pt_guarded:
|
6734 |
|
|
return "DW_AT_GNU_pt_guarded";
|
6735 |
|
|
case DW_AT_GNU_locks_excluded:
|
6736 |
|
|
return "DW_AT_GNU_locks_excluded";
|
6737 |
|
|
case DW_AT_GNU_exclusive_locks_required:
|
6738 |
|
|
return "DW_AT_GNU_exclusive_locks_required";
|
6739 |
|
|
case DW_AT_GNU_shared_locks_required:
|
6740 |
|
|
return "DW_AT_GNU_shared_locks_required";
|
6741 |
|
|
case DW_AT_GNU_odr_signature:
|
6742 |
|
|
return "DW_AT_GNU_odr_signature";
|
6743 |
|
|
case DW_AT_GNU_template_name:
|
6744 |
|
|
return "DW_AT_GNU_template_name";
|
6745 |
|
|
|
6746 |
|
|
case DW_AT_VMS_rtnbeg_pd_address:
|
6747 |
|
|
return "DW_AT_VMS_rtnbeg_pd_address";
|
6748 |
|
|
|
6749 |
|
|
default:
|
6750 |
|
|
return "DW_AT_<unknown>";
|
6751 |
|
|
}
|
6752 |
|
|
}
|
6753 |
|
|
|
6754 |
|
|
/* Convert a DWARF value form code into its string name. */
|
6755 |
|
|
|
6756 |
|
|
static const char *
|
6757 |
|
|
dwarf_form_name (unsigned int form)
|
6758 |
|
|
{
|
6759 |
|
|
switch (form)
|
6760 |
|
|
{
|
6761 |
|
|
case DW_FORM_addr:
|
6762 |
|
|
return "DW_FORM_addr";
|
6763 |
|
|
case DW_FORM_block2:
|
6764 |
|
|
return "DW_FORM_block2";
|
6765 |
|
|
case DW_FORM_block4:
|
6766 |
|
|
return "DW_FORM_block4";
|
6767 |
|
|
case DW_FORM_data2:
|
6768 |
|
|
return "DW_FORM_data2";
|
6769 |
|
|
case DW_FORM_data4:
|
6770 |
|
|
return "DW_FORM_data4";
|
6771 |
|
|
case DW_FORM_data8:
|
6772 |
|
|
return "DW_FORM_data8";
|
6773 |
|
|
case DW_FORM_string:
|
6774 |
|
|
return "DW_FORM_string";
|
6775 |
|
|
case DW_FORM_block:
|
6776 |
|
|
return "DW_FORM_block";
|
6777 |
|
|
case DW_FORM_block1:
|
6778 |
|
|
return "DW_FORM_block1";
|
6779 |
|
|
case DW_FORM_data1:
|
6780 |
|
|
return "DW_FORM_data1";
|
6781 |
|
|
case DW_FORM_flag:
|
6782 |
|
|
return "DW_FORM_flag";
|
6783 |
|
|
case DW_FORM_sdata:
|
6784 |
|
|
return "DW_FORM_sdata";
|
6785 |
|
|
case DW_FORM_strp:
|
6786 |
|
|
return "DW_FORM_strp";
|
6787 |
|
|
case DW_FORM_udata:
|
6788 |
|
|
return "DW_FORM_udata";
|
6789 |
|
|
case DW_FORM_ref_addr:
|
6790 |
|
|
return "DW_FORM_ref_addr";
|
6791 |
|
|
case DW_FORM_ref1:
|
6792 |
|
|
return "DW_FORM_ref1";
|
6793 |
|
|
case DW_FORM_ref2:
|
6794 |
|
|
return "DW_FORM_ref2";
|
6795 |
|
|
case DW_FORM_ref4:
|
6796 |
|
|
return "DW_FORM_ref4";
|
6797 |
|
|
case DW_FORM_ref8:
|
6798 |
|
|
return "DW_FORM_ref8";
|
6799 |
|
|
case DW_FORM_ref_udata:
|
6800 |
|
|
return "DW_FORM_ref_udata";
|
6801 |
|
|
case DW_FORM_indirect:
|
6802 |
|
|
return "DW_FORM_indirect";
|
6803 |
|
|
case DW_FORM_sec_offset:
|
6804 |
|
|
return "DW_FORM_sec_offset";
|
6805 |
|
|
case DW_FORM_exprloc:
|
6806 |
|
|
return "DW_FORM_exprloc";
|
6807 |
|
|
case DW_FORM_flag_present:
|
6808 |
|
|
return "DW_FORM_flag_present";
|
6809 |
|
|
case DW_FORM_ref_sig8:
|
6810 |
|
|
return "DW_FORM_ref_sig8";
|
6811 |
|
|
default:
|
6812 |
|
|
return "DW_FORM_<unknown>";
|
6813 |
|
|
}
|
6814 |
|
|
}
|
6815 |
|
|
|
6816 |
|
|
/* Determine the "ultimate origin" of a decl. The decl may be an inlined
|
6817 |
|
|
instance of an inlined instance of a decl which is local to an inline
|
6818 |
|
|
function, so we have to trace all of the way back through the origin chain
|
6819 |
|
|
to find out what sort of node actually served as the original seed for the
|
6820 |
|
|
given block. */
|
6821 |
|
|
|
6822 |
|
|
static tree
|
6823 |
|
|
decl_ultimate_origin (const_tree decl)
|
6824 |
|
|
{
|
6825 |
|
|
if (!CODE_CONTAINS_STRUCT (TREE_CODE (decl), TS_DECL_COMMON))
|
6826 |
|
|
return NULL_TREE;
|
6827 |
|
|
|
6828 |
|
|
/* output_inline_function sets DECL_ABSTRACT_ORIGIN for all the
|
6829 |
|
|
nodes in the function to point to themselves; ignore that if
|
6830 |
|
|
we're trying to output the abstract instance of this function. */
|
6831 |
|
|
if (DECL_ABSTRACT (decl) && DECL_ABSTRACT_ORIGIN (decl) == decl)
|
6832 |
|
|
return NULL_TREE;
|
6833 |
|
|
|
6834 |
|
|
/* Since the DECL_ABSTRACT_ORIGIN for a DECL is supposed to be the
|
6835 |
|
|
most distant ancestor, this should never happen. */
|
6836 |
|
|
gcc_assert (!DECL_FROM_INLINE (DECL_ORIGIN (decl)));
|
6837 |
|
|
|
6838 |
|
|
return DECL_ABSTRACT_ORIGIN (decl);
|
6839 |
|
|
}
|
6840 |
|
|
|
6841 |
|
|
/* Get the class to which DECL belongs, if any. In g++, the DECL_CONTEXT
|
6842 |
|
|
of a virtual function may refer to a base class, so we check the 'this'
|
6843 |
|
|
parameter. */
|
6844 |
|
|
|
6845 |
|
|
static tree
|
6846 |
|
|
decl_class_context (tree decl)
|
6847 |
|
|
{
|
6848 |
|
|
tree context = NULL_TREE;
|
6849 |
|
|
|
6850 |
|
|
if (TREE_CODE (decl) != FUNCTION_DECL || ! DECL_VINDEX (decl))
|
6851 |
|
|
context = DECL_CONTEXT (decl);
|
6852 |
|
|
else
|
6853 |
|
|
context = TYPE_MAIN_VARIANT
|
6854 |
|
|
(TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl)))));
|
6855 |
|
|
|
6856 |
|
|
if (context && !TYPE_P (context))
|
6857 |
|
|
context = NULL_TREE;
|
6858 |
|
|
|
6859 |
|
|
return context;
|
6860 |
|
|
}
|
6861 |
|
|
|
6862 |
|
|
/* Add an attribute/value pair to a DIE. */
|
6863 |
|
|
|
6864 |
|
|
static inline void
|
6865 |
|
|
add_dwarf_attr (dw_die_ref die, dw_attr_ref attr)
|
6866 |
|
|
{
|
6867 |
|
|
/* Maybe this should be an assert? */
|
6868 |
|
|
if (die == NULL)
|
6869 |
|
|
return;
|
6870 |
|
|
|
6871 |
|
|
if (die->die_attr == NULL)
|
6872 |
|
|
die->die_attr = VEC_alloc (dw_attr_node, gc, 1);
|
6873 |
|
|
VEC_safe_push (dw_attr_node, gc, die->die_attr, attr);
|
6874 |
|
|
}
|
6875 |
|
|
|
6876 |
|
|
static inline enum dw_val_class
|
6877 |
|
|
AT_class (dw_attr_ref a)
|
6878 |
|
|
{
|
6879 |
|
|
return a->dw_attr_val.val_class;
|
6880 |
|
|
}
|
6881 |
|
|
|
6882 |
|
|
/* Add a flag value attribute to a DIE. */
|
6883 |
|
|
|
6884 |
|
|
static inline void
|
6885 |
|
|
add_AT_flag (dw_die_ref die, enum dwarf_attribute attr_kind, unsigned int flag)
|
6886 |
|
|
{
|
6887 |
|
|
dw_attr_node attr;
|
6888 |
|
|
|
6889 |
|
|
attr.dw_attr = attr_kind;
|
6890 |
|
|
attr.dw_attr_val.val_class = dw_val_class_flag;
|
6891 |
|
|
attr.dw_attr_val.v.val_flag = flag;
|
6892 |
|
|
add_dwarf_attr (die, &attr);
|
6893 |
|
|
}
|
6894 |
|
|
|
6895 |
|
|
static inline unsigned
|
6896 |
|
|
AT_flag (dw_attr_ref a)
|
6897 |
|
|
{
|
6898 |
|
|
gcc_assert (a && AT_class (a) == dw_val_class_flag);
|
6899 |
|
|
return a->dw_attr_val.v.val_flag;
|
6900 |
|
|
}
|
6901 |
|
|
|
6902 |
|
|
/* Add a signed integer attribute value to a DIE. */
|
6903 |
|
|
|
6904 |
|
|
static inline void
|
6905 |
|
|
add_AT_int (dw_die_ref die, enum dwarf_attribute attr_kind, HOST_WIDE_INT int_val)
|
6906 |
|
|
{
|
6907 |
|
|
dw_attr_node attr;
|
6908 |
|
|
|
6909 |
|
|
attr.dw_attr = attr_kind;
|
6910 |
|
|
attr.dw_attr_val.val_class = dw_val_class_const;
|
6911 |
|
|
attr.dw_attr_val.v.val_int = int_val;
|
6912 |
|
|
add_dwarf_attr (die, &attr);
|
6913 |
|
|
}
|
6914 |
|
|
|
6915 |
|
|
static inline HOST_WIDE_INT
|
6916 |
|
|
AT_int (dw_attr_ref a)
|
6917 |
|
|
{
|
6918 |
|
|
gcc_assert (a && AT_class (a) == dw_val_class_const);
|
6919 |
|
|
return a->dw_attr_val.v.val_int;
|
6920 |
|
|
}
|
6921 |
|
|
|
6922 |
|
|
/* Add an unsigned integer attribute value to a DIE. */
|
6923 |
|
|
|
6924 |
|
|
static inline void
|
6925 |
|
|
add_AT_unsigned (dw_die_ref die, enum dwarf_attribute attr_kind,
|
6926 |
|
|
unsigned HOST_WIDE_INT unsigned_val)
|
6927 |
|
|
{
|
6928 |
|
|
dw_attr_node attr;
|
6929 |
|
|
|
6930 |
|
|
attr.dw_attr = attr_kind;
|
6931 |
|
|
attr.dw_attr_val.val_class = dw_val_class_unsigned_const;
|
6932 |
|
|
attr.dw_attr_val.v.val_unsigned = unsigned_val;
|
6933 |
|
|
add_dwarf_attr (die, &attr);
|
6934 |
|
|
}
|
6935 |
|
|
|
6936 |
|
|
static inline unsigned HOST_WIDE_INT
|
6937 |
|
|
AT_unsigned (dw_attr_ref a)
|
6938 |
|
|
{
|
6939 |
|
|
gcc_assert (a && AT_class (a) == dw_val_class_unsigned_const);
|
6940 |
|
|
return a->dw_attr_val.v.val_unsigned;
|
6941 |
|
|
}
|
6942 |
|
|
|
6943 |
|
|
/* Add an unsigned double integer attribute value to a DIE. */
|
6944 |
|
|
|
6945 |
|
|
static inline void
|
6946 |
|
|
add_AT_double (dw_die_ref die, enum dwarf_attribute attr_kind,
|
6947 |
|
|
HOST_WIDE_INT high, unsigned HOST_WIDE_INT low)
|
6948 |
|
|
{
|
6949 |
|
|
dw_attr_node attr;
|
6950 |
|
|
|
6951 |
|
|
attr.dw_attr = attr_kind;
|
6952 |
|
|
attr.dw_attr_val.val_class = dw_val_class_const_double;
|
6953 |
|
|
attr.dw_attr_val.v.val_double.high = high;
|
6954 |
|
|
attr.dw_attr_val.v.val_double.low = low;
|
6955 |
|
|
add_dwarf_attr (die, &attr);
|
6956 |
|
|
}
|
6957 |
|
|
|
6958 |
|
|
/* Add a floating point attribute value to a DIE and return it. */
|
6959 |
|
|
|
6960 |
|
|
static inline void
|
6961 |
|
|
add_AT_vec (dw_die_ref die, enum dwarf_attribute attr_kind,
|
6962 |
|
|
unsigned int length, unsigned int elt_size, unsigned char *array)
|
6963 |
|
|
{
|
6964 |
|
|
dw_attr_node attr;
|
6965 |
|
|
|
6966 |
|
|
attr.dw_attr = attr_kind;
|
6967 |
|
|
attr.dw_attr_val.val_class = dw_val_class_vec;
|
6968 |
|
|
attr.dw_attr_val.v.val_vec.length = length;
|
6969 |
|
|
attr.dw_attr_val.v.val_vec.elt_size = elt_size;
|
6970 |
|
|
attr.dw_attr_val.v.val_vec.array = array;
|
6971 |
|
|
add_dwarf_attr (die, &attr);
|
6972 |
|
|
}
|
6973 |
|
|
|
6974 |
|
|
/* Add an 8-byte data attribute value to a DIE. */
|
6975 |
|
|
|
6976 |
|
|
static inline void
|
6977 |
|
|
add_AT_data8 (dw_die_ref die, enum dwarf_attribute attr_kind,
|
6978 |
|
|
unsigned char data8[8])
|
6979 |
|
|
{
|
6980 |
|
|
dw_attr_node attr;
|
6981 |
|
|
|
6982 |
|
|
attr.dw_attr = attr_kind;
|
6983 |
|
|
attr.dw_attr_val.val_class = dw_val_class_data8;
|
6984 |
|
|
memcpy (attr.dw_attr_val.v.val_data8, data8, 8);
|
6985 |
|
|
add_dwarf_attr (die, &attr);
|
6986 |
|
|
}
|
6987 |
|
|
|
6988 |
|
|
/* Hash and equality functions for debug_str_hash. */
|
6989 |
|
|
|
6990 |
|
|
static hashval_t
|
6991 |
|
|
debug_str_do_hash (const void *x)
|
6992 |
|
|
{
|
6993 |
|
|
return htab_hash_string (((const struct indirect_string_node *)x)->str);
|
6994 |
|
|
}
|
6995 |
|
|
|
6996 |
|
|
static int
|
6997 |
|
|
debug_str_eq (const void *x1, const void *x2)
|
6998 |
|
|
{
|
6999 |
|
|
return strcmp ((((const struct indirect_string_node *)x1)->str),
|
7000 |
|
|
(const char *)x2) == 0;
|
7001 |
|
|
}
|
7002 |
|
|
|
7003 |
|
|
/* Add STR to the indirect string hash table. */
|
7004 |
|
|
|
7005 |
|
|
static struct indirect_string_node *
|
7006 |
|
|
find_AT_string (const char *str)
|
7007 |
|
|
{
|
7008 |
|
|
struct indirect_string_node *node;
|
7009 |
|
|
void **slot;
|
7010 |
|
|
|
7011 |
|
|
if (! debug_str_hash)
|
7012 |
|
|
debug_str_hash = htab_create_ggc (10, debug_str_do_hash,
|
7013 |
|
|
debug_str_eq, NULL);
|
7014 |
|
|
|
7015 |
|
|
slot = htab_find_slot_with_hash (debug_str_hash, str,
|
7016 |
|
|
htab_hash_string (str), INSERT);
|
7017 |
|
|
if (*slot == NULL)
|
7018 |
|
|
{
|
7019 |
|
|
node = (struct indirect_string_node *)
|
7020 |
|
|
ggc_alloc_cleared (sizeof (struct indirect_string_node));
|
7021 |
|
|
node->str = ggc_strdup (str);
|
7022 |
|
|
*slot = node;
|
7023 |
|
|
}
|
7024 |
|
|
else
|
7025 |
|
|
node = (struct indirect_string_node *) *slot;
|
7026 |
|
|
|
7027 |
|
|
node->refcount++;
|
7028 |
|
|
return node;
|
7029 |
|
|
}
|
7030 |
|
|
|
7031 |
|
|
/* Add a string attribute value to a DIE. */
|
7032 |
|
|
|
7033 |
|
|
static inline void
|
7034 |
|
|
add_AT_string (dw_die_ref die, enum dwarf_attribute attr_kind, const char *str)
|
7035 |
|
|
{
|
7036 |
|
|
dw_attr_node attr;
|
7037 |
|
|
struct indirect_string_node *node;
|
7038 |
|
|
|
7039 |
|
|
node = find_AT_string (str);
|
7040 |
|
|
|
7041 |
|
|
attr.dw_attr = attr_kind;
|
7042 |
|
|
attr.dw_attr_val.val_class = dw_val_class_str;
|
7043 |
|
|
attr.dw_attr_val.v.val_str = node;
|
7044 |
|
|
add_dwarf_attr (die, &attr);
|
7045 |
|
|
}
|
7046 |
|
|
|
7047 |
|
|
/* Create a label for an indirect string node, ensuring it is going to
|
7048 |
|
|
be output, unless its reference count goes down to zero. */
|
7049 |
|
|
|
7050 |
|
|
static inline void
|
7051 |
|
|
gen_label_for_indirect_string (struct indirect_string_node *node)
|
7052 |
|
|
{
|
7053 |
|
|
char label[32];
|
7054 |
|
|
|
7055 |
|
|
if (node->label)
|
7056 |
|
|
return;
|
7057 |
|
|
|
7058 |
|
|
ASM_GENERATE_INTERNAL_LABEL (label, "LASF", dw2_string_counter);
|
7059 |
|
|
++dw2_string_counter;
|
7060 |
|
|
node->label = xstrdup (label);
|
7061 |
|
|
}
|
7062 |
|
|
|
7063 |
|
|
/* Create a SYMBOL_REF rtx whose value is the initial address of a
|
7064 |
|
|
debug string STR. */
|
7065 |
|
|
|
7066 |
|
|
static inline rtx
|
7067 |
|
|
get_debug_string_label (const char *str)
|
7068 |
|
|
{
|
7069 |
|
|
struct indirect_string_node *node = find_AT_string (str);
|
7070 |
|
|
|
7071 |
|
|
debug_str_hash_forced = true;
|
7072 |
|
|
|
7073 |
|
|
gen_label_for_indirect_string (node);
|
7074 |
|
|
|
7075 |
|
|
return gen_rtx_SYMBOL_REF (Pmode, node->label);
|
7076 |
|
|
}
|
7077 |
|
|
|
7078 |
|
|
static inline const char *
|
7079 |
|
|
AT_string (dw_attr_ref a)
|
7080 |
|
|
{
|
7081 |
|
|
gcc_assert (a && AT_class (a) == dw_val_class_str);
|
7082 |
|
|
return a->dw_attr_val.v.val_str->str;
|
7083 |
|
|
}
|
7084 |
|
|
|
7085 |
|
|
/* Find out whether a string should be output inline in DIE
|
7086 |
|
|
or out-of-line in .debug_str section. */
|
7087 |
|
|
|
7088 |
|
|
static enum dwarf_form
|
7089 |
|
|
AT_string_form (dw_attr_ref a)
|
7090 |
|
|
{
|
7091 |
|
|
struct indirect_string_node *node;
|
7092 |
|
|
unsigned int len;
|
7093 |
|
|
|
7094 |
|
|
gcc_assert (a && AT_class (a) == dw_val_class_str);
|
7095 |
|
|
|
7096 |
|
|
node = a->dw_attr_val.v.val_str;
|
7097 |
|
|
if (node->form)
|
7098 |
|
|
return node->form;
|
7099 |
|
|
|
7100 |
|
|
len = strlen (node->str) + 1;
|
7101 |
|
|
|
7102 |
|
|
/* If the string is shorter or equal to the size of the reference, it is
|
7103 |
|
|
always better to put it inline. */
|
7104 |
|
|
if (len <= DWARF_OFFSET_SIZE || node->refcount == 0)
|
7105 |
|
|
return node->form = DW_FORM_string;
|
7106 |
|
|
|
7107 |
|
|
/* If we cannot expect the linker to merge strings in .debug_str
|
7108 |
|
|
section, only put it into .debug_str if it is worth even in this
|
7109 |
|
|
single module. */
|
7110 |
|
|
if (DWARF2_INDIRECT_STRING_SUPPORT_MISSING_ON_TARGET
|
7111 |
|
|
|| ((debug_str_section->common.flags & SECTION_MERGE) == 0
|
7112 |
|
|
&& (len - DWARF_OFFSET_SIZE) * node->refcount <= len))
|
7113 |
|
|
return node->form = DW_FORM_string;
|
7114 |
|
|
|
7115 |
|
|
gen_label_for_indirect_string (node);
|
7116 |
|
|
|
7117 |
|
|
return node->form = DW_FORM_strp;
|
7118 |
|
|
}
|
7119 |
|
|
|
7120 |
|
|
/* Add a DIE reference attribute value to a DIE. */
|
7121 |
|
|
|
7122 |
|
|
static inline void
|
7123 |
|
|
add_AT_die_ref (dw_die_ref die, enum dwarf_attribute attr_kind, dw_die_ref targ_die)
|
7124 |
|
|
{
|
7125 |
|
|
dw_attr_node attr;
|
7126 |
|
|
|
7127 |
|
|
attr.dw_attr = attr_kind;
|
7128 |
|
|
attr.dw_attr_val.val_class = dw_val_class_die_ref;
|
7129 |
|
|
attr.dw_attr_val.v.val_die_ref.die = targ_die;
|
7130 |
|
|
attr.dw_attr_val.v.val_die_ref.external = 0;
|
7131 |
|
|
add_dwarf_attr (die, &attr);
|
7132 |
|
|
}
|
7133 |
|
|
|
7134 |
|
|
/* Add an AT_specification attribute to a DIE, and also make the back
|
7135 |
|
|
pointer from the specification to the definition. */
|
7136 |
|
|
|
7137 |
|
|
static inline void
|
7138 |
|
|
add_AT_specification (dw_die_ref die, dw_die_ref targ_die)
|
7139 |
|
|
{
|
7140 |
|
|
add_AT_die_ref (die, DW_AT_specification, targ_die);
|
7141 |
|
|
gcc_assert (!targ_die->die_definition);
|
7142 |
|
|
targ_die->die_definition = die;
|
7143 |
|
|
}
|
7144 |
|
|
|
7145 |
|
|
static inline dw_die_ref
|
7146 |
|
|
AT_ref (dw_attr_ref a)
|
7147 |
|
|
{
|
7148 |
|
|
gcc_assert (a && AT_class (a) == dw_val_class_die_ref);
|
7149 |
|
|
return a->dw_attr_val.v.val_die_ref.die;
|
7150 |
|
|
}
|
7151 |
|
|
|
7152 |
|
|
static inline int
|
7153 |
|
|
AT_ref_external (dw_attr_ref a)
|
7154 |
|
|
{
|
7155 |
|
|
if (a && AT_class (a) == dw_val_class_die_ref)
|
7156 |
|
|
return a->dw_attr_val.v.val_die_ref.external;
|
7157 |
|
|
|
7158 |
|
|
return 0;
|
7159 |
|
|
}
|
7160 |
|
|
|
7161 |
|
|
static inline void
|
7162 |
|
|
set_AT_ref_external (dw_attr_ref a, int i)
|
7163 |
|
|
{
|
7164 |
|
|
gcc_assert (a && AT_class (a) == dw_val_class_die_ref);
|
7165 |
|
|
a->dw_attr_val.v.val_die_ref.external = i;
|
7166 |
|
|
}
|
7167 |
|
|
|
7168 |
|
|
/* Add an FDE reference attribute value to a DIE. */
|
7169 |
|
|
|
7170 |
|
|
static inline void
|
7171 |
|
|
add_AT_fde_ref (dw_die_ref die, enum dwarf_attribute attr_kind, unsigned int targ_fde)
|
7172 |
|
|
{
|
7173 |
|
|
dw_attr_node attr;
|
7174 |
|
|
|
7175 |
|
|
attr.dw_attr = attr_kind;
|
7176 |
|
|
attr.dw_attr_val.val_class = dw_val_class_fde_ref;
|
7177 |
|
|
attr.dw_attr_val.v.val_fde_index = targ_fde;
|
7178 |
|
|
add_dwarf_attr (die, &attr);
|
7179 |
|
|
}
|
7180 |
|
|
|
7181 |
|
|
/* Add a location description attribute value to a DIE. */
|
7182 |
|
|
|
7183 |
|
|
static inline void
|
7184 |
|
|
add_AT_loc (dw_die_ref die, enum dwarf_attribute attr_kind, dw_loc_descr_ref loc)
|
7185 |
|
|
{
|
7186 |
|
|
dw_attr_node attr;
|
7187 |
|
|
|
7188 |
|
|
attr.dw_attr = attr_kind;
|
7189 |
|
|
attr.dw_attr_val.val_class = dw_val_class_loc;
|
7190 |
|
|
attr.dw_attr_val.v.val_loc = loc;
|
7191 |
|
|
add_dwarf_attr (die, &attr);
|
7192 |
|
|
}
|
7193 |
|
|
|
7194 |
|
|
static inline dw_loc_descr_ref
|
7195 |
|
|
AT_loc (dw_attr_ref a)
|
7196 |
|
|
{
|
7197 |
|
|
gcc_assert (a && AT_class (a) == dw_val_class_loc);
|
7198 |
|
|
return a->dw_attr_val.v.val_loc;
|
7199 |
|
|
}
|
7200 |
|
|
|
7201 |
|
|
static inline void
|
7202 |
|
|
add_AT_loc_list (dw_die_ref die, enum dwarf_attribute attr_kind, dw_loc_list_ref loc_list)
|
7203 |
|
|
{
|
7204 |
|
|
dw_attr_node attr;
|
7205 |
|
|
|
7206 |
|
|
attr.dw_attr = attr_kind;
|
7207 |
|
|
attr.dw_attr_val.val_class = dw_val_class_loc_list;
|
7208 |
|
|
attr.dw_attr_val.v.val_loc_list = loc_list;
|
7209 |
|
|
add_dwarf_attr (die, &attr);
|
7210 |
|
|
have_location_lists = true;
|
7211 |
|
|
}
|
7212 |
|
|
|
7213 |
|
|
static inline dw_loc_list_ref
|
7214 |
|
|
AT_loc_list (dw_attr_ref a)
|
7215 |
|
|
{
|
7216 |
|
|
gcc_assert (a && AT_class (a) == dw_val_class_loc_list);
|
7217 |
|
|
return a->dw_attr_val.v.val_loc_list;
|
7218 |
|
|
}
|
7219 |
|
|
|
7220 |
|
|
static inline dw_loc_list_ref *
|
7221 |
|
|
AT_loc_list_ptr (dw_attr_ref a)
|
7222 |
|
|
{
|
7223 |
|
|
gcc_assert (a && AT_class (a) == dw_val_class_loc_list);
|
7224 |
|
|
return &a->dw_attr_val.v.val_loc_list;
|
7225 |
|
|
}
|
7226 |
|
|
|
7227 |
|
|
/* Add an address constant attribute value to a DIE. */
|
7228 |
|
|
|
7229 |
|
|
static inline void
|
7230 |
|
|
add_AT_addr (dw_die_ref die, enum dwarf_attribute attr_kind, rtx addr)
|
7231 |
|
|
{
|
7232 |
|
|
dw_attr_node attr;
|
7233 |
|
|
|
7234 |
|
|
attr.dw_attr = attr_kind;
|
7235 |
|
|
attr.dw_attr_val.val_class = dw_val_class_addr;
|
7236 |
|
|
attr.dw_attr_val.v.val_addr = addr;
|
7237 |
|
|
add_dwarf_attr (die, &attr);
|
7238 |
|
|
}
|
7239 |
|
|
|
7240 |
|
|
/* Get the RTX from to an address DIE attribute. */
|
7241 |
|
|
|
7242 |
|
|
static inline rtx
|
7243 |
|
|
AT_addr (dw_attr_ref a)
|
7244 |
|
|
{
|
7245 |
|
|
gcc_assert (a && AT_class (a) == dw_val_class_addr);
|
7246 |
|
|
return a->dw_attr_val.v.val_addr;
|
7247 |
|
|
}
|
7248 |
|
|
|
7249 |
|
|
/* Add a file attribute value to a DIE. */
|
7250 |
|
|
|
7251 |
|
|
static inline void
|
7252 |
|
|
add_AT_file (dw_die_ref die, enum dwarf_attribute attr_kind,
|
7253 |
|
|
struct dwarf_file_data *fd)
|
7254 |
|
|
{
|
7255 |
|
|
dw_attr_node attr;
|
7256 |
|
|
|
7257 |
|
|
attr.dw_attr = attr_kind;
|
7258 |
|
|
attr.dw_attr_val.val_class = dw_val_class_file;
|
7259 |
|
|
attr.dw_attr_val.v.val_file = fd;
|
7260 |
|
|
add_dwarf_attr (die, &attr);
|
7261 |
|
|
}
|
7262 |
|
|
|
7263 |
|
|
/* Get the dwarf_file_data from a file DIE attribute. */
|
7264 |
|
|
|
7265 |
|
|
static inline struct dwarf_file_data *
|
7266 |
|
|
AT_file (dw_attr_ref a)
|
7267 |
|
|
{
|
7268 |
|
|
gcc_assert (a && AT_class (a) == dw_val_class_file);
|
7269 |
|
|
return a->dw_attr_val.v.val_file;
|
7270 |
|
|
}
|
7271 |
|
|
|
7272 |
|
|
/* Add a label identifier attribute value to a DIE. */
|
7273 |
|
|
|
7274 |
|
|
static inline void
|
7275 |
|
|
add_AT_lbl_id (dw_die_ref die, enum dwarf_attribute attr_kind, const char *lbl_id)
|
7276 |
|
|
{
|
7277 |
|
|
dw_attr_node attr;
|
7278 |
|
|
|
7279 |
|
|
attr.dw_attr = attr_kind;
|
7280 |
|
|
attr.dw_attr_val.val_class = dw_val_class_lbl_id;
|
7281 |
|
|
attr.dw_attr_val.v.val_lbl_id = xstrdup (lbl_id);
|
7282 |
|
|
add_dwarf_attr (die, &attr);
|
7283 |
|
|
}
|
7284 |
|
|
|
7285 |
|
|
/* Add a section offset attribute value to a DIE, an offset into the
|
7286 |
|
|
debug_line section. */
|
7287 |
|
|
|
7288 |
|
|
static inline void
|
7289 |
|
|
add_AT_lineptr (dw_die_ref die, enum dwarf_attribute attr_kind,
|
7290 |
|
|
const char *label)
|
7291 |
|
|
{
|
7292 |
|
|
dw_attr_node attr;
|
7293 |
|
|
|
7294 |
|
|
attr.dw_attr = attr_kind;
|
7295 |
|
|
attr.dw_attr_val.val_class = dw_val_class_lineptr;
|
7296 |
|
|
attr.dw_attr_val.v.val_lbl_id = xstrdup (label);
|
7297 |
|
|
add_dwarf_attr (die, &attr);
|
7298 |
|
|
}
|
7299 |
|
|
|
7300 |
|
|
/* Add a section offset attribute value to a DIE, an offset into the
|
7301 |
|
|
debug_macinfo section. */
|
7302 |
|
|
|
7303 |
|
|
static inline void
|
7304 |
|
|
add_AT_macptr (dw_die_ref die, enum dwarf_attribute attr_kind,
|
7305 |
|
|
const char *label)
|
7306 |
|
|
{
|
7307 |
|
|
dw_attr_node attr;
|
7308 |
|
|
|
7309 |
|
|
attr.dw_attr = attr_kind;
|
7310 |
|
|
attr.dw_attr_val.val_class = dw_val_class_macptr;
|
7311 |
|
|
attr.dw_attr_val.v.val_lbl_id = xstrdup (label);
|
7312 |
|
|
add_dwarf_attr (die, &attr);
|
7313 |
|
|
}
|
7314 |
|
|
|
7315 |
|
|
/* Add an offset attribute value to a DIE. */
|
7316 |
|
|
|
7317 |
|
|
static inline void
|
7318 |
|
|
add_AT_offset (dw_die_ref die, enum dwarf_attribute attr_kind,
|
7319 |
|
|
unsigned HOST_WIDE_INT offset)
|
7320 |
|
|
{
|
7321 |
|
|
dw_attr_node attr;
|
7322 |
|
|
|
7323 |
|
|
attr.dw_attr = attr_kind;
|
7324 |
|
|
attr.dw_attr_val.val_class = dw_val_class_offset;
|
7325 |
|
|
attr.dw_attr_val.v.val_offset = offset;
|
7326 |
|
|
add_dwarf_attr (die, &attr);
|
7327 |
|
|
}
|
7328 |
|
|
|
7329 |
|
|
/* Add an range_list attribute value to a DIE. */
|
7330 |
|
|
|
7331 |
|
|
static void
|
7332 |
|
|
add_AT_range_list (dw_die_ref die, enum dwarf_attribute attr_kind,
|
7333 |
|
|
long unsigned int offset)
|
7334 |
|
|
{
|
7335 |
|
|
dw_attr_node attr;
|
7336 |
|
|
|
7337 |
|
|
attr.dw_attr = attr_kind;
|
7338 |
|
|
attr.dw_attr_val.val_class = dw_val_class_range_list;
|
7339 |
|
|
attr.dw_attr_val.v.val_offset = offset;
|
7340 |
|
|
add_dwarf_attr (die, &attr);
|
7341 |
|
|
}
|
7342 |
|
|
|
7343 |
|
|
static inline const char *
|
7344 |
|
|
AT_lbl (dw_attr_ref a)
|
7345 |
|
|
{
|
7346 |
|
|
gcc_assert (a && (AT_class (a) == dw_val_class_lbl_id
|
7347 |
|
|
|| AT_class (a) == dw_val_class_lineptr
|
7348 |
|
|
|| AT_class (a) == dw_val_class_macptr));
|
7349 |
|
|
return a->dw_attr_val.v.val_lbl_id;
|
7350 |
|
|
}
|
7351 |
|
|
|
7352 |
|
|
/* Get the attribute of type attr_kind. */
|
7353 |
|
|
|
7354 |
|
|
static dw_attr_ref
|
7355 |
|
|
get_AT (dw_die_ref die, enum dwarf_attribute attr_kind)
|
7356 |
|
|
{
|
7357 |
|
|
dw_attr_ref a;
|
7358 |
|
|
unsigned ix;
|
7359 |
|
|
dw_die_ref spec = NULL;
|
7360 |
|
|
|
7361 |
|
|
if (! die)
|
7362 |
|
|
return NULL;
|
7363 |
|
|
|
7364 |
|
|
for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
|
7365 |
|
|
if (a->dw_attr == attr_kind)
|
7366 |
|
|
return a;
|
7367 |
|
|
else if (a->dw_attr == DW_AT_specification
|
7368 |
|
|
|| a->dw_attr == DW_AT_abstract_origin)
|
7369 |
|
|
spec = AT_ref (a);
|
7370 |
|
|
|
7371 |
|
|
if (spec)
|
7372 |
|
|
return get_AT (spec, attr_kind);
|
7373 |
|
|
|
7374 |
|
|
return NULL;
|
7375 |
|
|
}
|
7376 |
|
|
|
7377 |
|
|
/* Return the "low pc" attribute value, typically associated with a subprogram
|
7378 |
|
|
DIE. Return null if the "low pc" attribute is either not present, or if it
|
7379 |
|
|
cannot be represented as an assembler label identifier. */
|
7380 |
|
|
|
7381 |
|
|
static inline const char *
|
7382 |
|
|
get_AT_low_pc (dw_die_ref die)
|
7383 |
|
|
{
|
7384 |
|
|
dw_attr_ref a = get_AT (die, DW_AT_low_pc);
|
7385 |
|
|
|
7386 |
|
|
return a ? AT_lbl (a) : NULL;
|
7387 |
|
|
}
|
7388 |
|
|
|
7389 |
|
|
/* Return the "high pc" attribute value, typically associated with a subprogram
|
7390 |
|
|
DIE. Return null if the "high pc" attribute is either not present, or if it
|
7391 |
|
|
cannot be represented as an assembler label identifier. */
|
7392 |
|
|
|
7393 |
|
|
static inline const char *
|
7394 |
|
|
get_AT_hi_pc (dw_die_ref die)
|
7395 |
|
|
{
|
7396 |
|
|
dw_attr_ref a = get_AT (die, DW_AT_high_pc);
|
7397 |
|
|
|
7398 |
|
|
return a ? AT_lbl (a) : NULL;
|
7399 |
|
|
}
|
7400 |
|
|
|
7401 |
|
|
/* Return the value of the string attribute designated by ATTR_KIND, or
|
7402 |
|
|
NULL if it is not present. */
|
7403 |
|
|
|
7404 |
|
|
static inline const char *
|
7405 |
|
|
get_AT_string (dw_die_ref die, enum dwarf_attribute attr_kind)
|
7406 |
|
|
{
|
7407 |
|
|
dw_attr_ref a = get_AT (die, attr_kind);
|
7408 |
|
|
|
7409 |
|
|
return a ? AT_string (a) : NULL;
|
7410 |
|
|
}
|
7411 |
|
|
|
7412 |
|
|
/* Return the value of the flag attribute designated by ATTR_KIND, or -1
|
7413 |
|
|
if it is not present. */
|
7414 |
|
|
|
7415 |
|
|
static inline int
|
7416 |
|
|
get_AT_flag (dw_die_ref die, enum dwarf_attribute attr_kind)
|
7417 |
|
|
{
|
7418 |
|
|
dw_attr_ref a = get_AT (die, attr_kind);
|
7419 |
|
|
|
7420 |
|
|
return a ? AT_flag (a) : 0;
|
7421 |
|
|
}
|
7422 |
|
|
|
7423 |
|
|
/* Return the value of the unsigned attribute designated by ATTR_KIND, or 0
|
7424 |
|
|
if it is not present. */
|
7425 |
|
|
|
7426 |
|
|
static inline unsigned
|
7427 |
|
|
get_AT_unsigned (dw_die_ref die, enum dwarf_attribute attr_kind)
|
7428 |
|
|
{
|
7429 |
|
|
dw_attr_ref a = get_AT (die, attr_kind);
|
7430 |
|
|
|
7431 |
|
|
return a ? AT_unsigned (a) : 0;
|
7432 |
|
|
}
|
7433 |
|
|
|
7434 |
|
|
static inline dw_die_ref
|
7435 |
|
|
get_AT_ref (dw_die_ref die, enum dwarf_attribute attr_kind)
|
7436 |
|
|
{
|
7437 |
|
|
dw_attr_ref a = get_AT (die, attr_kind);
|
7438 |
|
|
|
7439 |
|
|
return a ? AT_ref (a) : NULL;
|
7440 |
|
|
}
|
7441 |
|
|
|
7442 |
|
|
static inline struct dwarf_file_data *
|
7443 |
|
|
get_AT_file (dw_die_ref die, enum dwarf_attribute attr_kind)
|
7444 |
|
|
{
|
7445 |
|
|
dw_attr_ref a = get_AT (die, attr_kind);
|
7446 |
|
|
|
7447 |
|
|
return a ? AT_file (a) : NULL;
|
7448 |
|
|
}
|
7449 |
|
|
|
7450 |
|
|
/* Return TRUE if the language is C++. */
|
7451 |
|
|
|
7452 |
|
|
static inline bool
|
7453 |
|
|
is_cxx (void)
|
7454 |
|
|
{
|
7455 |
|
|
unsigned int lang = get_AT_unsigned (comp_unit_die, DW_AT_language);
|
7456 |
|
|
|
7457 |
|
|
return lang == DW_LANG_C_plus_plus || lang == DW_LANG_ObjC_plus_plus;
|
7458 |
|
|
}
|
7459 |
|
|
|
7460 |
|
|
/* Return TRUE if the language is Fortran. */
|
7461 |
|
|
|
7462 |
|
|
static inline bool
|
7463 |
|
|
is_fortran (void)
|
7464 |
|
|
{
|
7465 |
|
|
unsigned int lang = get_AT_unsigned (comp_unit_die, DW_AT_language);
|
7466 |
|
|
|
7467 |
|
|
return (lang == DW_LANG_Fortran77
|
7468 |
|
|
|| lang == DW_LANG_Fortran90
|
7469 |
|
|
|| lang == DW_LANG_Fortran95);
|
7470 |
|
|
}
|
7471 |
|
|
|
7472 |
|
|
/* Return TRUE if the language is Ada. */
|
7473 |
|
|
|
7474 |
|
|
static inline bool
|
7475 |
|
|
is_ada (void)
|
7476 |
|
|
{
|
7477 |
|
|
unsigned int lang = get_AT_unsigned (comp_unit_die, DW_AT_language);
|
7478 |
|
|
|
7479 |
|
|
return lang == DW_LANG_Ada95 || lang == DW_LANG_Ada83;
|
7480 |
|
|
}
|
7481 |
|
|
|
7482 |
|
|
/* Remove the specified attribute if present. */
|
7483 |
|
|
|
7484 |
|
|
static void
|
7485 |
|
|
remove_AT (dw_die_ref die, enum dwarf_attribute attr_kind)
|
7486 |
|
|
{
|
7487 |
|
|
dw_attr_ref a;
|
7488 |
|
|
unsigned ix;
|
7489 |
|
|
|
7490 |
|
|
if (! die)
|
7491 |
|
|
return;
|
7492 |
|
|
|
7493 |
|
|
for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
|
7494 |
|
|
if (a->dw_attr == attr_kind)
|
7495 |
|
|
{
|
7496 |
|
|
if (AT_class (a) == dw_val_class_str)
|
7497 |
|
|
if (a->dw_attr_val.v.val_str->refcount)
|
7498 |
|
|
a->dw_attr_val.v.val_str->refcount--;
|
7499 |
|
|
|
7500 |
|
|
/* VEC_ordered_remove should help reduce the number of abbrevs
|
7501 |
|
|
that are needed. */
|
7502 |
|
|
VEC_ordered_remove (dw_attr_node, die->die_attr, ix);
|
7503 |
|
|
return;
|
7504 |
|
|
}
|
7505 |
|
|
}
|
7506 |
|
|
|
7507 |
|
|
/* Remove CHILD from its parent. PREV must have the property that
|
7508 |
|
|
PREV->DIE_SIB == CHILD. Does not alter CHILD. */
|
7509 |
|
|
|
7510 |
|
|
static void
|
7511 |
|
|
remove_child_with_prev (dw_die_ref child, dw_die_ref prev)
|
7512 |
|
|
{
|
7513 |
|
|
gcc_assert (child->die_parent == prev->die_parent);
|
7514 |
|
|
gcc_assert (prev->die_sib == child);
|
7515 |
|
|
if (prev == child)
|
7516 |
|
|
{
|
7517 |
|
|
gcc_assert (child->die_parent->die_child == child);
|
7518 |
|
|
prev = NULL;
|
7519 |
|
|
}
|
7520 |
|
|
else
|
7521 |
|
|
prev->die_sib = child->die_sib;
|
7522 |
|
|
if (child->die_parent->die_child == child)
|
7523 |
|
|
child->die_parent->die_child = prev;
|
7524 |
|
|
}
|
7525 |
|
|
|
7526 |
|
|
/* Replace OLD_CHILD with NEW_CHILD. PREV must have the property that
|
7527 |
|
|
PREV->DIE_SIB == OLD_CHILD. Does not alter OLD_CHILD. */
|
7528 |
|
|
|
7529 |
|
|
static void
|
7530 |
|
|
replace_child (dw_die_ref old_child, dw_die_ref new_child, dw_die_ref prev)
|
7531 |
|
|
{
|
7532 |
|
|
dw_die_ref parent = old_child->die_parent;
|
7533 |
|
|
|
7534 |
|
|
gcc_assert (parent == prev->die_parent);
|
7535 |
|
|
gcc_assert (prev->die_sib == old_child);
|
7536 |
|
|
|
7537 |
|
|
new_child->die_parent = parent;
|
7538 |
|
|
if (prev == old_child)
|
7539 |
|
|
{
|
7540 |
|
|
gcc_assert (parent->die_child == old_child);
|
7541 |
|
|
new_child->die_sib = new_child;
|
7542 |
|
|
}
|
7543 |
|
|
else
|
7544 |
|
|
{
|
7545 |
|
|
prev->die_sib = new_child;
|
7546 |
|
|
new_child->die_sib = old_child->die_sib;
|
7547 |
|
|
}
|
7548 |
|
|
if (old_child->die_parent->die_child == old_child)
|
7549 |
|
|
old_child->die_parent->die_child = new_child;
|
7550 |
|
|
}
|
7551 |
|
|
|
7552 |
|
|
/* Move all children from OLD_PARENT to NEW_PARENT. */
|
7553 |
|
|
|
7554 |
|
|
static void
|
7555 |
|
|
move_all_children (dw_die_ref old_parent, dw_die_ref new_parent)
|
7556 |
|
|
{
|
7557 |
|
|
dw_die_ref c;
|
7558 |
|
|
new_parent->die_child = old_parent->die_child;
|
7559 |
|
|
old_parent->die_child = NULL;
|
7560 |
|
|
FOR_EACH_CHILD (new_parent, c, c->die_parent = new_parent);
|
7561 |
|
|
}
|
7562 |
|
|
|
7563 |
|
|
/* Remove child DIE whose die_tag is TAG. Do nothing if no child
|
7564 |
|
|
matches TAG. */
|
7565 |
|
|
|
7566 |
|
|
static void
|
7567 |
|
|
remove_child_TAG (dw_die_ref die, enum dwarf_tag tag)
|
7568 |
|
|
{
|
7569 |
|
|
dw_die_ref c;
|
7570 |
|
|
|
7571 |
|
|
c = die->die_child;
|
7572 |
|
|
if (c) do {
|
7573 |
|
|
dw_die_ref prev = c;
|
7574 |
|
|
c = c->die_sib;
|
7575 |
|
|
while (c->die_tag == tag)
|
7576 |
|
|
{
|
7577 |
|
|
remove_child_with_prev (c, prev);
|
7578 |
|
|
/* Might have removed every child. */
|
7579 |
|
|
if (c == c->die_sib)
|
7580 |
|
|
return;
|
7581 |
|
|
c = c->die_sib;
|
7582 |
|
|
}
|
7583 |
|
|
} while (c != die->die_child);
|
7584 |
|
|
}
|
7585 |
|
|
|
7586 |
|
|
/* Add a CHILD_DIE as the last child of DIE. */
|
7587 |
|
|
|
7588 |
|
|
static void
|
7589 |
|
|
add_child_die (dw_die_ref die, dw_die_ref child_die)
|
7590 |
|
|
{
|
7591 |
|
|
/* FIXME this should probably be an assert. */
|
7592 |
|
|
if (! die || ! child_die)
|
7593 |
|
|
return;
|
7594 |
|
|
gcc_assert (die != child_die);
|
7595 |
|
|
|
7596 |
|
|
child_die->die_parent = die;
|
7597 |
|
|
if (die->die_child)
|
7598 |
|
|
{
|
7599 |
|
|
child_die->die_sib = die->die_child->die_sib;
|
7600 |
|
|
die->die_child->die_sib = child_die;
|
7601 |
|
|
}
|
7602 |
|
|
else
|
7603 |
|
|
child_die->die_sib = child_die;
|
7604 |
|
|
die->die_child = child_die;
|
7605 |
|
|
}
|
7606 |
|
|
|
7607 |
|
|
/* Move CHILD, which must be a child of PARENT or the DIE for which PARENT
|
7608 |
|
|
is the specification, to the end of PARENT's list of children.
|
7609 |
|
|
This is done by removing and re-adding it. */
|
7610 |
|
|
|
7611 |
|
|
static void
|
7612 |
|
|
splice_child_die (dw_die_ref parent, dw_die_ref child)
|
7613 |
|
|
{
|
7614 |
|
|
dw_die_ref p;
|
7615 |
|
|
|
7616 |
|
|
/* We want the declaration DIE from inside the class, not the
|
7617 |
|
|
specification DIE at toplevel. */
|
7618 |
|
|
if (child->die_parent != parent)
|
7619 |
|
|
{
|
7620 |
|
|
dw_die_ref tmp = get_AT_ref (child, DW_AT_specification);
|
7621 |
|
|
|
7622 |
|
|
if (tmp)
|
7623 |
|
|
child = tmp;
|
7624 |
|
|
}
|
7625 |
|
|
|
7626 |
|
|
gcc_assert (child->die_parent == parent
|
7627 |
|
|
|| (child->die_parent
|
7628 |
|
|
== get_AT_ref (parent, DW_AT_specification)));
|
7629 |
|
|
|
7630 |
|
|
for (p = child->die_parent->die_child; ; p = p->die_sib)
|
7631 |
|
|
if (p->die_sib == child)
|
7632 |
|
|
{
|
7633 |
|
|
remove_child_with_prev (child, p);
|
7634 |
|
|
break;
|
7635 |
|
|
}
|
7636 |
|
|
|
7637 |
|
|
add_child_die (parent, child);
|
7638 |
|
|
}
|
7639 |
|
|
|
7640 |
|
|
/* Return a pointer to a newly created DIE node. */
|
7641 |
|
|
|
7642 |
|
|
static inline dw_die_ref
|
7643 |
|
|
new_die (enum dwarf_tag tag_value, dw_die_ref parent_die, tree t)
|
7644 |
|
|
{
|
7645 |
|
|
dw_die_ref die = GGC_CNEW (die_node);
|
7646 |
|
|
|
7647 |
|
|
die->die_tag = tag_value;
|
7648 |
|
|
|
7649 |
|
|
if (parent_die != NULL)
|
7650 |
|
|
add_child_die (parent_die, die);
|
7651 |
|
|
else
|
7652 |
|
|
{
|
7653 |
|
|
limbo_die_node *limbo_node;
|
7654 |
|
|
|
7655 |
|
|
limbo_node = GGC_CNEW (limbo_die_node);
|
7656 |
|
|
limbo_node->die = die;
|
7657 |
|
|
limbo_node->created_for = t;
|
7658 |
|
|
limbo_node->next = limbo_die_list;
|
7659 |
|
|
limbo_die_list = limbo_node;
|
7660 |
|
|
}
|
7661 |
|
|
|
7662 |
|
|
return die;
|
7663 |
|
|
}
|
7664 |
|
|
|
7665 |
|
|
/* Return the DIE associated with the given type specifier. */
|
7666 |
|
|
|
7667 |
|
|
static inline dw_die_ref
|
7668 |
|
|
lookup_type_die (tree type)
|
7669 |
|
|
{
|
7670 |
|
|
return TYPE_SYMTAB_DIE (type);
|
7671 |
|
|
}
|
7672 |
|
|
|
7673 |
|
|
/* Equate a DIE to a given type specifier. */
|
7674 |
|
|
|
7675 |
|
|
static inline void
|
7676 |
|
|
equate_type_number_to_die (tree type, dw_die_ref type_die)
|
7677 |
|
|
{
|
7678 |
|
|
TYPE_SYMTAB_DIE (type) = type_die;
|
7679 |
|
|
}
|
7680 |
|
|
|
7681 |
|
|
/* Returns a hash value for X (which really is a die_struct). */
|
7682 |
|
|
|
7683 |
|
|
static hashval_t
|
7684 |
|
|
decl_die_table_hash (const void *x)
|
7685 |
|
|
{
|
7686 |
|
|
return (hashval_t) ((const_dw_die_ref) x)->decl_id;
|
7687 |
|
|
}
|
7688 |
|
|
|
7689 |
|
|
/* Return nonzero if decl_id of die_struct X is the same as UID of decl *Y. */
|
7690 |
|
|
|
7691 |
|
|
static int
|
7692 |
|
|
decl_die_table_eq (const void *x, const void *y)
|
7693 |
|
|
{
|
7694 |
|
|
return (((const_dw_die_ref) x)->decl_id == DECL_UID ((const_tree) y));
|
7695 |
|
|
}
|
7696 |
|
|
|
7697 |
|
|
/* Return the DIE associated with a given declaration. */
|
7698 |
|
|
|
7699 |
|
|
static inline dw_die_ref
|
7700 |
|
|
lookup_decl_die (tree decl)
|
7701 |
|
|
{
|
7702 |
|
|
return (dw_die_ref) htab_find_with_hash (decl_die_table, decl, DECL_UID (decl));
|
7703 |
|
|
}
|
7704 |
|
|
|
7705 |
|
|
/* Returns a hash value for X (which really is a var_loc_list). */
|
7706 |
|
|
|
7707 |
|
|
static hashval_t
|
7708 |
|
|
decl_loc_table_hash (const void *x)
|
7709 |
|
|
{
|
7710 |
|
|
return (hashval_t) ((const var_loc_list *) x)->decl_id;
|
7711 |
|
|
}
|
7712 |
|
|
|
7713 |
|
|
/* Return nonzero if decl_id of var_loc_list X is the same as
|
7714 |
|
|
UID of decl *Y. */
|
7715 |
|
|
|
7716 |
|
|
static int
|
7717 |
|
|
decl_loc_table_eq (const void *x, const void *y)
|
7718 |
|
|
{
|
7719 |
|
|
return (((const var_loc_list *) x)->decl_id == DECL_UID ((const_tree) y));
|
7720 |
|
|
}
|
7721 |
|
|
|
7722 |
|
|
/* Return the var_loc list associated with a given declaration. */
|
7723 |
|
|
|
7724 |
|
|
static inline var_loc_list *
|
7725 |
|
|
lookup_decl_loc (const_tree decl)
|
7726 |
|
|
{
|
7727 |
|
|
if (!decl_loc_table)
|
7728 |
|
|
return NULL;
|
7729 |
|
|
return (var_loc_list *)
|
7730 |
|
|
htab_find_with_hash (decl_loc_table, decl, DECL_UID (decl));
|
7731 |
|
|
}
|
7732 |
|
|
|
7733 |
|
|
/* Equate a DIE to a particular declaration. */
|
7734 |
|
|
|
7735 |
|
|
static void
|
7736 |
|
|
equate_decl_number_to_die (tree decl, dw_die_ref decl_die)
|
7737 |
|
|
{
|
7738 |
|
|
unsigned int decl_id = DECL_UID (decl);
|
7739 |
|
|
void **slot;
|
7740 |
|
|
|
7741 |
|
|
slot = htab_find_slot_with_hash (decl_die_table, decl, decl_id, INSERT);
|
7742 |
|
|
*slot = decl_die;
|
7743 |
|
|
decl_die->decl_id = decl_id;
|
7744 |
|
|
}
|
7745 |
|
|
|
7746 |
|
|
/* Add a variable location node to the linked list for DECL. */
|
7747 |
|
|
|
7748 |
|
|
static struct var_loc_node *
|
7749 |
|
|
add_var_loc_to_decl (tree decl, rtx loc_note)
|
7750 |
|
|
{
|
7751 |
|
|
unsigned int decl_id = DECL_UID (decl);
|
7752 |
|
|
var_loc_list *temp;
|
7753 |
|
|
void **slot;
|
7754 |
|
|
struct var_loc_node *loc = NULL;
|
7755 |
|
|
|
7756 |
|
|
slot = htab_find_slot_with_hash (decl_loc_table, decl, decl_id, INSERT);
|
7757 |
|
|
if (*slot == NULL)
|
7758 |
|
|
{
|
7759 |
|
|
temp = GGC_CNEW (var_loc_list);
|
7760 |
|
|
temp->decl_id = decl_id;
|
7761 |
|
|
*slot = temp;
|
7762 |
|
|
}
|
7763 |
|
|
else
|
7764 |
|
|
temp = (var_loc_list *) *slot;
|
7765 |
|
|
|
7766 |
|
|
if (temp->last)
|
7767 |
|
|
{
|
7768 |
|
|
/* If the current location is the same as the end of the list,
|
7769 |
|
|
and either both or neither of the locations is uninitialized,
|
7770 |
|
|
we have nothing to do. */
|
7771 |
|
|
if ((!rtx_equal_p (NOTE_VAR_LOCATION_LOC (temp->last->var_loc_note),
|
7772 |
|
|
NOTE_VAR_LOCATION_LOC (loc_note)))
|
7773 |
|
|
|| ((NOTE_VAR_LOCATION_STATUS (temp->last->var_loc_note)
|
7774 |
|
|
!= NOTE_VAR_LOCATION_STATUS (loc_note))
|
7775 |
|
|
&& ((NOTE_VAR_LOCATION_STATUS (temp->last->var_loc_note)
|
7776 |
|
|
== VAR_INIT_STATUS_UNINITIALIZED)
|
7777 |
|
|
|| (NOTE_VAR_LOCATION_STATUS (loc_note)
|
7778 |
|
|
== VAR_INIT_STATUS_UNINITIALIZED))))
|
7779 |
|
|
{
|
7780 |
|
|
/* Add LOC to the end of list and update LAST. */
|
7781 |
|
|
loc = GGC_CNEW (struct var_loc_node);
|
7782 |
|
|
temp->last->next = loc;
|
7783 |
|
|
temp->last = loc;
|
7784 |
|
|
}
|
7785 |
|
|
}
|
7786 |
|
|
else
|
7787 |
|
|
{
|
7788 |
|
|
loc = GGC_CNEW (struct var_loc_node);
|
7789 |
|
|
temp->first = loc;
|
7790 |
|
|
temp->last = loc;
|
7791 |
|
|
}
|
7792 |
|
|
return loc;
|
7793 |
|
|
}
|
7794 |
|
|
|
7795 |
|
|
/* Keep track of the number of spaces used to indent the
|
7796 |
|
|
output of the debugging routines that print the structure of
|
7797 |
|
|
the DIE internal representation. */
|
7798 |
|
|
static int print_indent;
|
7799 |
|
|
|
7800 |
|
|
/* Indent the line the number of spaces given by print_indent. */
|
7801 |
|
|
|
7802 |
|
|
static inline void
|
7803 |
|
|
print_spaces (FILE *outfile)
|
7804 |
|
|
{
|
7805 |
|
|
fprintf (outfile, "%*s", print_indent, "");
|
7806 |
|
|
}
|
7807 |
|
|
|
7808 |
|
|
/* Print a type signature in hex. */
|
7809 |
|
|
|
7810 |
|
|
static inline void
|
7811 |
|
|
print_signature (FILE *outfile, char *sig)
|
7812 |
|
|
{
|
7813 |
|
|
int i;
|
7814 |
|
|
|
7815 |
|
|
for (i = 0; i < DWARF_TYPE_SIGNATURE_SIZE; i++)
|
7816 |
|
|
fprintf (outfile, "%02x", sig[i] & 0xff);
|
7817 |
|
|
}
|
7818 |
|
|
|
7819 |
|
|
/* Print the information associated with a given DIE, and its children.
|
7820 |
|
|
This routine is a debugging aid only. */
|
7821 |
|
|
|
7822 |
|
|
static void
|
7823 |
|
|
print_die (dw_die_ref die, FILE *outfile)
|
7824 |
|
|
{
|
7825 |
|
|
dw_attr_ref a;
|
7826 |
|
|
dw_die_ref c;
|
7827 |
|
|
unsigned ix;
|
7828 |
|
|
|
7829 |
|
|
print_spaces (outfile);
|
7830 |
|
|
fprintf (outfile, "DIE %4ld: %s\n",
|
7831 |
|
|
die->die_offset, dwarf_tag_name (die->die_tag));
|
7832 |
|
|
print_spaces (outfile);
|
7833 |
|
|
fprintf (outfile, " abbrev id: %lu", die->die_abbrev);
|
7834 |
|
|
fprintf (outfile, " offset: %ld\n", die->die_offset);
|
7835 |
|
|
if (dwarf_version >= 4 && die->die_id.die_type_node)
|
7836 |
|
|
{
|
7837 |
|
|
print_spaces (outfile);
|
7838 |
|
|
fprintf (outfile, " signature: ");
|
7839 |
|
|
print_signature (outfile, die->die_id.die_type_node->signature);
|
7840 |
|
|
fprintf (outfile, "\n");
|
7841 |
|
|
}
|
7842 |
|
|
|
7843 |
|
|
for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
|
7844 |
|
|
{
|
7845 |
|
|
print_spaces (outfile);
|
7846 |
|
|
fprintf (outfile, " %s: ", dwarf_attr_name (a->dw_attr));
|
7847 |
|
|
|
7848 |
|
|
switch (AT_class (a))
|
7849 |
|
|
{
|
7850 |
|
|
case dw_val_class_addr:
|
7851 |
|
|
fprintf (outfile, "address");
|
7852 |
|
|
break;
|
7853 |
|
|
case dw_val_class_offset:
|
7854 |
|
|
fprintf (outfile, "offset");
|
7855 |
|
|
break;
|
7856 |
|
|
case dw_val_class_loc:
|
7857 |
|
|
fprintf (outfile, "location descriptor");
|
7858 |
|
|
break;
|
7859 |
|
|
case dw_val_class_loc_list:
|
7860 |
|
|
fprintf (outfile, "location list -> label:%s",
|
7861 |
|
|
AT_loc_list (a)->ll_symbol);
|
7862 |
|
|
break;
|
7863 |
|
|
case dw_val_class_range_list:
|
7864 |
|
|
fprintf (outfile, "range list");
|
7865 |
|
|
break;
|
7866 |
|
|
case dw_val_class_const:
|
7867 |
|
|
fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, AT_int (a));
|
7868 |
|
|
break;
|
7869 |
|
|
case dw_val_class_unsigned_const:
|
7870 |
|
|
fprintf (outfile, HOST_WIDE_INT_PRINT_UNSIGNED, AT_unsigned (a));
|
7871 |
|
|
break;
|
7872 |
|
|
case dw_val_class_const_double:
|
7873 |
|
|
fprintf (outfile, "constant ("HOST_WIDE_INT_PRINT_DEC","\
|
7874 |
|
|
HOST_WIDE_INT_PRINT_UNSIGNED")",
|
7875 |
|
|
a->dw_attr_val.v.val_double.high,
|
7876 |
|
|
a->dw_attr_val.v.val_double.low);
|
7877 |
|
|
break;
|
7878 |
|
|
case dw_val_class_vec:
|
7879 |
|
|
fprintf (outfile, "floating-point or vector constant");
|
7880 |
|
|
break;
|
7881 |
|
|
case dw_val_class_flag:
|
7882 |
|
|
fprintf (outfile, "%u", AT_flag (a));
|
7883 |
|
|
break;
|
7884 |
|
|
case dw_val_class_die_ref:
|
7885 |
|
|
if (AT_ref (a) != NULL)
|
7886 |
|
|
{
|
7887 |
|
|
if (dwarf_version >= 4 && AT_ref (a)->die_id.die_type_node)
|
7888 |
|
|
{
|
7889 |
|
|
fprintf (outfile, "die -> signature: ");
|
7890 |
|
|
print_signature (outfile,
|
7891 |
|
|
AT_ref (a)->die_id.die_type_node->signature);
|
7892 |
|
|
}
|
7893 |
|
|
else if (dwarf_version < 4 && AT_ref (a)->die_id.die_symbol)
|
7894 |
|
|
fprintf (outfile, "die -> label: %s",
|
7895 |
|
|
AT_ref (a)->die_id.die_symbol);
|
7896 |
|
|
else
|
7897 |
|
|
fprintf (outfile, "die -> %ld", AT_ref (a)->die_offset);
|
7898 |
|
|
}
|
7899 |
|
|
else
|
7900 |
|
|
fprintf (outfile, "die -> <null>");
|
7901 |
|
|
break;
|
7902 |
|
|
case dw_val_class_lbl_id:
|
7903 |
|
|
case dw_val_class_lineptr:
|
7904 |
|
|
case dw_val_class_macptr:
|
7905 |
|
|
fprintf (outfile, "label: %s", AT_lbl (a));
|
7906 |
|
|
break;
|
7907 |
|
|
case dw_val_class_str:
|
7908 |
|
|
if (AT_string (a) != NULL)
|
7909 |
|
|
fprintf (outfile, "\"%s\"", AT_string (a));
|
7910 |
|
|
else
|
7911 |
|
|
fprintf (outfile, "<null>");
|
7912 |
|
|
break;
|
7913 |
|
|
case dw_val_class_file:
|
7914 |
|
|
fprintf (outfile, "\"%s\" (%d)", AT_file (a)->filename,
|
7915 |
|
|
AT_file (a)->emitted_number);
|
7916 |
|
|
break;
|
7917 |
|
|
case dw_val_class_data8:
|
7918 |
|
|
{
|
7919 |
|
|
int i;
|
7920 |
|
|
|
7921 |
|
|
for (i = 0; i < 8; i++)
|
7922 |
|
|
fprintf (outfile, "%02x", a->dw_attr_val.v.val_data8[i]);
|
7923 |
|
|
break;
|
7924 |
|
|
}
|
7925 |
|
|
default:
|
7926 |
|
|
break;
|
7927 |
|
|
}
|
7928 |
|
|
|
7929 |
|
|
fprintf (outfile, "\n");
|
7930 |
|
|
}
|
7931 |
|
|
|
7932 |
|
|
if (die->die_child != NULL)
|
7933 |
|
|
{
|
7934 |
|
|
print_indent += 4;
|
7935 |
|
|
FOR_EACH_CHILD (die, c, print_die (c, outfile));
|
7936 |
|
|
print_indent -= 4;
|
7937 |
|
|
}
|
7938 |
|
|
if (print_indent == 0)
|
7939 |
|
|
fprintf (outfile, "\n");
|
7940 |
|
|
}
|
7941 |
|
|
|
7942 |
|
|
/* Print the contents of the source code line number correspondence table.
|
7943 |
|
|
This routine is a debugging aid only. */
|
7944 |
|
|
|
7945 |
|
|
static void
|
7946 |
|
|
print_dwarf_line_table (FILE *outfile)
|
7947 |
|
|
{
|
7948 |
|
|
unsigned i;
|
7949 |
|
|
dw_line_info_ref line_info;
|
7950 |
|
|
|
7951 |
|
|
fprintf (outfile, "\n\nDWARF source line information\n");
|
7952 |
|
|
for (i = 1; i < line_info_table_in_use; i++)
|
7953 |
|
|
{
|
7954 |
|
|
line_info = &line_info_table[i];
|
7955 |
|
|
fprintf (outfile, "%5d: %4ld %6ld\n", i,
|
7956 |
|
|
line_info->dw_file_num,
|
7957 |
|
|
line_info->dw_line_num);
|
7958 |
|
|
}
|
7959 |
|
|
|
7960 |
|
|
fprintf (outfile, "\n\n");
|
7961 |
|
|
}
|
7962 |
|
|
|
7963 |
|
|
/* Print the information collected for a given DIE. */
|
7964 |
|
|
|
7965 |
|
|
void
|
7966 |
|
|
debug_dwarf_die (dw_die_ref die)
|
7967 |
|
|
{
|
7968 |
|
|
print_die (die, stderr);
|
7969 |
|
|
}
|
7970 |
|
|
|
7971 |
|
|
/* Print all DWARF information collected for the compilation unit.
|
7972 |
|
|
This routine is a debugging aid only. */
|
7973 |
|
|
|
7974 |
|
|
void
|
7975 |
|
|
debug_dwarf (void)
|
7976 |
|
|
{
|
7977 |
|
|
print_indent = 0;
|
7978 |
|
|
print_die (comp_unit_die, stderr);
|
7979 |
|
|
if (! DWARF2_ASM_LINE_DEBUG_INFO)
|
7980 |
|
|
print_dwarf_line_table (stderr);
|
7981 |
|
|
}
|
7982 |
|
|
|
7983 |
|
|
/* Start a new compilation unit DIE for an include file. OLD_UNIT is the CU
|
7984 |
|
|
for the enclosing include file, if any. BINCL_DIE is the DW_TAG_GNU_BINCL
|
7985 |
|
|
DIE that marks the start of the DIEs for this include file. */
|
7986 |
|
|
|
7987 |
|
|
static dw_die_ref
|
7988 |
|
|
push_new_compile_unit (dw_die_ref old_unit, dw_die_ref bincl_die)
|
7989 |
|
|
{
|
7990 |
|
|
const char *filename = get_AT_string (bincl_die, DW_AT_name);
|
7991 |
|
|
dw_die_ref new_unit = gen_compile_unit_die (filename);
|
7992 |
|
|
|
7993 |
|
|
new_unit->die_sib = old_unit;
|
7994 |
|
|
return new_unit;
|
7995 |
|
|
}
|
7996 |
|
|
|
7997 |
|
|
/* Close an include-file CU and reopen the enclosing one. */
|
7998 |
|
|
|
7999 |
|
|
static dw_die_ref
|
8000 |
|
|
pop_compile_unit (dw_die_ref old_unit)
|
8001 |
|
|
{
|
8002 |
|
|
dw_die_ref new_unit = old_unit->die_sib;
|
8003 |
|
|
|
8004 |
|
|
old_unit->die_sib = NULL;
|
8005 |
|
|
return new_unit;
|
8006 |
|
|
}
|
8007 |
|
|
|
8008 |
|
|
#define CHECKSUM(FOO) md5_process_bytes (&(FOO), sizeof (FOO), ctx)
|
8009 |
|
|
#define CHECKSUM_STRING(FOO) md5_process_bytes ((FOO), strlen (FOO), ctx)
|
8010 |
|
|
|
8011 |
|
|
/* Calculate the checksum of a location expression. */
|
8012 |
|
|
|
8013 |
|
|
static inline void
|
8014 |
|
|
loc_checksum (dw_loc_descr_ref loc, struct md5_ctx *ctx)
|
8015 |
|
|
{
|
8016 |
|
|
int tem;
|
8017 |
|
|
|
8018 |
|
|
tem = (loc->dtprel << 8) | ((unsigned int) loc->dw_loc_opc);
|
8019 |
|
|
CHECKSUM (tem);
|
8020 |
|
|
CHECKSUM (loc->dw_loc_oprnd1);
|
8021 |
|
|
CHECKSUM (loc->dw_loc_oprnd2);
|
8022 |
|
|
}
|
8023 |
|
|
|
8024 |
|
|
/* Calculate the checksum of an attribute. */
|
8025 |
|
|
|
8026 |
|
|
static void
|
8027 |
|
|
attr_checksum (dw_attr_ref at, struct md5_ctx *ctx, int *mark)
|
8028 |
|
|
{
|
8029 |
|
|
dw_loc_descr_ref loc;
|
8030 |
|
|
rtx r;
|
8031 |
|
|
|
8032 |
|
|
CHECKSUM (at->dw_attr);
|
8033 |
|
|
|
8034 |
|
|
/* We don't care that this was compiled with a different compiler
|
8035 |
|
|
snapshot; if the output is the same, that's what matters. */
|
8036 |
|
|
if (at->dw_attr == DW_AT_producer)
|
8037 |
|
|
return;
|
8038 |
|
|
|
8039 |
|
|
switch (AT_class (at))
|
8040 |
|
|
{
|
8041 |
|
|
case dw_val_class_const:
|
8042 |
|
|
CHECKSUM (at->dw_attr_val.v.val_int);
|
8043 |
|
|
break;
|
8044 |
|
|
case dw_val_class_unsigned_const:
|
8045 |
|
|
CHECKSUM (at->dw_attr_val.v.val_unsigned);
|
8046 |
|
|
break;
|
8047 |
|
|
case dw_val_class_const_double:
|
8048 |
|
|
CHECKSUM (at->dw_attr_val.v.val_double);
|
8049 |
|
|
break;
|
8050 |
|
|
case dw_val_class_vec:
|
8051 |
|
|
CHECKSUM (at->dw_attr_val.v.val_vec);
|
8052 |
|
|
break;
|
8053 |
|
|
case dw_val_class_flag:
|
8054 |
|
|
CHECKSUM (at->dw_attr_val.v.val_flag);
|
8055 |
|
|
break;
|
8056 |
|
|
case dw_val_class_str:
|
8057 |
|
|
CHECKSUM_STRING (AT_string (at));
|
8058 |
|
|
break;
|
8059 |
|
|
|
8060 |
|
|
case dw_val_class_addr:
|
8061 |
|
|
r = AT_addr (at);
|
8062 |
|
|
gcc_assert (GET_CODE (r) == SYMBOL_REF);
|
8063 |
|
|
CHECKSUM_STRING (XSTR (r, 0));
|
8064 |
|
|
break;
|
8065 |
|
|
|
8066 |
|
|
case dw_val_class_offset:
|
8067 |
|
|
CHECKSUM (at->dw_attr_val.v.val_offset);
|
8068 |
|
|
break;
|
8069 |
|
|
|
8070 |
|
|
case dw_val_class_loc:
|
8071 |
|
|
for (loc = AT_loc (at); loc; loc = loc->dw_loc_next)
|
8072 |
|
|
loc_checksum (loc, ctx);
|
8073 |
|
|
break;
|
8074 |
|
|
|
8075 |
|
|
case dw_val_class_die_ref:
|
8076 |
|
|
die_checksum (AT_ref (at), ctx, mark);
|
8077 |
|
|
break;
|
8078 |
|
|
|
8079 |
|
|
case dw_val_class_fde_ref:
|
8080 |
|
|
case dw_val_class_lbl_id:
|
8081 |
|
|
case dw_val_class_lineptr:
|
8082 |
|
|
case dw_val_class_macptr:
|
8083 |
|
|
break;
|
8084 |
|
|
|
8085 |
|
|
case dw_val_class_file:
|
8086 |
|
|
CHECKSUM_STRING (AT_file (at)->filename);
|
8087 |
|
|
break;
|
8088 |
|
|
|
8089 |
|
|
case dw_val_class_data8:
|
8090 |
|
|
CHECKSUM (at->dw_attr_val.v.val_data8);
|
8091 |
|
|
break;
|
8092 |
|
|
|
8093 |
|
|
default:
|
8094 |
|
|
break;
|
8095 |
|
|
}
|
8096 |
|
|
}
|
8097 |
|
|
|
8098 |
|
|
/* Calculate the checksum of a DIE. */
|
8099 |
|
|
|
8100 |
|
|
static void
|
8101 |
|
|
die_checksum (dw_die_ref die, struct md5_ctx *ctx, int *mark)
|
8102 |
|
|
{
|
8103 |
|
|
dw_die_ref c;
|
8104 |
|
|
dw_attr_ref a;
|
8105 |
|
|
unsigned ix;
|
8106 |
|
|
|
8107 |
|
|
/* To avoid infinite recursion. */
|
8108 |
|
|
if (die->die_mark)
|
8109 |
|
|
{
|
8110 |
|
|
CHECKSUM (die->die_mark);
|
8111 |
|
|
return;
|
8112 |
|
|
}
|
8113 |
|
|
die->die_mark = ++(*mark);
|
8114 |
|
|
|
8115 |
|
|
CHECKSUM (die->die_tag);
|
8116 |
|
|
|
8117 |
|
|
for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
|
8118 |
|
|
attr_checksum (a, ctx, mark);
|
8119 |
|
|
|
8120 |
|
|
FOR_EACH_CHILD (die, c, die_checksum (c, ctx, mark));
|
8121 |
|
|
}
|
8122 |
|
|
|
8123 |
|
|
#undef CHECKSUM
|
8124 |
|
|
#undef CHECKSUM_STRING
|
8125 |
|
|
|
8126 |
|
|
/* For DWARF-4 types, include the trailing NULL when checksumming strings. */
|
8127 |
|
|
#define CHECKSUM(FOO) md5_process_bytes (&(FOO), sizeof (FOO), ctx)
|
8128 |
|
|
#define CHECKSUM_STRING(FOO) md5_process_bytes ((FOO), strlen (FOO) + 1, ctx)
|
8129 |
|
|
#define CHECKSUM_SLEB128(FOO) checksum_sleb128 ((FOO), ctx)
|
8130 |
|
|
#define CHECKSUM_ULEB128(FOO) checksum_uleb128 ((FOO), ctx)
|
8131 |
|
|
#define CHECKSUM_ATTR(FOO) \
|
8132 |
|
|
if (FOO) attr_checksum_ordered (die->die_tag, (FOO), ctx, mark)
|
8133 |
|
|
|
8134 |
|
|
/* Calculate the checksum of a number in signed LEB128 format. */
|
8135 |
|
|
|
8136 |
|
|
static void
|
8137 |
|
|
checksum_sleb128 (HOST_WIDE_INT value, struct md5_ctx *ctx)
|
8138 |
|
|
{
|
8139 |
|
|
unsigned char byte;
|
8140 |
|
|
bool more;
|
8141 |
|
|
|
8142 |
|
|
while (1)
|
8143 |
|
|
{
|
8144 |
|
|
byte = (value & 0x7f);
|
8145 |
|
|
value >>= 7;
|
8146 |
|
|
more = !((value == 0 && (byte & 0x40) == 0)
|
8147 |
|
|
|| (value == -1 && (byte & 0x40) != 0));
|
8148 |
|
|
if (more)
|
8149 |
|
|
byte |= 0x80;
|
8150 |
|
|
CHECKSUM (byte);
|
8151 |
|
|
if (!more)
|
8152 |
|
|
break;
|
8153 |
|
|
}
|
8154 |
|
|
}
|
8155 |
|
|
|
8156 |
|
|
/* Calculate the checksum of a number in unsigned LEB128 format. */
|
8157 |
|
|
|
8158 |
|
|
static void
|
8159 |
|
|
checksum_uleb128 (unsigned HOST_WIDE_INT value, struct md5_ctx *ctx)
|
8160 |
|
|
{
|
8161 |
|
|
while (1)
|
8162 |
|
|
{
|
8163 |
|
|
unsigned char byte = (value & 0x7f);
|
8164 |
|
|
value >>= 7;
|
8165 |
|
|
if (value != 0)
|
8166 |
|
|
/* More bytes to follow. */
|
8167 |
|
|
byte |= 0x80;
|
8168 |
|
|
CHECKSUM (byte);
|
8169 |
|
|
if (value == 0)
|
8170 |
|
|
break;
|
8171 |
|
|
}
|
8172 |
|
|
}
|
8173 |
|
|
|
8174 |
|
|
/* Checksum the context of the DIE. This adds the names of any
|
8175 |
|
|
surrounding namespaces or structures to the checksum. */
|
8176 |
|
|
|
8177 |
|
|
static void
|
8178 |
|
|
checksum_die_context (dw_die_ref die, struct md5_ctx *ctx)
|
8179 |
|
|
{
|
8180 |
|
|
const char *name;
|
8181 |
|
|
dw_die_ref spec;
|
8182 |
|
|
int tag = die->die_tag;
|
8183 |
|
|
|
8184 |
|
|
if (tag != DW_TAG_namespace
|
8185 |
|
|
&& tag != DW_TAG_structure_type
|
8186 |
|
|
&& tag != DW_TAG_class_type)
|
8187 |
|
|
return;
|
8188 |
|
|
|
8189 |
|
|
name = get_AT_string (die, DW_AT_name);
|
8190 |
|
|
|
8191 |
|
|
spec = get_AT_ref (die, DW_AT_specification);
|
8192 |
|
|
if (spec != NULL)
|
8193 |
|
|
die = spec;
|
8194 |
|
|
|
8195 |
|
|
if (die->die_parent != NULL)
|
8196 |
|
|
checksum_die_context (die->die_parent, ctx);
|
8197 |
|
|
|
8198 |
|
|
CHECKSUM_ULEB128 ('C');
|
8199 |
|
|
CHECKSUM_ULEB128 (tag);
|
8200 |
|
|
if (name != NULL)
|
8201 |
|
|
CHECKSUM_STRING (name);
|
8202 |
|
|
}
|
8203 |
|
|
|
8204 |
|
|
/* Calculate the checksum of a location expression. */
|
8205 |
|
|
|
8206 |
|
|
static inline void
|
8207 |
|
|
loc_checksum_ordered (dw_loc_descr_ref loc, struct md5_ctx *ctx)
|
8208 |
|
|
{
|
8209 |
|
|
/* Special case for lone DW_OP_plus_uconst: checksum as if the location
|
8210 |
|
|
were emitted as a DW_FORM_sdata instead of a location expression. */
|
8211 |
|
|
if (loc->dw_loc_opc == DW_OP_plus_uconst && loc->dw_loc_next == NULL)
|
8212 |
|
|
{
|
8213 |
|
|
CHECKSUM_ULEB128 (DW_FORM_sdata);
|
8214 |
|
|
CHECKSUM_SLEB128 ((HOST_WIDE_INT) loc->dw_loc_oprnd1.v.val_unsigned);
|
8215 |
|
|
return;
|
8216 |
|
|
}
|
8217 |
|
|
|
8218 |
|
|
/* Otherwise, just checksum the raw location expression. */
|
8219 |
|
|
while (loc != NULL)
|
8220 |
|
|
{
|
8221 |
|
|
CHECKSUM_ULEB128 (loc->dw_loc_opc);
|
8222 |
|
|
CHECKSUM (loc->dw_loc_oprnd1);
|
8223 |
|
|
CHECKSUM (loc->dw_loc_oprnd2);
|
8224 |
|
|
loc = loc->dw_loc_next;
|
8225 |
|
|
}
|
8226 |
|
|
}
|
8227 |
|
|
|
8228 |
|
|
/* Calculate the checksum of an attribute. */
|
8229 |
|
|
|
8230 |
|
|
static void
|
8231 |
|
|
attr_checksum_ordered (enum dwarf_tag tag, dw_attr_ref at,
|
8232 |
|
|
struct md5_ctx *ctx, int *mark)
|
8233 |
|
|
{
|
8234 |
|
|
dw_loc_descr_ref loc;
|
8235 |
|
|
rtx r;
|
8236 |
|
|
|
8237 |
|
|
if (AT_class (at) == dw_val_class_die_ref)
|
8238 |
|
|
{
|
8239 |
|
|
dw_die_ref target_die = AT_ref (at);
|
8240 |
|
|
|
8241 |
|
|
/* For pointer and reference types, we checksum only the (qualified)
|
8242 |
|
|
name of the target type (if there is a name). For friend entries,
|
8243 |
|
|
we checksum only the (qualified) name of the target type or function.
|
8244 |
|
|
This allows the checksum to remain the same whether the target type
|
8245 |
|
|
is complete or not. */
|
8246 |
|
|
if ((at->dw_attr == DW_AT_type
|
8247 |
|
|
&& (tag == DW_TAG_pointer_type
|
8248 |
|
|
|| tag == DW_TAG_reference_type
|
8249 |
|
|
|| tag == DW_TAG_ptr_to_member_type))
|
8250 |
|
|
|| (at->dw_attr == DW_AT_friend
|
8251 |
|
|
&& tag == DW_TAG_friend))
|
8252 |
|
|
{
|
8253 |
|
|
dw_attr_ref name_attr = get_AT (target_die, DW_AT_name);
|
8254 |
|
|
|
8255 |
|
|
if (name_attr != NULL)
|
8256 |
|
|
{
|
8257 |
|
|
dw_die_ref decl = get_AT_ref (target_die, DW_AT_specification);
|
8258 |
|
|
|
8259 |
|
|
if (decl == NULL)
|
8260 |
|
|
decl = target_die;
|
8261 |
|
|
CHECKSUM_ULEB128 ('N');
|
8262 |
|
|
CHECKSUM_ULEB128 (at->dw_attr);
|
8263 |
|
|
if (decl->die_parent != NULL)
|
8264 |
|
|
checksum_die_context (decl->die_parent, ctx);
|
8265 |
|
|
CHECKSUM_ULEB128 ('E');
|
8266 |
|
|
CHECKSUM_STRING (AT_string (name_attr));
|
8267 |
|
|
return;
|
8268 |
|
|
}
|
8269 |
|
|
}
|
8270 |
|
|
|
8271 |
|
|
/* For all other references to another DIE, we check to see if the
|
8272 |
|
|
target DIE has already been visited. If it has, we emit a
|
8273 |
|
|
backward reference; if not, we descend recursively. */
|
8274 |
|
|
if (target_die->die_mark > 0)
|
8275 |
|
|
{
|
8276 |
|
|
CHECKSUM_ULEB128 ('R');
|
8277 |
|
|
CHECKSUM_ULEB128 (at->dw_attr);
|
8278 |
|
|
CHECKSUM_ULEB128 (target_die->die_mark);
|
8279 |
|
|
}
|
8280 |
|
|
else
|
8281 |
|
|
{
|
8282 |
|
|
dw_die_ref decl = get_AT_ref (target_die, DW_AT_specification);
|
8283 |
|
|
|
8284 |
|
|
if (decl == NULL)
|
8285 |
|
|
decl = target_die;
|
8286 |
|
|
target_die->die_mark = ++(*mark);
|
8287 |
|
|
CHECKSUM_ULEB128 ('T');
|
8288 |
|
|
CHECKSUM_ULEB128 (at->dw_attr);
|
8289 |
|
|
if (decl->die_parent != NULL)
|
8290 |
|
|
checksum_die_context (decl->die_parent, ctx);
|
8291 |
|
|
die_checksum_ordered (target_die, ctx, mark);
|
8292 |
|
|
}
|
8293 |
|
|
return;
|
8294 |
|
|
}
|
8295 |
|
|
|
8296 |
|
|
CHECKSUM_ULEB128 ('A');
|
8297 |
|
|
CHECKSUM_ULEB128 (at->dw_attr);
|
8298 |
|
|
|
8299 |
|
|
switch (AT_class (at))
|
8300 |
|
|
{
|
8301 |
|
|
case dw_val_class_const:
|
8302 |
|
|
CHECKSUM_ULEB128 (DW_FORM_sdata);
|
8303 |
|
|
CHECKSUM_SLEB128 (at->dw_attr_val.v.val_int);
|
8304 |
|
|
break;
|
8305 |
|
|
|
8306 |
|
|
case dw_val_class_unsigned_const:
|
8307 |
|
|
CHECKSUM_ULEB128 (DW_FORM_sdata);
|
8308 |
|
|
CHECKSUM_SLEB128 ((int) at->dw_attr_val.v.val_unsigned);
|
8309 |
|
|
break;
|
8310 |
|
|
|
8311 |
|
|
case dw_val_class_const_double:
|
8312 |
|
|
CHECKSUM_ULEB128 (DW_FORM_block);
|
8313 |
|
|
CHECKSUM_ULEB128 (sizeof (at->dw_attr_val.v.val_double));
|
8314 |
|
|
CHECKSUM (at->dw_attr_val.v.val_double);
|
8315 |
|
|
break;
|
8316 |
|
|
|
8317 |
|
|
case dw_val_class_vec:
|
8318 |
|
|
CHECKSUM_ULEB128 (DW_FORM_block);
|
8319 |
|
|
CHECKSUM_ULEB128 (sizeof (at->dw_attr_val.v.val_vec));
|
8320 |
|
|
CHECKSUM (at->dw_attr_val.v.val_vec);
|
8321 |
|
|
break;
|
8322 |
|
|
|
8323 |
|
|
case dw_val_class_flag:
|
8324 |
|
|
CHECKSUM_ULEB128 (DW_FORM_flag);
|
8325 |
|
|
CHECKSUM_ULEB128 (at->dw_attr_val.v.val_flag ? 1 : 0);
|
8326 |
|
|
break;
|
8327 |
|
|
|
8328 |
|
|
case dw_val_class_str:
|
8329 |
|
|
CHECKSUM_ULEB128 (DW_FORM_string);
|
8330 |
|
|
CHECKSUM_STRING (AT_string (at));
|
8331 |
|
|
break;
|
8332 |
|
|
|
8333 |
|
|
case dw_val_class_addr:
|
8334 |
|
|
r = AT_addr (at);
|
8335 |
|
|
gcc_assert (GET_CODE (r) == SYMBOL_REF);
|
8336 |
|
|
CHECKSUM_ULEB128 (DW_FORM_string);
|
8337 |
|
|
CHECKSUM_STRING (XSTR (r, 0));
|
8338 |
|
|
break;
|
8339 |
|
|
|
8340 |
|
|
case dw_val_class_offset:
|
8341 |
|
|
CHECKSUM_ULEB128 (DW_FORM_sdata);
|
8342 |
|
|
CHECKSUM_ULEB128 (at->dw_attr_val.v.val_offset);
|
8343 |
|
|
break;
|
8344 |
|
|
|
8345 |
|
|
case dw_val_class_loc:
|
8346 |
|
|
for (loc = AT_loc (at); loc; loc = loc->dw_loc_next)
|
8347 |
|
|
loc_checksum_ordered (loc, ctx);
|
8348 |
|
|
break;
|
8349 |
|
|
|
8350 |
|
|
case dw_val_class_fde_ref:
|
8351 |
|
|
case dw_val_class_lbl_id:
|
8352 |
|
|
case dw_val_class_lineptr:
|
8353 |
|
|
case dw_val_class_macptr:
|
8354 |
|
|
break;
|
8355 |
|
|
|
8356 |
|
|
case dw_val_class_file:
|
8357 |
|
|
CHECKSUM_ULEB128 (DW_FORM_string);
|
8358 |
|
|
CHECKSUM_STRING (AT_file (at)->filename);
|
8359 |
|
|
break;
|
8360 |
|
|
|
8361 |
|
|
case dw_val_class_data8:
|
8362 |
|
|
CHECKSUM (at->dw_attr_val.v.val_data8);
|
8363 |
|
|
break;
|
8364 |
|
|
|
8365 |
|
|
default:
|
8366 |
|
|
break;
|
8367 |
|
|
}
|
8368 |
|
|
}
|
8369 |
|
|
|
8370 |
|
|
struct checksum_attributes
|
8371 |
|
|
{
|
8372 |
|
|
dw_attr_ref at_name;
|
8373 |
|
|
dw_attr_ref at_type;
|
8374 |
|
|
dw_attr_ref at_friend;
|
8375 |
|
|
dw_attr_ref at_accessibility;
|
8376 |
|
|
dw_attr_ref at_address_class;
|
8377 |
|
|
dw_attr_ref at_allocated;
|
8378 |
|
|
dw_attr_ref at_artificial;
|
8379 |
|
|
dw_attr_ref at_associated;
|
8380 |
|
|
dw_attr_ref at_binary_scale;
|
8381 |
|
|
dw_attr_ref at_bit_offset;
|
8382 |
|
|
dw_attr_ref at_bit_size;
|
8383 |
|
|
dw_attr_ref at_bit_stride;
|
8384 |
|
|
dw_attr_ref at_byte_size;
|
8385 |
|
|
dw_attr_ref at_byte_stride;
|
8386 |
|
|
dw_attr_ref at_const_value;
|
8387 |
|
|
dw_attr_ref at_containing_type;
|
8388 |
|
|
dw_attr_ref at_count;
|
8389 |
|
|
dw_attr_ref at_data_location;
|
8390 |
|
|
dw_attr_ref at_data_member_location;
|
8391 |
|
|
dw_attr_ref at_decimal_scale;
|
8392 |
|
|
dw_attr_ref at_decimal_sign;
|
8393 |
|
|
dw_attr_ref at_default_value;
|
8394 |
|
|
dw_attr_ref at_digit_count;
|
8395 |
|
|
dw_attr_ref at_discr;
|
8396 |
|
|
dw_attr_ref at_discr_list;
|
8397 |
|
|
dw_attr_ref at_discr_value;
|
8398 |
|
|
dw_attr_ref at_encoding;
|
8399 |
|
|
dw_attr_ref at_endianity;
|
8400 |
|
|
dw_attr_ref at_explicit;
|
8401 |
|
|
dw_attr_ref at_is_optional;
|
8402 |
|
|
dw_attr_ref at_location;
|
8403 |
|
|
dw_attr_ref at_lower_bound;
|
8404 |
|
|
dw_attr_ref at_mutable;
|
8405 |
|
|
dw_attr_ref at_ordering;
|
8406 |
|
|
dw_attr_ref at_picture_string;
|
8407 |
|
|
dw_attr_ref at_prototyped;
|
8408 |
|
|
dw_attr_ref at_small;
|
8409 |
|
|
dw_attr_ref at_segment;
|
8410 |
|
|
dw_attr_ref at_string_length;
|
8411 |
|
|
dw_attr_ref at_threads_scaled;
|
8412 |
|
|
dw_attr_ref at_upper_bound;
|
8413 |
|
|
dw_attr_ref at_use_location;
|
8414 |
|
|
dw_attr_ref at_use_UTF8;
|
8415 |
|
|
dw_attr_ref at_variable_parameter;
|
8416 |
|
|
dw_attr_ref at_virtuality;
|
8417 |
|
|
dw_attr_ref at_visibility;
|
8418 |
|
|
dw_attr_ref at_vtable_elem_location;
|
8419 |
|
|
};
|
8420 |
|
|
|
8421 |
|
|
/* Collect the attributes that we will want to use for the checksum. */
|
8422 |
|
|
|
8423 |
|
|
static void
|
8424 |
|
|
collect_checksum_attributes (struct checksum_attributes *attrs, dw_die_ref die)
|
8425 |
|
|
{
|
8426 |
|
|
dw_attr_ref a;
|
8427 |
|
|
unsigned ix;
|
8428 |
|
|
|
8429 |
|
|
for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
|
8430 |
|
|
{
|
8431 |
|
|
switch (a->dw_attr)
|
8432 |
|
|
{
|
8433 |
|
|
case DW_AT_name:
|
8434 |
|
|
attrs->at_name = a;
|
8435 |
|
|
break;
|
8436 |
|
|
case DW_AT_type:
|
8437 |
|
|
attrs->at_type = a;
|
8438 |
|
|
break;
|
8439 |
|
|
case DW_AT_friend:
|
8440 |
|
|
attrs->at_friend = a;
|
8441 |
|
|
break;
|
8442 |
|
|
case DW_AT_accessibility:
|
8443 |
|
|
attrs->at_accessibility = a;
|
8444 |
|
|
break;
|
8445 |
|
|
case DW_AT_address_class:
|
8446 |
|
|
attrs->at_address_class = a;
|
8447 |
|
|
break;
|
8448 |
|
|
case DW_AT_allocated:
|
8449 |
|
|
attrs->at_allocated = a;
|
8450 |
|
|
break;
|
8451 |
|
|
case DW_AT_artificial:
|
8452 |
|
|
attrs->at_artificial = a;
|
8453 |
|
|
break;
|
8454 |
|
|
case DW_AT_associated:
|
8455 |
|
|
attrs->at_associated = a;
|
8456 |
|
|
break;
|
8457 |
|
|
case DW_AT_binary_scale:
|
8458 |
|
|
attrs->at_binary_scale = a;
|
8459 |
|
|
break;
|
8460 |
|
|
case DW_AT_bit_offset:
|
8461 |
|
|
attrs->at_bit_offset = a;
|
8462 |
|
|
break;
|
8463 |
|
|
case DW_AT_bit_size:
|
8464 |
|
|
attrs->at_bit_size = a;
|
8465 |
|
|
break;
|
8466 |
|
|
case DW_AT_bit_stride:
|
8467 |
|
|
attrs->at_bit_stride = a;
|
8468 |
|
|
break;
|
8469 |
|
|
case DW_AT_byte_size:
|
8470 |
|
|
attrs->at_byte_size = a;
|
8471 |
|
|
break;
|
8472 |
|
|
case DW_AT_byte_stride:
|
8473 |
|
|
attrs->at_byte_stride = a;
|
8474 |
|
|
break;
|
8475 |
|
|
case DW_AT_const_value:
|
8476 |
|
|
attrs->at_const_value = a;
|
8477 |
|
|
break;
|
8478 |
|
|
case DW_AT_containing_type:
|
8479 |
|
|
attrs->at_containing_type = a;
|
8480 |
|
|
break;
|
8481 |
|
|
case DW_AT_count:
|
8482 |
|
|
attrs->at_count = a;
|
8483 |
|
|
break;
|
8484 |
|
|
case DW_AT_data_location:
|
8485 |
|
|
attrs->at_data_location = a;
|
8486 |
|
|
break;
|
8487 |
|
|
case DW_AT_data_member_location:
|
8488 |
|
|
attrs->at_data_member_location = a;
|
8489 |
|
|
break;
|
8490 |
|
|
case DW_AT_decimal_scale:
|
8491 |
|
|
attrs->at_decimal_scale = a;
|
8492 |
|
|
break;
|
8493 |
|
|
case DW_AT_decimal_sign:
|
8494 |
|
|
attrs->at_decimal_sign = a;
|
8495 |
|
|
break;
|
8496 |
|
|
case DW_AT_default_value:
|
8497 |
|
|
attrs->at_default_value = a;
|
8498 |
|
|
break;
|
8499 |
|
|
case DW_AT_digit_count:
|
8500 |
|
|
attrs->at_digit_count = a;
|
8501 |
|
|
break;
|
8502 |
|
|
case DW_AT_discr:
|
8503 |
|
|
attrs->at_discr = a;
|
8504 |
|
|
break;
|
8505 |
|
|
case DW_AT_discr_list:
|
8506 |
|
|
attrs->at_discr_list = a;
|
8507 |
|
|
break;
|
8508 |
|
|
case DW_AT_discr_value:
|
8509 |
|
|
attrs->at_discr_value = a;
|
8510 |
|
|
break;
|
8511 |
|
|
case DW_AT_encoding:
|
8512 |
|
|
attrs->at_encoding = a;
|
8513 |
|
|
break;
|
8514 |
|
|
case DW_AT_endianity:
|
8515 |
|
|
attrs->at_endianity = a;
|
8516 |
|
|
break;
|
8517 |
|
|
case DW_AT_explicit:
|
8518 |
|
|
attrs->at_explicit = a;
|
8519 |
|
|
break;
|
8520 |
|
|
case DW_AT_is_optional:
|
8521 |
|
|
attrs->at_is_optional = a;
|
8522 |
|
|
break;
|
8523 |
|
|
case DW_AT_location:
|
8524 |
|
|
attrs->at_location = a;
|
8525 |
|
|
break;
|
8526 |
|
|
case DW_AT_lower_bound:
|
8527 |
|
|
attrs->at_lower_bound = a;
|
8528 |
|
|
break;
|
8529 |
|
|
case DW_AT_mutable:
|
8530 |
|
|
attrs->at_mutable = a;
|
8531 |
|
|
break;
|
8532 |
|
|
case DW_AT_ordering:
|
8533 |
|
|
attrs->at_ordering = a;
|
8534 |
|
|
break;
|
8535 |
|
|
case DW_AT_picture_string:
|
8536 |
|
|
attrs->at_picture_string = a;
|
8537 |
|
|
break;
|
8538 |
|
|
case DW_AT_prototyped:
|
8539 |
|
|
attrs->at_prototyped = a;
|
8540 |
|
|
break;
|
8541 |
|
|
case DW_AT_small:
|
8542 |
|
|
attrs->at_small = a;
|
8543 |
|
|
break;
|
8544 |
|
|
case DW_AT_segment:
|
8545 |
|
|
attrs->at_segment = a;
|
8546 |
|
|
break;
|
8547 |
|
|
case DW_AT_string_length:
|
8548 |
|
|
attrs->at_string_length = a;
|
8549 |
|
|
break;
|
8550 |
|
|
case DW_AT_threads_scaled:
|
8551 |
|
|
attrs->at_threads_scaled = a;
|
8552 |
|
|
break;
|
8553 |
|
|
case DW_AT_upper_bound:
|
8554 |
|
|
attrs->at_upper_bound = a;
|
8555 |
|
|
break;
|
8556 |
|
|
case DW_AT_use_location:
|
8557 |
|
|
attrs->at_use_location = a;
|
8558 |
|
|
break;
|
8559 |
|
|
case DW_AT_use_UTF8:
|
8560 |
|
|
attrs->at_use_UTF8 = a;
|
8561 |
|
|
break;
|
8562 |
|
|
case DW_AT_variable_parameter:
|
8563 |
|
|
attrs->at_variable_parameter = a;
|
8564 |
|
|
break;
|
8565 |
|
|
case DW_AT_virtuality:
|
8566 |
|
|
attrs->at_virtuality = a;
|
8567 |
|
|
break;
|
8568 |
|
|
case DW_AT_visibility:
|
8569 |
|
|
attrs->at_visibility = a;
|
8570 |
|
|
break;
|
8571 |
|
|
case DW_AT_vtable_elem_location:
|
8572 |
|
|
attrs->at_vtable_elem_location = a;
|
8573 |
|
|
break;
|
8574 |
|
|
default:
|
8575 |
|
|
break;
|
8576 |
|
|
}
|
8577 |
|
|
}
|
8578 |
|
|
}
|
8579 |
|
|
|
8580 |
|
|
/* Calculate the checksum of a DIE, using an ordered subset of attributes. */
|
8581 |
|
|
|
8582 |
|
|
static void
|
8583 |
|
|
die_checksum_ordered (dw_die_ref die, struct md5_ctx *ctx, int *mark)
|
8584 |
|
|
{
|
8585 |
|
|
dw_die_ref c;
|
8586 |
|
|
dw_die_ref decl;
|
8587 |
|
|
struct checksum_attributes attrs;
|
8588 |
|
|
|
8589 |
|
|
CHECKSUM_ULEB128 ('D');
|
8590 |
|
|
CHECKSUM_ULEB128 (die->die_tag);
|
8591 |
|
|
|
8592 |
|
|
memset (&attrs, 0, sizeof (attrs));
|
8593 |
|
|
|
8594 |
|
|
decl = get_AT_ref (die, DW_AT_specification);
|
8595 |
|
|
if (decl != NULL)
|
8596 |
|
|
collect_checksum_attributes (&attrs, decl);
|
8597 |
|
|
collect_checksum_attributes (&attrs, die);
|
8598 |
|
|
|
8599 |
|
|
CHECKSUM_ATTR (attrs.at_name);
|
8600 |
|
|
CHECKSUM_ATTR (attrs.at_accessibility);
|
8601 |
|
|
CHECKSUM_ATTR (attrs.at_address_class);
|
8602 |
|
|
CHECKSUM_ATTR (attrs.at_allocated);
|
8603 |
|
|
CHECKSUM_ATTR (attrs.at_artificial);
|
8604 |
|
|
CHECKSUM_ATTR (attrs.at_associated);
|
8605 |
|
|
CHECKSUM_ATTR (attrs.at_binary_scale);
|
8606 |
|
|
CHECKSUM_ATTR (attrs.at_bit_offset);
|
8607 |
|
|
CHECKSUM_ATTR (attrs.at_bit_size);
|
8608 |
|
|
CHECKSUM_ATTR (attrs.at_bit_stride);
|
8609 |
|
|
CHECKSUM_ATTR (attrs.at_byte_size);
|
8610 |
|
|
CHECKSUM_ATTR (attrs.at_byte_stride);
|
8611 |
|
|
CHECKSUM_ATTR (attrs.at_const_value);
|
8612 |
|
|
CHECKSUM_ATTR (attrs.at_containing_type);
|
8613 |
|
|
CHECKSUM_ATTR (attrs.at_count);
|
8614 |
|
|
CHECKSUM_ATTR (attrs.at_data_location);
|
8615 |
|
|
CHECKSUM_ATTR (attrs.at_data_member_location);
|
8616 |
|
|
CHECKSUM_ATTR (attrs.at_decimal_scale);
|
8617 |
|
|
CHECKSUM_ATTR (attrs.at_decimal_sign);
|
8618 |
|
|
CHECKSUM_ATTR (attrs.at_default_value);
|
8619 |
|
|
CHECKSUM_ATTR (attrs.at_digit_count);
|
8620 |
|
|
CHECKSUM_ATTR (attrs.at_discr);
|
8621 |
|
|
CHECKSUM_ATTR (attrs.at_discr_list);
|
8622 |
|
|
CHECKSUM_ATTR (attrs.at_discr_value);
|
8623 |
|
|
CHECKSUM_ATTR (attrs.at_encoding);
|
8624 |
|
|
CHECKSUM_ATTR (attrs.at_endianity);
|
8625 |
|
|
CHECKSUM_ATTR (attrs.at_explicit);
|
8626 |
|
|
CHECKSUM_ATTR (attrs.at_is_optional);
|
8627 |
|
|
CHECKSUM_ATTR (attrs.at_location);
|
8628 |
|
|
CHECKSUM_ATTR (attrs.at_lower_bound);
|
8629 |
|
|
CHECKSUM_ATTR (attrs.at_mutable);
|
8630 |
|
|
CHECKSUM_ATTR (attrs.at_ordering);
|
8631 |
|
|
CHECKSUM_ATTR (attrs.at_picture_string);
|
8632 |
|
|
CHECKSUM_ATTR (attrs.at_prototyped);
|
8633 |
|
|
CHECKSUM_ATTR (attrs.at_small);
|
8634 |
|
|
CHECKSUM_ATTR (attrs.at_segment);
|
8635 |
|
|
CHECKSUM_ATTR (attrs.at_string_length);
|
8636 |
|
|
CHECKSUM_ATTR (attrs.at_threads_scaled);
|
8637 |
|
|
CHECKSUM_ATTR (attrs.at_upper_bound);
|
8638 |
|
|
CHECKSUM_ATTR (attrs.at_use_location);
|
8639 |
|
|
CHECKSUM_ATTR (attrs.at_use_UTF8);
|
8640 |
|
|
CHECKSUM_ATTR (attrs.at_variable_parameter);
|
8641 |
|
|
CHECKSUM_ATTR (attrs.at_virtuality);
|
8642 |
|
|
CHECKSUM_ATTR (attrs.at_visibility);
|
8643 |
|
|
CHECKSUM_ATTR (attrs.at_vtable_elem_location);
|
8644 |
|
|
CHECKSUM_ATTR (attrs.at_type);
|
8645 |
|
|
CHECKSUM_ATTR (attrs.at_friend);
|
8646 |
|
|
|
8647 |
|
|
/* Checksum the child DIEs, except for nested types and member functions. */
|
8648 |
|
|
c = die->die_child;
|
8649 |
|
|
if (c) do {
|
8650 |
|
|
dw_attr_ref name_attr;
|
8651 |
|
|
|
8652 |
|
|
c = c->die_sib;
|
8653 |
|
|
name_attr = get_AT (c, DW_AT_name);
|
8654 |
|
|
if ((is_type_die (c) || c->die_tag == DW_TAG_subprogram)
|
8655 |
|
|
&& name_attr != NULL)
|
8656 |
|
|
{
|
8657 |
|
|
CHECKSUM_ULEB128 ('S');
|
8658 |
|
|
CHECKSUM_ULEB128 (c->die_tag);
|
8659 |
|
|
CHECKSUM_STRING (AT_string (name_attr));
|
8660 |
|
|
}
|
8661 |
|
|
else
|
8662 |
|
|
{
|
8663 |
|
|
/* Mark this DIE so it gets processed when unmarking. */
|
8664 |
|
|
if (c->die_mark == 0)
|
8665 |
|
|
c->die_mark = -1;
|
8666 |
|
|
die_checksum_ordered (c, ctx, mark);
|
8667 |
|
|
}
|
8668 |
|
|
} while (c != die->die_child);
|
8669 |
|
|
|
8670 |
|
|
CHECKSUM_ULEB128 (0);
|
8671 |
|
|
}
|
8672 |
|
|
|
8673 |
|
|
#undef CHECKSUM
|
8674 |
|
|
#undef CHECKSUM_STRING
|
8675 |
|
|
#undef CHECKSUM_ATTR
|
8676 |
|
|
#undef CHECKSUM_LEB128
|
8677 |
|
|
#undef CHECKSUM_ULEB128
|
8678 |
|
|
|
8679 |
|
|
/* Generate the type signature for DIE. This is computed by generating an
|
8680 |
|
|
MD5 checksum over the DIE's tag, its relevant attributes, and its
|
8681 |
|
|
children. Attributes that are references to other DIEs are processed
|
8682 |
|
|
by recursion, using the MARK field to prevent infinite recursion.
|
8683 |
|
|
If the DIE is nested inside a namespace or another type, we also
|
8684 |
|
|
need to include that context in the signature. The lower 64 bits
|
8685 |
|
|
of the resulting MD5 checksum comprise the signature. */
|
8686 |
|
|
|
8687 |
|
|
static void
|
8688 |
|
|
generate_type_signature (dw_die_ref die, comdat_type_node *type_node)
|
8689 |
|
|
{
|
8690 |
|
|
int mark;
|
8691 |
|
|
const char *name;
|
8692 |
|
|
unsigned char checksum[16];
|
8693 |
|
|
struct md5_ctx ctx;
|
8694 |
|
|
dw_die_ref decl;
|
8695 |
|
|
|
8696 |
|
|
name = get_AT_string (die, DW_AT_name);
|
8697 |
|
|
decl = get_AT_ref (die, DW_AT_specification);
|
8698 |
|
|
|
8699 |
|
|
/* First, compute a signature for just the type name (and its surrounding
|
8700 |
|
|
context, if any. This is stored in the type unit DIE for link-time
|
8701 |
|
|
ODR (one-definition rule) checking. */
|
8702 |
|
|
|
8703 |
|
|
if (is_cxx() && name != NULL)
|
8704 |
|
|
{
|
8705 |
|
|
md5_init_ctx (&ctx);
|
8706 |
|
|
|
8707 |
|
|
/* Checksum the names of surrounding namespaces and structures. */
|
8708 |
|
|
if (decl != NULL && decl->die_parent != NULL)
|
8709 |
|
|
checksum_die_context (decl->die_parent, &ctx);
|
8710 |
|
|
|
8711 |
|
|
md5_process_bytes (&die->die_tag, sizeof (die->die_tag), &ctx);
|
8712 |
|
|
md5_process_bytes (name, strlen (name) + 1, &ctx);
|
8713 |
|
|
md5_finish_ctx (&ctx, checksum);
|
8714 |
|
|
|
8715 |
|
|
add_AT_data8 (type_node->root_die, DW_AT_GNU_odr_signature, &checksum[8]);
|
8716 |
|
|
}
|
8717 |
|
|
|
8718 |
|
|
/* Next, compute the complete type signature. */
|
8719 |
|
|
|
8720 |
|
|
md5_init_ctx (&ctx);
|
8721 |
|
|
mark = 1;
|
8722 |
|
|
die->die_mark = mark;
|
8723 |
|
|
|
8724 |
|
|
/* Checksum the names of surrounding namespaces and structures. */
|
8725 |
|
|
if (decl != NULL && decl->die_parent != NULL)
|
8726 |
|
|
checksum_die_context (decl->die_parent, &ctx);
|
8727 |
|
|
|
8728 |
|
|
/* Checksum the DIE and its children. */
|
8729 |
|
|
die_checksum_ordered (die, &ctx, &mark);
|
8730 |
|
|
unmark_all_dies (die);
|
8731 |
|
|
md5_finish_ctx (&ctx, checksum);
|
8732 |
|
|
|
8733 |
|
|
/* Store the signature in the type node and link the type DIE and the
|
8734 |
|
|
type node together. */
|
8735 |
|
|
memcpy (type_node->signature, &checksum[16 - DWARF_TYPE_SIGNATURE_SIZE],
|
8736 |
|
|
DWARF_TYPE_SIGNATURE_SIZE);
|
8737 |
|
|
die->die_id.die_type_node = type_node;
|
8738 |
|
|
type_node->type_die = die;
|
8739 |
|
|
|
8740 |
|
|
/* If the DIE is a specification, link its declaration to the type node
|
8741 |
|
|
as well. */
|
8742 |
|
|
if (decl != NULL)
|
8743 |
|
|
decl->die_id.die_type_node = type_node;
|
8744 |
|
|
}
|
8745 |
|
|
|
8746 |
|
|
/* Do the location expressions look same? */
|
8747 |
|
|
static inline int
|
8748 |
|
|
same_loc_p (dw_loc_descr_ref loc1, dw_loc_descr_ref loc2, int *mark)
|
8749 |
|
|
{
|
8750 |
|
|
return loc1->dw_loc_opc == loc2->dw_loc_opc
|
8751 |
|
|
&& same_dw_val_p (&loc1->dw_loc_oprnd1, &loc2->dw_loc_oprnd1, mark)
|
8752 |
|
|
&& same_dw_val_p (&loc1->dw_loc_oprnd2, &loc2->dw_loc_oprnd2, mark);
|
8753 |
|
|
}
|
8754 |
|
|
|
8755 |
|
|
/* Do the values look the same? */
|
8756 |
|
|
static int
|
8757 |
|
|
same_dw_val_p (const dw_val_node *v1, const dw_val_node *v2, int *mark)
|
8758 |
|
|
{
|
8759 |
|
|
dw_loc_descr_ref loc1, loc2;
|
8760 |
|
|
rtx r1, r2;
|
8761 |
|
|
|
8762 |
|
|
if (v1->val_class != v2->val_class)
|
8763 |
|
|
return 0;
|
8764 |
|
|
|
8765 |
|
|
switch (v1->val_class)
|
8766 |
|
|
{
|
8767 |
|
|
case dw_val_class_const:
|
8768 |
|
|
return v1->v.val_int == v2->v.val_int;
|
8769 |
|
|
case dw_val_class_unsigned_const:
|
8770 |
|
|
return v1->v.val_unsigned == v2->v.val_unsigned;
|
8771 |
|
|
case dw_val_class_const_double:
|
8772 |
|
|
return v1->v.val_double.high == v2->v.val_double.high
|
8773 |
|
|
&& v1->v.val_double.low == v2->v.val_double.low;
|
8774 |
|
|
case dw_val_class_vec:
|
8775 |
|
|
if (v1->v.val_vec.length != v2->v.val_vec.length
|
8776 |
|
|
|| v1->v.val_vec.elt_size != v2->v.val_vec.elt_size)
|
8777 |
|
|
return 0;
|
8778 |
|
|
if (memcmp (v1->v.val_vec.array, v2->v.val_vec.array,
|
8779 |
|
|
v1->v.val_vec.length * v1->v.val_vec.elt_size))
|
8780 |
|
|
return 0;
|
8781 |
|
|
return 1;
|
8782 |
|
|
case dw_val_class_flag:
|
8783 |
|
|
return v1->v.val_flag == v2->v.val_flag;
|
8784 |
|
|
case dw_val_class_str:
|
8785 |
|
|
return !strcmp(v1->v.val_str->str, v2->v.val_str->str);
|
8786 |
|
|
|
8787 |
|
|
case dw_val_class_addr:
|
8788 |
|
|
r1 = v1->v.val_addr;
|
8789 |
|
|
r2 = v2->v.val_addr;
|
8790 |
|
|
if (GET_CODE (r1) != GET_CODE (r2))
|
8791 |
|
|
return 0;
|
8792 |
|
|
return !rtx_equal_p (r1, r2);
|
8793 |
|
|
|
8794 |
|
|
case dw_val_class_offset:
|
8795 |
|
|
return v1->v.val_offset == v2->v.val_offset;
|
8796 |
|
|
|
8797 |
|
|
case dw_val_class_loc:
|
8798 |
|
|
for (loc1 = v1->v.val_loc, loc2 = v2->v.val_loc;
|
8799 |
|
|
loc1 && loc2;
|
8800 |
|
|
loc1 = loc1->dw_loc_next, loc2 = loc2->dw_loc_next)
|
8801 |
|
|
if (!same_loc_p (loc1, loc2, mark))
|
8802 |
|
|
return 0;
|
8803 |
|
|
return !loc1 && !loc2;
|
8804 |
|
|
|
8805 |
|
|
case dw_val_class_die_ref:
|
8806 |
|
|
return same_die_p (v1->v.val_die_ref.die, v2->v.val_die_ref.die, mark);
|
8807 |
|
|
|
8808 |
|
|
case dw_val_class_fde_ref:
|
8809 |
|
|
case dw_val_class_lbl_id:
|
8810 |
|
|
case dw_val_class_lineptr:
|
8811 |
|
|
case dw_val_class_macptr:
|
8812 |
|
|
return 1;
|
8813 |
|
|
|
8814 |
|
|
case dw_val_class_file:
|
8815 |
|
|
return v1->v.val_file == v2->v.val_file;
|
8816 |
|
|
|
8817 |
|
|
case dw_val_class_data8:
|
8818 |
|
|
return !memcmp (v1->v.val_data8, v2->v.val_data8, 8);
|
8819 |
|
|
|
8820 |
|
|
default:
|
8821 |
|
|
return 1;
|
8822 |
|
|
}
|
8823 |
|
|
}
|
8824 |
|
|
|
8825 |
|
|
/* Do the attributes look the same? */
|
8826 |
|
|
|
8827 |
|
|
static int
|
8828 |
|
|
same_attr_p (dw_attr_ref at1, dw_attr_ref at2, int *mark)
|
8829 |
|
|
{
|
8830 |
|
|
if (at1->dw_attr != at2->dw_attr)
|
8831 |
|
|
return 0;
|
8832 |
|
|
|
8833 |
|
|
/* We don't care that this was compiled with a different compiler
|
8834 |
|
|
snapshot; if the output is the same, that's what matters. */
|
8835 |
|
|
if (at1->dw_attr == DW_AT_producer)
|
8836 |
|
|
return 1;
|
8837 |
|
|
|
8838 |
|
|
return same_dw_val_p (&at1->dw_attr_val, &at2->dw_attr_val, mark);
|
8839 |
|
|
}
|
8840 |
|
|
|
8841 |
|
|
/* Do the dies look the same? */
|
8842 |
|
|
|
8843 |
|
|
static int
|
8844 |
|
|
same_die_p (dw_die_ref die1, dw_die_ref die2, int *mark)
|
8845 |
|
|
{
|
8846 |
|
|
dw_die_ref c1, c2;
|
8847 |
|
|
dw_attr_ref a1;
|
8848 |
|
|
unsigned ix;
|
8849 |
|
|
|
8850 |
|
|
/* To avoid infinite recursion. */
|
8851 |
|
|
if (die1->die_mark)
|
8852 |
|
|
return die1->die_mark == die2->die_mark;
|
8853 |
|
|
die1->die_mark = die2->die_mark = ++(*mark);
|
8854 |
|
|
|
8855 |
|
|
if (die1->die_tag != die2->die_tag)
|
8856 |
|
|
return 0;
|
8857 |
|
|
|
8858 |
|
|
if (VEC_length (dw_attr_node, die1->die_attr)
|
8859 |
|
|
!= VEC_length (dw_attr_node, die2->die_attr))
|
8860 |
|
|
return 0;
|
8861 |
|
|
|
8862 |
|
|
for (ix = 0; VEC_iterate (dw_attr_node, die1->die_attr, ix, a1); ix++)
|
8863 |
|
|
if (!same_attr_p (a1, VEC_index (dw_attr_node, die2->die_attr, ix), mark))
|
8864 |
|
|
return 0;
|
8865 |
|
|
|
8866 |
|
|
c1 = die1->die_child;
|
8867 |
|
|
c2 = die2->die_child;
|
8868 |
|
|
if (! c1)
|
8869 |
|
|
{
|
8870 |
|
|
if (c2)
|
8871 |
|
|
return 0;
|
8872 |
|
|
}
|
8873 |
|
|
else
|
8874 |
|
|
for (;;)
|
8875 |
|
|
{
|
8876 |
|
|
if (!same_die_p (c1, c2, mark))
|
8877 |
|
|
return 0;
|
8878 |
|
|
c1 = c1->die_sib;
|
8879 |
|
|
c2 = c2->die_sib;
|
8880 |
|
|
if (c1 == die1->die_child)
|
8881 |
|
|
{
|
8882 |
|
|
if (c2 == die2->die_child)
|
8883 |
|
|
break;
|
8884 |
|
|
else
|
8885 |
|
|
return 0;
|
8886 |
|
|
}
|
8887 |
|
|
}
|
8888 |
|
|
|
8889 |
|
|
return 1;
|
8890 |
|
|
}
|
8891 |
|
|
|
8892 |
|
|
/* Do the dies look the same? Wrapper around same_die_p. */
|
8893 |
|
|
|
8894 |
|
|
static int
|
8895 |
|
|
same_die_p_wrap (dw_die_ref die1, dw_die_ref die2)
|
8896 |
|
|
{
|
8897 |
|
|
int mark = 0;
|
8898 |
|
|
int ret = same_die_p (die1, die2, &mark);
|
8899 |
|
|
|
8900 |
|
|
unmark_all_dies (die1);
|
8901 |
|
|
unmark_all_dies (die2);
|
8902 |
|
|
|
8903 |
|
|
return ret;
|
8904 |
|
|
}
|
8905 |
|
|
|
8906 |
|
|
/* The prefix to attach to symbols on DIEs in the current comdat debug
|
8907 |
|
|
info section. */
|
8908 |
|
|
static char *comdat_symbol_id;
|
8909 |
|
|
|
8910 |
|
|
/* The index of the current symbol within the current comdat CU. */
|
8911 |
|
|
static unsigned int comdat_symbol_number;
|
8912 |
|
|
|
8913 |
|
|
/* Calculate the MD5 checksum of the compilation unit DIE UNIT_DIE and its
|
8914 |
|
|
children, and set comdat_symbol_id accordingly. */
|
8915 |
|
|
|
8916 |
|
|
static void
|
8917 |
|
|
compute_section_prefix (dw_die_ref unit_die)
|
8918 |
|
|
{
|
8919 |
|
|
const char *die_name = get_AT_string (unit_die, DW_AT_name);
|
8920 |
|
|
const char *base = die_name ? lbasename (die_name) : "anonymous";
|
8921 |
|
|
char *name = XALLOCAVEC (char, strlen (base) + 64);
|
8922 |
|
|
char *p;
|
8923 |
|
|
int i, mark;
|
8924 |
|
|
unsigned char checksum[16];
|
8925 |
|
|
struct md5_ctx ctx;
|
8926 |
|
|
|
8927 |
|
|
/* Compute the checksum of the DIE, then append part of it as hex digits to
|
8928 |
|
|
the name filename of the unit. */
|
8929 |
|
|
|
8930 |
|
|
md5_init_ctx (&ctx);
|
8931 |
|
|
mark = 0;
|
8932 |
|
|
die_checksum (unit_die, &ctx, &mark);
|
8933 |
|
|
unmark_all_dies (unit_die);
|
8934 |
|
|
md5_finish_ctx (&ctx, checksum);
|
8935 |
|
|
|
8936 |
|
|
sprintf (name, "%s.", base);
|
8937 |
|
|
clean_symbol_name (name);
|
8938 |
|
|
|
8939 |
|
|
p = name + strlen (name);
|
8940 |
|
|
for (i = 0; i < 4; i++)
|
8941 |
|
|
{
|
8942 |
|
|
sprintf (p, "%.2x", checksum[i]);
|
8943 |
|
|
p += 2;
|
8944 |
|
|
}
|
8945 |
|
|
|
8946 |
|
|
comdat_symbol_id = unit_die->die_id.die_symbol = xstrdup (name);
|
8947 |
|
|
comdat_symbol_number = 0;
|
8948 |
|
|
}
|
8949 |
|
|
|
8950 |
|
|
/* Returns nonzero if DIE represents a type, in the sense of TYPE_P. */
|
8951 |
|
|
|
8952 |
|
|
static int
|
8953 |
|
|
is_type_die (dw_die_ref die)
|
8954 |
|
|
{
|
8955 |
|
|
switch (die->die_tag)
|
8956 |
|
|
{
|
8957 |
|
|
case DW_TAG_array_type:
|
8958 |
|
|
case DW_TAG_class_type:
|
8959 |
|
|
case DW_TAG_interface_type:
|
8960 |
|
|
case DW_TAG_enumeration_type:
|
8961 |
|
|
case DW_TAG_pointer_type:
|
8962 |
|
|
case DW_TAG_reference_type:
|
8963 |
|
|
case DW_TAG_string_type:
|
8964 |
|
|
case DW_TAG_structure_type:
|
8965 |
|
|
case DW_TAG_subroutine_type:
|
8966 |
|
|
case DW_TAG_union_type:
|
8967 |
|
|
case DW_TAG_ptr_to_member_type:
|
8968 |
|
|
case DW_TAG_set_type:
|
8969 |
|
|
case DW_TAG_subrange_type:
|
8970 |
|
|
case DW_TAG_base_type:
|
8971 |
|
|
case DW_TAG_const_type:
|
8972 |
|
|
case DW_TAG_file_type:
|
8973 |
|
|
case DW_TAG_packed_type:
|
8974 |
|
|
case DW_TAG_volatile_type:
|
8975 |
|
|
case DW_TAG_typedef:
|
8976 |
|
|
return 1;
|
8977 |
|
|
default:
|
8978 |
|
|
return 0;
|
8979 |
|
|
}
|
8980 |
|
|
}
|
8981 |
|
|
|
8982 |
|
|
/* Returns 1 iff C is the sort of DIE that should go into a COMDAT CU.
|
8983 |
|
|
Basically, we want to choose the bits that are likely to be shared between
|
8984 |
|
|
compilations (types) and leave out the bits that are specific to individual
|
8985 |
|
|
compilations (functions). */
|
8986 |
|
|
|
8987 |
|
|
static int
|
8988 |
|
|
is_comdat_die (dw_die_ref c)
|
8989 |
|
|
{
|
8990 |
|
|
/* I think we want to leave base types and __vtbl_ptr_type in the main CU, as
|
8991 |
|
|
we do for stabs. The advantage is a greater likelihood of sharing between
|
8992 |
|
|
objects that don't include headers in the same order (and therefore would
|
8993 |
|
|
put the base types in a different comdat). jason 8/28/00 */
|
8994 |
|
|
|
8995 |
|
|
if (c->die_tag == DW_TAG_base_type)
|
8996 |
|
|
return 0;
|
8997 |
|
|
|
8998 |
|
|
if (c->die_tag == DW_TAG_pointer_type
|
8999 |
|
|
|| c->die_tag == DW_TAG_reference_type
|
9000 |
|
|
|| c->die_tag == DW_TAG_const_type
|
9001 |
|
|
|| c->die_tag == DW_TAG_volatile_type)
|
9002 |
|
|
{
|
9003 |
|
|
dw_die_ref t = get_AT_ref (c, DW_AT_type);
|
9004 |
|
|
|
9005 |
|
|
return t ? is_comdat_die (t) : 0;
|
9006 |
|
|
}
|
9007 |
|
|
|
9008 |
|
|
return is_type_die (c);
|
9009 |
|
|
}
|
9010 |
|
|
|
9011 |
|
|
/* Returns 1 iff C is the sort of DIE that might be referred to from another
|
9012 |
|
|
compilation unit. */
|
9013 |
|
|
|
9014 |
|
|
static int
|
9015 |
|
|
is_symbol_die (dw_die_ref c)
|
9016 |
|
|
{
|
9017 |
|
|
return (is_type_die (c)
|
9018 |
|
|
|| is_declaration_die (c)
|
9019 |
|
|
|| c->die_tag == DW_TAG_namespace
|
9020 |
|
|
|| c->die_tag == DW_TAG_module);
|
9021 |
|
|
}
|
9022 |
|
|
|
9023 |
|
|
static char *
|
9024 |
|
|
gen_internal_sym (const char *prefix)
|
9025 |
|
|
{
|
9026 |
|
|
char buf[256];
|
9027 |
|
|
|
9028 |
|
|
ASM_GENERATE_INTERNAL_LABEL (buf, prefix, label_num++);
|
9029 |
|
|
return xstrdup (buf);
|
9030 |
|
|
}
|
9031 |
|
|
|
9032 |
|
|
/* Assign symbols to all worthy DIEs under DIE. */
|
9033 |
|
|
|
9034 |
|
|
static void
|
9035 |
|
|
assign_symbol_names (dw_die_ref die)
|
9036 |
|
|
{
|
9037 |
|
|
dw_die_ref c;
|
9038 |
|
|
|
9039 |
|
|
if (is_symbol_die (die))
|
9040 |
|
|
{
|
9041 |
|
|
if (comdat_symbol_id)
|
9042 |
|
|
{
|
9043 |
|
|
char *p = XALLOCAVEC (char, strlen (comdat_symbol_id) + 64);
|
9044 |
|
|
|
9045 |
|
|
sprintf (p, "%s.%s.%x", DIE_LABEL_PREFIX,
|
9046 |
|
|
comdat_symbol_id, comdat_symbol_number++);
|
9047 |
|
|
die->die_id.die_symbol = xstrdup (p);
|
9048 |
|
|
}
|
9049 |
|
|
else
|
9050 |
|
|
die->die_id.die_symbol = gen_internal_sym ("LDIE");
|
9051 |
|
|
}
|
9052 |
|
|
|
9053 |
|
|
FOR_EACH_CHILD (die, c, assign_symbol_names (c));
|
9054 |
|
|
}
|
9055 |
|
|
|
9056 |
|
|
struct cu_hash_table_entry
|
9057 |
|
|
{
|
9058 |
|
|
dw_die_ref cu;
|
9059 |
|
|
unsigned min_comdat_num, max_comdat_num;
|
9060 |
|
|
struct cu_hash_table_entry *next;
|
9061 |
|
|
};
|
9062 |
|
|
|
9063 |
|
|
/* Routines to manipulate hash table of CUs. */
|
9064 |
|
|
static hashval_t
|
9065 |
|
|
htab_cu_hash (const void *of)
|
9066 |
|
|
{
|
9067 |
|
|
const struct cu_hash_table_entry *const entry =
|
9068 |
|
|
(const struct cu_hash_table_entry *) of;
|
9069 |
|
|
|
9070 |
|
|
return htab_hash_string (entry->cu->die_id.die_symbol);
|
9071 |
|
|
}
|
9072 |
|
|
|
9073 |
|
|
static int
|
9074 |
|
|
htab_cu_eq (const void *of1, const void *of2)
|
9075 |
|
|
{
|
9076 |
|
|
const struct cu_hash_table_entry *const entry1 =
|
9077 |
|
|
(const struct cu_hash_table_entry *) of1;
|
9078 |
|
|
const struct die_struct *const entry2 = (const struct die_struct *) of2;
|
9079 |
|
|
|
9080 |
|
|
return !strcmp (entry1->cu->die_id.die_symbol, entry2->die_id.die_symbol);
|
9081 |
|
|
}
|
9082 |
|
|
|
9083 |
|
|
static void
|
9084 |
|
|
htab_cu_del (void *what)
|
9085 |
|
|
{
|
9086 |
|
|
struct cu_hash_table_entry *next,
|
9087 |
|
|
*entry = (struct cu_hash_table_entry *) what;
|
9088 |
|
|
|
9089 |
|
|
while (entry)
|
9090 |
|
|
{
|
9091 |
|
|
next = entry->next;
|
9092 |
|
|
free (entry);
|
9093 |
|
|
entry = next;
|
9094 |
|
|
}
|
9095 |
|
|
}
|
9096 |
|
|
|
9097 |
|
|
/* Check whether we have already seen this CU and set up SYM_NUM
|
9098 |
|
|
accordingly. */
|
9099 |
|
|
static int
|
9100 |
|
|
check_duplicate_cu (dw_die_ref cu, htab_t htable, unsigned int *sym_num)
|
9101 |
|
|
{
|
9102 |
|
|
struct cu_hash_table_entry dummy;
|
9103 |
|
|
struct cu_hash_table_entry **slot, *entry, *last = &dummy;
|
9104 |
|
|
|
9105 |
|
|
dummy.max_comdat_num = 0;
|
9106 |
|
|
|
9107 |
|
|
slot = (struct cu_hash_table_entry **)
|
9108 |
|
|
htab_find_slot_with_hash (htable, cu, htab_hash_string (cu->die_id.die_symbol),
|
9109 |
|
|
INSERT);
|
9110 |
|
|
entry = *slot;
|
9111 |
|
|
|
9112 |
|
|
for (; entry; last = entry, entry = entry->next)
|
9113 |
|
|
{
|
9114 |
|
|
if (same_die_p_wrap (cu, entry->cu))
|
9115 |
|
|
break;
|
9116 |
|
|
}
|
9117 |
|
|
|
9118 |
|
|
if (entry)
|
9119 |
|
|
{
|
9120 |
|
|
*sym_num = entry->min_comdat_num;
|
9121 |
|
|
return 1;
|
9122 |
|
|
}
|
9123 |
|
|
|
9124 |
|
|
entry = XCNEW (struct cu_hash_table_entry);
|
9125 |
|
|
entry->cu = cu;
|
9126 |
|
|
entry->min_comdat_num = *sym_num = last->max_comdat_num;
|
9127 |
|
|
entry->next = *slot;
|
9128 |
|
|
*slot = entry;
|
9129 |
|
|
|
9130 |
|
|
return 0;
|
9131 |
|
|
}
|
9132 |
|
|
|
9133 |
|
|
/* Record SYM_NUM to record of CU in HTABLE. */
|
9134 |
|
|
static void
|
9135 |
|
|
record_comdat_symbol_number (dw_die_ref cu, htab_t htable, unsigned int sym_num)
|
9136 |
|
|
{
|
9137 |
|
|
struct cu_hash_table_entry **slot, *entry;
|
9138 |
|
|
|
9139 |
|
|
slot = (struct cu_hash_table_entry **)
|
9140 |
|
|
htab_find_slot_with_hash (htable, cu, htab_hash_string (cu->die_id.die_symbol),
|
9141 |
|
|
NO_INSERT);
|
9142 |
|
|
entry = *slot;
|
9143 |
|
|
|
9144 |
|
|
entry->max_comdat_num = sym_num;
|
9145 |
|
|
}
|
9146 |
|
|
|
9147 |
|
|
/* Traverse the DIE (which is always comp_unit_die), and set up
|
9148 |
|
|
additional compilation units for each of the include files we see
|
9149 |
|
|
bracketed by BINCL/EINCL. */
|
9150 |
|
|
|
9151 |
|
|
static void
|
9152 |
|
|
break_out_includes (dw_die_ref die)
|
9153 |
|
|
{
|
9154 |
|
|
dw_die_ref c;
|
9155 |
|
|
dw_die_ref unit = NULL;
|
9156 |
|
|
limbo_die_node *node, **pnode;
|
9157 |
|
|
htab_t cu_hash_table;
|
9158 |
|
|
|
9159 |
|
|
c = die->die_child;
|
9160 |
|
|
if (c) do {
|
9161 |
|
|
dw_die_ref prev = c;
|
9162 |
|
|
c = c->die_sib;
|
9163 |
|
|
while (c->die_tag == DW_TAG_GNU_BINCL || c->die_tag == DW_TAG_GNU_EINCL
|
9164 |
|
|
|| (unit && is_comdat_die (c)))
|
9165 |
|
|
{
|
9166 |
|
|
dw_die_ref next = c->die_sib;
|
9167 |
|
|
|
9168 |
|
|
/* This DIE is for a secondary CU; remove it from the main one. */
|
9169 |
|
|
remove_child_with_prev (c, prev);
|
9170 |
|
|
|
9171 |
|
|
if (c->die_tag == DW_TAG_GNU_BINCL)
|
9172 |
|
|
unit = push_new_compile_unit (unit, c);
|
9173 |
|
|
else if (c->die_tag == DW_TAG_GNU_EINCL)
|
9174 |
|
|
unit = pop_compile_unit (unit);
|
9175 |
|
|
else
|
9176 |
|
|
add_child_die (unit, c);
|
9177 |
|
|
c = next;
|
9178 |
|
|
if (c == die->die_child)
|
9179 |
|
|
break;
|
9180 |
|
|
}
|
9181 |
|
|
} while (c != die->die_child);
|
9182 |
|
|
|
9183 |
|
|
#if 0
|
9184 |
|
|
/* We can only use this in debugging, since the frontend doesn't check
|
9185 |
|
|
to make sure that we leave every include file we enter. */
|
9186 |
|
|
gcc_assert (!unit);
|
9187 |
|
|
#endif
|
9188 |
|
|
|
9189 |
|
|
assign_symbol_names (die);
|
9190 |
|
|
cu_hash_table = htab_create (10, htab_cu_hash, htab_cu_eq, htab_cu_del);
|
9191 |
|
|
for (node = limbo_die_list, pnode = &limbo_die_list;
|
9192 |
|
|
node;
|
9193 |
|
|
node = node->next)
|
9194 |
|
|
{
|
9195 |
|
|
int is_dupl;
|
9196 |
|
|
|
9197 |
|
|
compute_section_prefix (node->die);
|
9198 |
|
|
is_dupl = check_duplicate_cu (node->die, cu_hash_table,
|
9199 |
|
|
&comdat_symbol_number);
|
9200 |
|
|
assign_symbol_names (node->die);
|
9201 |
|
|
if (is_dupl)
|
9202 |
|
|
*pnode = node->next;
|
9203 |
|
|
else
|
9204 |
|
|
{
|
9205 |
|
|
pnode = &node->next;
|
9206 |
|
|
record_comdat_symbol_number (node->die, cu_hash_table,
|
9207 |
|
|
comdat_symbol_number);
|
9208 |
|
|
}
|
9209 |
|
|
}
|
9210 |
|
|
htab_delete (cu_hash_table);
|
9211 |
|
|
}
|
9212 |
|
|
|
9213 |
|
|
/* Return non-zero if this DIE is a declaration. */
|
9214 |
|
|
|
9215 |
|
|
static int
|
9216 |
|
|
is_declaration_die (dw_die_ref die)
|
9217 |
|
|
{
|
9218 |
|
|
dw_attr_ref a;
|
9219 |
|
|
unsigned ix;
|
9220 |
|
|
|
9221 |
|
|
for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
|
9222 |
|
|
if (a->dw_attr == DW_AT_declaration)
|
9223 |
|
|
return 1;
|
9224 |
|
|
|
9225 |
|
|
return 0;
|
9226 |
|
|
}
|
9227 |
|
|
|
9228 |
|
|
/* Return non-zero if this is a type DIE that should be moved to a
|
9229 |
|
|
COMDAT .debug_types section. */
|
9230 |
|
|
|
9231 |
|
|
static int
|
9232 |
|
|
should_move_die_to_comdat (dw_die_ref die)
|
9233 |
|
|
{
|
9234 |
|
|
switch (die->die_tag)
|
9235 |
|
|
{
|
9236 |
|
|
case DW_TAG_class_type:
|
9237 |
|
|
case DW_TAG_structure_type:
|
9238 |
|
|
case DW_TAG_enumeration_type:
|
9239 |
|
|
case DW_TAG_union_type:
|
9240 |
|
|
/* Don't move declarations or inlined instances. */
|
9241 |
|
|
if (is_declaration_die (die) || get_AT (die, DW_AT_abstract_origin))
|
9242 |
|
|
return 0;
|
9243 |
|
|
return 1;
|
9244 |
|
|
case DW_TAG_array_type:
|
9245 |
|
|
case DW_TAG_interface_type:
|
9246 |
|
|
case DW_TAG_pointer_type:
|
9247 |
|
|
case DW_TAG_reference_type:
|
9248 |
|
|
case DW_TAG_string_type:
|
9249 |
|
|
case DW_TAG_subroutine_type:
|
9250 |
|
|
case DW_TAG_ptr_to_member_type:
|
9251 |
|
|
case DW_TAG_set_type:
|
9252 |
|
|
case DW_TAG_subrange_type:
|
9253 |
|
|
case DW_TAG_base_type:
|
9254 |
|
|
case DW_TAG_const_type:
|
9255 |
|
|
case DW_TAG_file_type:
|
9256 |
|
|
case DW_TAG_packed_type:
|
9257 |
|
|
case DW_TAG_volatile_type:
|
9258 |
|
|
case DW_TAG_typedef:
|
9259 |
|
|
default:
|
9260 |
|
|
return 0;
|
9261 |
|
|
}
|
9262 |
|
|
}
|
9263 |
|
|
|
9264 |
|
|
/* Make a clone of DIE. */
|
9265 |
|
|
|
9266 |
|
|
static dw_die_ref
|
9267 |
|
|
clone_die (dw_die_ref die)
|
9268 |
|
|
{
|
9269 |
|
|
dw_die_ref clone;
|
9270 |
|
|
dw_attr_ref a;
|
9271 |
|
|
unsigned ix;
|
9272 |
|
|
|
9273 |
|
|
clone = GGC_CNEW (die_node);
|
9274 |
|
|
clone->die_tag = die->die_tag;
|
9275 |
|
|
|
9276 |
|
|
for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
|
9277 |
|
|
add_dwarf_attr (clone, a);
|
9278 |
|
|
|
9279 |
|
|
return clone;
|
9280 |
|
|
}
|
9281 |
|
|
|
9282 |
|
|
/* Make a clone of the tree rooted at DIE. */
|
9283 |
|
|
|
9284 |
|
|
static dw_die_ref
|
9285 |
|
|
clone_tree (dw_die_ref die)
|
9286 |
|
|
{
|
9287 |
|
|
dw_die_ref c;
|
9288 |
|
|
dw_die_ref clone = clone_die (die);
|
9289 |
|
|
|
9290 |
|
|
FOR_EACH_CHILD (die, c, add_child_die (clone, clone_tree(c)));
|
9291 |
|
|
|
9292 |
|
|
return clone;
|
9293 |
|
|
}
|
9294 |
|
|
|
9295 |
|
|
/* Make a clone of DIE as a declaration. */
|
9296 |
|
|
|
9297 |
|
|
static dw_die_ref
|
9298 |
|
|
clone_as_declaration (dw_die_ref die)
|
9299 |
|
|
{
|
9300 |
|
|
dw_die_ref clone;
|
9301 |
|
|
dw_die_ref decl;
|
9302 |
|
|
dw_attr_ref a;
|
9303 |
|
|
unsigned ix;
|
9304 |
|
|
|
9305 |
|
|
/* If the DIE is already a declaration, just clone it. */
|
9306 |
|
|
if (is_declaration_die (die))
|
9307 |
|
|
return clone_die (die);
|
9308 |
|
|
|
9309 |
|
|
/* If the DIE is a specification, just clone its declaration DIE. */
|
9310 |
|
|
decl = get_AT_ref (die, DW_AT_specification);
|
9311 |
|
|
if (decl != NULL)
|
9312 |
|
|
return clone_die (decl);
|
9313 |
|
|
|
9314 |
|
|
clone = GGC_CNEW (die_node);
|
9315 |
|
|
clone->die_tag = die->die_tag;
|
9316 |
|
|
|
9317 |
|
|
for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
|
9318 |
|
|
{
|
9319 |
|
|
/* We don't want to copy over all attributes.
|
9320 |
|
|
For example we don't want DW_AT_byte_size because otherwise we will no
|
9321 |
|
|
longer have a declaration and GDB will treat it as a definition. */
|
9322 |
|
|
|
9323 |
|
|
switch (a->dw_attr)
|
9324 |
|
|
{
|
9325 |
|
|
case DW_AT_artificial:
|
9326 |
|
|
case DW_AT_containing_type:
|
9327 |
|
|
case DW_AT_external:
|
9328 |
|
|
case DW_AT_name:
|
9329 |
|
|
case DW_AT_type:
|
9330 |
|
|
case DW_AT_virtuality:
|
9331 |
|
|
case DW_AT_MIPS_linkage_name:
|
9332 |
|
|
add_dwarf_attr (clone, a);
|
9333 |
|
|
break;
|
9334 |
|
|
case DW_AT_byte_size:
|
9335 |
|
|
default:
|
9336 |
|
|
break;
|
9337 |
|
|
}
|
9338 |
|
|
}
|
9339 |
|
|
|
9340 |
|
|
if (die->die_id.die_type_node)
|
9341 |
|
|
add_AT_die_ref (clone, DW_AT_signature, die);
|
9342 |
|
|
|
9343 |
|
|
add_AT_flag (clone, DW_AT_declaration, 1);
|
9344 |
|
|
return clone;
|
9345 |
|
|
}
|
9346 |
|
|
|
9347 |
|
|
/* Copy the declaration context to the new compile unit DIE. This includes
|
9348 |
|
|
any surrounding namespace or type declarations. If the DIE has an
|
9349 |
|
|
AT_specification attribute, it also includes attributes and children
|
9350 |
|
|
attached to the specification. */
|
9351 |
|
|
|
9352 |
|
|
static void
|
9353 |
|
|
copy_declaration_context (dw_die_ref unit, dw_die_ref die)
|
9354 |
|
|
{
|
9355 |
|
|
dw_die_ref decl;
|
9356 |
|
|
dw_die_ref new_decl;
|
9357 |
|
|
|
9358 |
|
|
decl = get_AT_ref (die, DW_AT_specification);
|
9359 |
|
|
if (decl == NULL)
|
9360 |
|
|
decl = die;
|
9361 |
|
|
else
|
9362 |
|
|
{
|
9363 |
|
|
unsigned ix;
|
9364 |
|
|
dw_die_ref c;
|
9365 |
|
|
dw_attr_ref a;
|
9366 |
|
|
|
9367 |
|
|
/* Copy the type node pointer from the new DIE to the original
|
9368 |
|
|
declaration DIE so we can forward references later. */
|
9369 |
|
|
decl->die_id.die_type_node = die->die_id.die_type_node;
|
9370 |
|
|
|
9371 |
|
|
remove_AT (die, DW_AT_specification);
|
9372 |
|
|
|
9373 |
|
|
for (ix = 0; VEC_iterate (dw_attr_node, decl->die_attr, ix, a); ix++)
|
9374 |
|
|
{
|
9375 |
|
|
if (a->dw_attr != DW_AT_name
|
9376 |
|
|
&& a->dw_attr != DW_AT_declaration
|
9377 |
|
|
&& a->dw_attr != DW_AT_external)
|
9378 |
|
|
add_dwarf_attr (die, a);
|
9379 |
|
|
}
|
9380 |
|
|
|
9381 |
|
|
FOR_EACH_CHILD (decl, c, add_child_die (die, clone_tree(c)));
|
9382 |
|
|
}
|
9383 |
|
|
|
9384 |
|
|
if (decl->die_parent != NULL
|
9385 |
|
|
&& decl->die_parent->die_tag != DW_TAG_compile_unit
|
9386 |
|
|
&& decl->die_parent->die_tag != DW_TAG_type_unit)
|
9387 |
|
|
{
|
9388 |
|
|
new_decl = copy_ancestor_tree (unit, decl, NULL);
|
9389 |
|
|
if (new_decl != NULL)
|
9390 |
|
|
{
|
9391 |
|
|
remove_AT (new_decl, DW_AT_signature);
|
9392 |
|
|
add_AT_specification (die, new_decl);
|
9393 |
|
|
}
|
9394 |
|
|
}
|
9395 |
|
|
}
|
9396 |
|
|
|
9397 |
|
|
/* Generate the skeleton ancestor tree for the given NODE, then clone
|
9398 |
|
|
the DIE and add the clone into the tree. */
|
9399 |
|
|
|
9400 |
|
|
static void
|
9401 |
|
|
generate_skeleton_ancestor_tree (skeleton_chain_node *node)
|
9402 |
|
|
{
|
9403 |
|
|
if (node->new_die != NULL)
|
9404 |
|
|
return;
|
9405 |
|
|
|
9406 |
|
|
node->new_die = clone_as_declaration (node->old_die);
|
9407 |
|
|
|
9408 |
|
|
if (node->parent != NULL)
|
9409 |
|
|
{
|
9410 |
|
|
generate_skeleton_ancestor_tree (node->parent);
|
9411 |
|
|
add_child_die (node->parent->new_die, node->new_die);
|
9412 |
|
|
}
|
9413 |
|
|
}
|
9414 |
|
|
|
9415 |
|
|
/* Generate a skeleton tree of DIEs containing any declarations that are
|
9416 |
|
|
found in the original tree. We traverse the tree looking for declaration
|
9417 |
|
|
DIEs, and construct the skeleton from the bottom up whenever we find one. */
|
9418 |
|
|
|
9419 |
|
|
static void
|
9420 |
|
|
generate_skeleton_bottom_up (skeleton_chain_node *parent)
|
9421 |
|
|
{
|
9422 |
|
|
skeleton_chain_node node;
|
9423 |
|
|
dw_die_ref c;
|
9424 |
|
|
dw_die_ref first;
|
9425 |
|
|
dw_die_ref prev = NULL;
|
9426 |
|
|
dw_die_ref next = NULL;
|
9427 |
|
|
|
9428 |
|
|
node.parent = parent;
|
9429 |
|
|
|
9430 |
|
|
first = c = parent->old_die->die_child;
|
9431 |
|
|
if (c)
|
9432 |
|
|
next = c->die_sib;
|
9433 |
|
|
if (c) do {
|
9434 |
|
|
if (prev == NULL || prev->die_sib == c)
|
9435 |
|
|
prev = c;
|
9436 |
|
|
c = next;
|
9437 |
|
|
next = (c == first ? NULL : c->die_sib);
|
9438 |
|
|
node.old_die = c;
|
9439 |
|
|
node.new_die = NULL;
|
9440 |
|
|
if (is_declaration_die (c))
|
9441 |
|
|
{
|
9442 |
|
|
/* Clone the existing DIE, move the original to the skeleton
|
9443 |
|
|
tree (which is in the main CU), and put the clone, with
|
9444 |
|
|
all the original's children, where the original came from. */
|
9445 |
|
|
dw_die_ref clone = clone_die (c);
|
9446 |
|
|
move_all_children (c, clone);
|
9447 |
|
|
|
9448 |
|
|
replace_child (c, clone, prev);
|
9449 |
|
|
generate_skeleton_ancestor_tree (parent);
|
9450 |
|
|
add_child_die (parent->new_die, c);
|
9451 |
|
|
node.new_die = c;
|
9452 |
|
|
c = clone;
|
9453 |
|
|
}
|
9454 |
|
|
generate_skeleton_bottom_up (&node);
|
9455 |
|
|
} while (next != NULL);
|
9456 |
|
|
}
|
9457 |
|
|
|
9458 |
|
|
/* Wrapper function for generate_skeleton_bottom_up. */
|
9459 |
|
|
|
9460 |
|
|
static dw_die_ref
|
9461 |
|
|
generate_skeleton (dw_die_ref die)
|
9462 |
|
|
{
|
9463 |
|
|
skeleton_chain_node node;
|
9464 |
|
|
|
9465 |
|
|
node.old_die = die;
|
9466 |
|
|
node.new_die = NULL;
|
9467 |
|
|
node.parent = NULL;
|
9468 |
|
|
|
9469 |
|
|
/* If this type definition is nested inside another type,
|
9470 |
|
|
always leave at least a declaration in its place. */
|
9471 |
|
|
if (die->die_parent != NULL && is_type_die (die->die_parent))
|
9472 |
|
|
node.new_die = clone_as_declaration (die);
|
9473 |
|
|
|
9474 |
|
|
generate_skeleton_bottom_up (&node);
|
9475 |
|
|
return node.new_die;
|
9476 |
|
|
}
|
9477 |
|
|
|
9478 |
|
|
/* Remove the DIE from its parent, possibly replacing it with a cloned
|
9479 |
|
|
declaration. The original DIE will be moved to a new compile unit
|
9480 |
|
|
so that existing references to it follow it to the new location. If
|
9481 |
|
|
any of the original DIE's descendants is a declaration, we need to
|
9482 |
|
|
replace the original DIE with a skeleton tree and move the
|
9483 |
|
|
declarations back into the skeleton tree. */
|
9484 |
|
|
|
9485 |
|
|
static dw_die_ref
|
9486 |
|
|
remove_child_or_replace_with_skeleton (dw_die_ref child, dw_die_ref prev)
|
9487 |
|
|
{
|
9488 |
|
|
dw_die_ref skeleton;
|
9489 |
|
|
|
9490 |
|
|
skeleton = generate_skeleton (child);
|
9491 |
|
|
if (skeleton == NULL)
|
9492 |
|
|
remove_child_with_prev (child, prev);
|
9493 |
|
|
else
|
9494 |
|
|
{
|
9495 |
|
|
skeleton->die_id.die_type_node = child->die_id.die_type_node;
|
9496 |
|
|
replace_child (child, skeleton, prev);
|
9497 |
|
|
}
|
9498 |
|
|
|
9499 |
|
|
return skeleton;
|
9500 |
|
|
}
|
9501 |
|
|
|
9502 |
|
|
/* Traverse the DIE and set up additional .debug_types sections for each
|
9503 |
|
|
type worthy of being placed in a COMDAT section. */
|
9504 |
|
|
|
9505 |
|
|
static void
|
9506 |
|
|
break_out_comdat_types (dw_die_ref die)
|
9507 |
|
|
{
|
9508 |
|
|
dw_die_ref c;
|
9509 |
|
|
dw_die_ref first;
|
9510 |
|
|
dw_die_ref prev = NULL;
|
9511 |
|
|
dw_die_ref next = NULL;
|
9512 |
|
|
dw_die_ref unit = NULL;
|
9513 |
|
|
|
9514 |
|
|
first = c = die->die_child;
|
9515 |
|
|
if (c)
|
9516 |
|
|
next = c->die_sib;
|
9517 |
|
|
if (c) do {
|
9518 |
|
|
if (prev == NULL || prev->die_sib == c)
|
9519 |
|
|
prev = c;
|
9520 |
|
|
c = next;
|
9521 |
|
|
next = (c == first ? NULL : c->die_sib);
|
9522 |
|
|
if (should_move_die_to_comdat (c))
|
9523 |
|
|
{
|
9524 |
|
|
dw_die_ref replacement;
|
9525 |
|
|
comdat_type_node_ref type_node;
|
9526 |
|
|
|
9527 |
|
|
/* Create a new type unit DIE as the root for the new tree, and
|
9528 |
|
|
add it to the list of comdat types. */
|
9529 |
|
|
unit = new_die (DW_TAG_type_unit, NULL, NULL);
|
9530 |
|
|
add_AT_unsigned (unit, DW_AT_language,
|
9531 |
|
|
get_AT_unsigned (comp_unit_die, DW_AT_language));
|
9532 |
|
|
type_node = GGC_CNEW (comdat_type_node);
|
9533 |
|
|
type_node->root_die = unit;
|
9534 |
|
|
type_node->next = comdat_type_list;
|
9535 |
|
|
comdat_type_list = type_node;
|
9536 |
|
|
|
9537 |
|
|
/* Generate the type signature. */
|
9538 |
|
|
generate_type_signature (c, type_node);
|
9539 |
|
|
|
9540 |
|
|
/* Copy the declaration context, attributes, and children of the
|
9541 |
|
|
declaration into the new compile unit DIE. */
|
9542 |
|
|
copy_declaration_context (unit, c);
|
9543 |
|
|
|
9544 |
|
|
/* Remove this DIE from the main CU. */
|
9545 |
|
|
replacement = remove_child_or_replace_with_skeleton (c, prev);
|
9546 |
|
|
|
9547 |
|
|
/* Break out nested types into their own type units. */
|
9548 |
|
|
break_out_comdat_types (c);
|
9549 |
|
|
|
9550 |
|
|
/* Add the DIE to the new compunit. */
|
9551 |
|
|
add_child_die (unit, c);
|
9552 |
|
|
|
9553 |
|
|
if (replacement != NULL)
|
9554 |
|
|
c = replacement;
|
9555 |
|
|
}
|
9556 |
|
|
else if (c->die_tag == DW_TAG_namespace
|
9557 |
|
|
|| c->die_tag == DW_TAG_class_type
|
9558 |
|
|
|| c->die_tag == DW_TAG_structure_type
|
9559 |
|
|
|| c->die_tag == DW_TAG_union_type)
|
9560 |
|
|
{
|
9561 |
|
|
/* Look for nested types that can be broken out. */
|
9562 |
|
|
break_out_comdat_types (c);
|
9563 |
|
|
}
|
9564 |
|
|
} while (next != NULL);
|
9565 |
|
|
}
|
9566 |
|
|
|
9567 |
|
|
/* Structure to map a DIE in one CU to its copy in a comdat type unit. */
|
9568 |
|
|
|
9569 |
|
|
struct decl_table_entry
|
9570 |
|
|
{
|
9571 |
|
|
dw_die_ref orig;
|
9572 |
|
|
dw_die_ref copy;
|
9573 |
|
|
};
|
9574 |
|
|
|
9575 |
|
|
/* Routines to manipulate hash table of copied declarations. */
|
9576 |
|
|
|
9577 |
|
|
static hashval_t
|
9578 |
|
|
htab_decl_hash (const void *of)
|
9579 |
|
|
{
|
9580 |
|
|
const struct decl_table_entry *const entry =
|
9581 |
|
|
(const struct decl_table_entry *) of;
|
9582 |
|
|
|
9583 |
|
|
return htab_hash_pointer (entry->orig);
|
9584 |
|
|
}
|
9585 |
|
|
|
9586 |
|
|
static int
|
9587 |
|
|
htab_decl_eq (const void *of1, const void *of2)
|
9588 |
|
|
{
|
9589 |
|
|
const struct decl_table_entry *const entry1 =
|
9590 |
|
|
(const struct decl_table_entry *) of1;
|
9591 |
|
|
const struct die_struct *const entry2 = (const struct die_struct *) of2;
|
9592 |
|
|
|
9593 |
|
|
return entry1->orig == entry2;
|
9594 |
|
|
}
|
9595 |
|
|
|
9596 |
|
|
static void
|
9597 |
|
|
htab_decl_del (void *what)
|
9598 |
|
|
{
|
9599 |
|
|
struct decl_table_entry *entry = (struct decl_table_entry *) what;
|
9600 |
|
|
|
9601 |
|
|
free (entry);
|
9602 |
|
|
}
|
9603 |
|
|
|
9604 |
|
|
/* Copy DIE and its ancestors, up to, but not including, the compile unit
|
9605 |
|
|
or type unit entry, to a new tree. Adds the new tree to UNIT and returns
|
9606 |
|
|
a pointer to the copy of DIE. If DECL_TABLE is provided, it is used
|
9607 |
|
|
to check if the ancestor has already been copied into UNIT. */
|
9608 |
|
|
|
9609 |
|
|
static dw_die_ref
|
9610 |
|
|
copy_ancestor_tree (dw_die_ref unit, dw_die_ref die, htab_t decl_table)
|
9611 |
|
|
{
|
9612 |
|
|
dw_die_ref parent = die->die_parent;
|
9613 |
|
|
dw_die_ref new_parent = unit;
|
9614 |
|
|
dw_die_ref copy;
|
9615 |
|
|
void **slot = NULL;
|
9616 |
|
|
struct decl_table_entry *entry = NULL;
|
9617 |
|
|
|
9618 |
|
|
if (decl_table)
|
9619 |
|
|
{
|
9620 |
|
|
/* Check if the entry has already been copied to UNIT. */
|
9621 |
|
|
slot = htab_find_slot_with_hash (decl_table, die,
|
9622 |
|
|
htab_hash_pointer (die), INSERT);
|
9623 |
|
|
if (*slot != HTAB_EMPTY_ENTRY)
|
9624 |
|
|
{
|
9625 |
|
|
entry = (struct decl_table_entry *) *slot;
|
9626 |
|
|
return entry->copy;
|
9627 |
|
|
}
|
9628 |
|
|
|
9629 |
|
|
/* Record in DECL_TABLE that DIE has been copied to UNIT. */
|
9630 |
|
|
entry = XCNEW (struct decl_table_entry);
|
9631 |
|
|
entry->orig = die;
|
9632 |
|
|
entry->copy = NULL;
|
9633 |
|
|
*slot = entry;
|
9634 |
|
|
}
|
9635 |
|
|
|
9636 |
|
|
if (parent != NULL)
|
9637 |
|
|
{
|
9638 |
|
|
dw_die_ref spec = get_AT_ref (parent, DW_AT_specification);
|
9639 |
|
|
if (spec != NULL)
|
9640 |
|
|
parent = spec;
|
9641 |
|
|
if (parent->die_tag != DW_TAG_compile_unit
|
9642 |
|
|
&& parent->die_tag != DW_TAG_type_unit)
|
9643 |
|
|
new_parent = copy_ancestor_tree (unit, parent, decl_table);
|
9644 |
|
|
}
|
9645 |
|
|
|
9646 |
|
|
copy = clone_as_declaration (die);
|
9647 |
|
|
add_child_die (new_parent, copy);
|
9648 |
|
|
|
9649 |
|
|
if (decl_table != NULL)
|
9650 |
|
|
{
|
9651 |
|
|
/* Make sure the copy is marked as part of the type unit. */
|
9652 |
|
|
copy->die_mark = 1;
|
9653 |
|
|
/* Record the pointer to the copy. */
|
9654 |
|
|
entry->copy = copy;
|
9655 |
|
|
}
|
9656 |
|
|
|
9657 |
|
|
return copy;
|
9658 |
|
|
}
|
9659 |
|
|
|
9660 |
|
|
/* Walk the DIE and its children, looking for references to incomplete
|
9661 |
|
|
or trivial types that are unmarked (i.e., that are not in the current
|
9662 |
|
|
type_unit). */
|
9663 |
|
|
|
9664 |
|
|
static void
|
9665 |
|
|
copy_decls_walk (dw_die_ref unit, dw_die_ref die, htab_t decl_table)
|
9666 |
|
|
{
|
9667 |
|
|
dw_die_ref c;
|
9668 |
|
|
dw_attr_ref a;
|
9669 |
|
|
unsigned ix;
|
9670 |
|
|
|
9671 |
|
|
for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
|
9672 |
|
|
{
|
9673 |
|
|
if (AT_class (a) == dw_val_class_die_ref)
|
9674 |
|
|
{
|
9675 |
|
|
dw_die_ref targ = AT_ref (a);
|
9676 |
|
|
comdat_type_node_ref type_node = targ->die_id.die_type_node;
|
9677 |
|
|
void **slot;
|
9678 |
|
|
struct decl_table_entry *entry;
|
9679 |
|
|
|
9680 |
|
|
if (targ->die_mark != 0 || type_node != NULL)
|
9681 |
|
|
continue;
|
9682 |
|
|
|
9683 |
|
|
slot = htab_find_slot_with_hash (decl_table, targ,
|
9684 |
|
|
htab_hash_pointer (targ), INSERT);
|
9685 |
|
|
|
9686 |
|
|
if (*slot != HTAB_EMPTY_ENTRY)
|
9687 |
|
|
{
|
9688 |
|
|
/* TARG has already been copied, so we just need to
|
9689 |
|
|
modify the reference to point to the copy. */
|
9690 |
|
|
entry = (struct decl_table_entry *) *slot;
|
9691 |
|
|
a->dw_attr_val.v.val_die_ref.die = entry->copy;
|
9692 |
|
|
}
|
9693 |
|
|
else
|
9694 |
|
|
{
|
9695 |
|
|
dw_die_ref parent = unit;
|
9696 |
|
|
dw_die_ref copy = clone_tree (targ);
|
9697 |
|
|
|
9698 |
|
|
/* Make sure the cloned tree is marked as part of the
|
9699 |
|
|
type unit. */
|
9700 |
|
|
mark_dies (copy);
|
9701 |
|
|
|
9702 |
|
|
/* Record in DECL_TABLE that TARG has been copied.
|
9703 |
|
|
Need to do this now, before the recursive call,
|
9704 |
|
|
because DECL_TABLE may be expanded and SLOT
|
9705 |
|
|
would no longer be a valid pointer. */
|
9706 |
|
|
entry = XCNEW (struct decl_table_entry);
|
9707 |
|
|
entry->orig = targ;
|
9708 |
|
|
entry->copy = copy;
|
9709 |
|
|
*slot = entry;
|
9710 |
|
|
|
9711 |
|
|
/* If TARG has surrounding context, copy its ancestor tree
|
9712 |
|
|
into the new type unit. */
|
9713 |
|
|
if (targ->die_parent != NULL
|
9714 |
|
|
&& targ->die_parent->die_tag != DW_TAG_compile_unit
|
9715 |
|
|
&& targ->die_parent->die_tag != DW_TAG_type_unit)
|
9716 |
|
|
parent = copy_ancestor_tree (unit, targ->die_parent,
|
9717 |
|
|
decl_table);
|
9718 |
|
|
|
9719 |
|
|
add_child_die (parent, copy);
|
9720 |
|
|
a->dw_attr_val.v.val_die_ref.die = copy;
|
9721 |
|
|
|
9722 |
|
|
/* Make sure the newly-copied DIE is walked. If it was
|
9723 |
|
|
installed in a previously-added context, it won't
|
9724 |
|
|
get visited otherwise. */
|
9725 |
|
|
if (parent != unit)
|
9726 |
|
|
copy_decls_walk (unit, parent, decl_table);
|
9727 |
|
|
}
|
9728 |
|
|
}
|
9729 |
|
|
}
|
9730 |
|
|
|
9731 |
|
|
FOR_EACH_CHILD (die, c, copy_decls_walk (unit, c, decl_table));
|
9732 |
|
|
}
|
9733 |
|
|
|
9734 |
|
|
/* Copy declarations for "unworthy" types into the new comdat section.
|
9735 |
|
|
Incomplete types, modified types, and certain other types aren't broken
|
9736 |
|
|
out into comdat sections of their own, so they don't have a signature,
|
9737 |
|
|
and we need to copy the declaration into the same section so that we
|
9738 |
|
|
don't have an external reference. */
|
9739 |
|
|
|
9740 |
|
|
static void
|
9741 |
|
|
copy_decls_for_unworthy_types (dw_die_ref unit)
|
9742 |
|
|
{
|
9743 |
|
|
htab_t decl_table;
|
9744 |
|
|
|
9745 |
|
|
mark_dies (unit);
|
9746 |
|
|
decl_table = htab_create (10, htab_decl_hash, htab_decl_eq, htab_decl_del);
|
9747 |
|
|
copy_decls_walk (unit, unit, decl_table);
|
9748 |
|
|
htab_delete (decl_table);
|
9749 |
|
|
unmark_dies (unit);
|
9750 |
|
|
}
|
9751 |
|
|
|
9752 |
|
|
/* Traverse the DIE and add a sibling attribute if it may have the
|
9753 |
|
|
effect of speeding up access to siblings. To save some space,
|
9754 |
|
|
avoid generating sibling attributes for DIE's without children. */
|
9755 |
|
|
|
9756 |
|
|
static void
|
9757 |
|
|
add_sibling_attributes (dw_die_ref die)
|
9758 |
|
|
{
|
9759 |
|
|
dw_die_ref c;
|
9760 |
|
|
|
9761 |
|
|
if (! die->die_child)
|
9762 |
|
|
return;
|
9763 |
|
|
|
9764 |
|
|
if (die->die_parent && die != die->die_parent->die_child)
|
9765 |
|
|
add_AT_die_ref (die, DW_AT_sibling, die->die_sib);
|
9766 |
|
|
|
9767 |
|
|
FOR_EACH_CHILD (die, c, add_sibling_attributes (c));
|
9768 |
|
|
}
|
9769 |
|
|
|
9770 |
|
|
/* Output all location lists for the DIE and its children. */
|
9771 |
|
|
|
9772 |
|
|
static void
|
9773 |
|
|
output_location_lists (dw_die_ref die)
|
9774 |
|
|
{
|
9775 |
|
|
dw_die_ref c;
|
9776 |
|
|
dw_attr_ref a;
|
9777 |
|
|
unsigned ix;
|
9778 |
|
|
|
9779 |
|
|
for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
|
9780 |
|
|
if (AT_class (a) == dw_val_class_loc_list)
|
9781 |
|
|
output_loc_list (AT_loc_list (a));
|
9782 |
|
|
|
9783 |
|
|
FOR_EACH_CHILD (die, c, output_location_lists (c));
|
9784 |
|
|
}
|
9785 |
|
|
|
9786 |
|
|
/* The format of each DIE (and its attribute value pairs) is encoded in an
|
9787 |
|
|
abbreviation table. This routine builds the abbreviation table and assigns
|
9788 |
|
|
a unique abbreviation id for each abbreviation entry. The children of each
|
9789 |
|
|
die are visited recursively. */
|
9790 |
|
|
|
9791 |
|
|
static void
|
9792 |
|
|
build_abbrev_table (dw_die_ref die)
|
9793 |
|
|
{
|
9794 |
|
|
unsigned long abbrev_id;
|
9795 |
|
|
unsigned int n_alloc;
|
9796 |
|
|
dw_die_ref c;
|
9797 |
|
|
dw_attr_ref a;
|
9798 |
|
|
unsigned ix;
|
9799 |
|
|
|
9800 |
|
|
/* Scan the DIE references, and mark as external any that refer to
|
9801 |
|
|
DIEs from other CUs (i.e. those which are not marked). */
|
9802 |
|
|
for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
|
9803 |
|
|
if (AT_class (a) == dw_val_class_die_ref
|
9804 |
|
|
&& AT_ref (a)->die_mark == 0)
|
9805 |
|
|
{
|
9806 |
|
|
gcc_assert (dwarf_version >= 4 || AT_ref (a)->die_id.die_symbol);
|
9807 |
|
|
set_AT_ref_external (a, 1);
|
9808 |
|
|
}
|
9809 |
|
|
|
9810 |
|
|
for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id)
|
9811 |
|
|
{
|
9812 |
|
|
dw_die_ref abbrev = abbrev_die_table[abbrev_id];
|
9813 |
|
|
dw_attr_ref die_a, abbrev_a;
|
9814 |
|
|
unsigned ix;
|
9815 |
|
|
bool ok = true;
|
9816 |
|
|
|
9817 |
|
|
if (abbrev->die_tag != die->die_tag)
|
9818 |
|
|
continue;
|
9819 |
|
|
if ((abbrev->die_child != NULL) != (die->die_child != NULL))
|
9820 |
|
|
continue;
|
9821 |
|
|
|
9822 |
|
|
if (VEC_length (dw_attr_node, abbrev->die_attr)
|
9823 |
|
|
!= VEC_length (dw_attr_node, die->die_attr))
|
9824 |
|
|
continue;
|
9825 |
|
|
|
9826 |
|
|
for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, die_a); ix++)
|
9827 |
|
|
{
|
9828 |
|
|
abbrev_a = VEC_index (dw_attr_node, abbrev->die_attr, ix);
|
9829 |
|
|
if ((abbrev_a->dw_attr != die_a->dw_attr)
|
9830 |
|
|
|| (value_format (abbrev_a) != value_format (die_a)))
|
9831 |
|
|
{
|
9832 |
|
|
ok = false;
|
9833 |
|
|
break;
|
9834 |
|
|
}
|
9835 |
|
|
}
|
9836 |
|
|
if (ok)
|
9837 |
|
|
break;
|
9838 |
|
|
}
|
9839 |
|
|
|
9840 |
|
|
if (abbrev_id >= abbrev_die_table_in_use)
|
9841 |
|
|
{
|
9842 |
|
|
if (abbrev_die_table_in_use >= abbrev_die_table_allocated)
|
9843 |
|
|
{
|
9844 |
|
|
n_alloc = abbrev_die_table_allocated + ABBREV_DIE_TABLE_INCREMENT;
|
9845 |
|
|
abbrev_die_table = GGC_RESIZEVEC (dw_die_ref, abbrev_die_table,
|
9846 |
|
|
n_alloc);
|
9847 |
|
|
|
9848 |
|
|
memset (&abbrev_die_table[abbrev_die_table_allocated], 0,
|
9849 |
|
|
(n_alloc - abbrev_die_table_allocated) * sizeof (dw_die_ref));
|
9850 |
|
|
abbrev_die_table_allocated = n_alloc;
|
9851 |
|
|
}
|
9852 |
|
|
|
9853 |
|
|
++abbrev_die_table_in_use;
|
9854 |
|
|
abbrev_die_table[abbrev_id] = die;
|
9855 |
|
|
}
|
9856 |
|
|
|
9857 |
|
|
die->die_abbrev = abbrev_id;
|
9858 |
|
|
FOR_EACH_CHILD (die, c, build_abbrev_table (c));
|
9859 |
|
|
}
|
9860 |
|
|
|
9861 |
|
|
/* Return the power-of-two number of bytes necessary to represent VALUE. */
|
9862 |
|
|
|
9863 |
|
|
static int
|
9864 |
|
|
constant_size (unsigned HOST_WIDE_INT value)
|
9865 |
|
|
{
|
9866 |
|
|
int log;
|
9867 |
|
|
|
9868 |
|
|
if (value == 0)
|
9869 |
|
|
log = 0;
|
9870 |
|
|
else
|
9871 |
|
|
log = floor_log2 (value);
|
9872 |
|
|
|
9873 |
|
|
log = log / 8;
|
9874 |
|
|
log = 1 << (floor_log2 (log) + 1);
|
9875 |
|
|
|
9876 |
|
|
return log;
|
9877 |
|
|
}
|
9878 |
|
|
|
9879 |
|
|
/* Return the size of a DIE as it is represented in the
|
9880 |
|
|
.debug_info section. */
|
9881 |
|
|
|
9882 |
|
|
static unsigned long
|
9883 |
|
|
size_of_die (dw_die_ref die)
|
9884 |
|
|
{
|
9885 |
|
|
unsigned long size = 0;
|
9886 |
|
|
dw_attr_ref a;
|
9887 |
|
|
unsigned ix;
|
9888 |
|
|
|
9889 |
|
|
size += size_of_uleb128 (die->die_abbrev);
|
9890 |
|
|
for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
|
9891 |
|
|
{
|
9892 |
|
|
switch (AT_class (a))
|
9893 |
|
|
{
|
9894 |
|
|
case dw_val_class_addr:
|
9895 |
|
|
size += DWARF2_ADDR_SIZE;
|
9896 |
|
|
break;
|
9897 |
|
|
case dw_val_class_offset:
|
9898 |
|
|
size += DWARF_OFFSET_SIZE;
|
9899 |
|
|
break;
|
9900 |
|
|
case dw_val_class_loc:
|
9901 |
|
|
{
|
9902 |
|
|
unsigned long lsize = size_of_locs (AT_loc (a));
|
9903 |
|
|
|
9904 |
|
|
/* Block length. */
|
9905 |
|
|
if (dwarf_version >= 4)
|
9906 |
|
|
size += size_of_uleb128 (lsize);
|
9907 |
|
|
else
|
9908 |
|
|
size += constant_size (lsize);
|
9909 |
|
|
size += lsize;
|
9910 |
|
|
}
|
9911 |
|
|
break;
|
9912 |
|
|
case dw_val_class_loc_list:
|
9913 |
|
|
size += DWARF_OFFSET_SIZE;
|
9914 |
|
|
break;
|
9915 |
|
|
case dw_val_class_range_list:
|
9916 |
|
|
size += DWARF_OFFSET_SIZE;
|
9917 |
|
|
break;
|
9918 |
|
|
case dw_val_class_const:
|
9919 |
|
|
size += size_of_sleb128 (AT_int (a));
|
9920 |
|
|
break;
|
9921 |
|
|
case dw_val_class_unsigned_const:
|
9922 |
|
|
size += constant_size (AT_unsigned (a));
|
9923 |
|
|
break;
|
9924 |
|
|
case dw_val_class_const_double:
|
9925 |
|
|
size += 2 * HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
|
9926 |
|
|
if (HOST_BITS_PER_WIDE_INT >= 64)
|
9927 |
|
|
size++; /* block */
|
9928 |
|
|
break;
|
9929 |
|
|
case dw_val_class_vec:
|
9930 |
|
|
size += constant_size (a->dw_attr_val.v.val_vec.length
|
9931 |
|
|
* a->dw_attr_val.v.val_vec.elt_size)
|
9932 |
|
|
+ a->dw_attr_val.v.val_vec.length
|
9933 |
|
|
* a->dw_attr_val.v.val_vec.elt_size; /* block */
|
9934 |
|
|
break;
|
9935 |
|
|
case dw_val_class_flag:
|
9936 |
|
|
if (dwarf_version >= 4)
|
9937 |
|
|
/* Currently all add_AT_flag calls pass in 1 as last argument,
|
9938 |
|
|
so DW_FORM_flag_present can be used. If that ever changes,
|
9939 |
|
|
we'll need to use DW_FORM_flag and have some optimization
|
9940 |
|
|
in build_abbrev_table that will change those to
|
9941 |
|
|
DW_FORM_flag_present if it is set to 1 in all DIEs using
|
9942 |
|
|
the same abbrev entry. */
|
9943 |
|
|
gcc_assert (a->dw_attr_val.v.val_flag == 1);
|
9944 |
|
|
else
|
9945 |
|
|
size += 1;
|
9946 |
|
|
break;
|
9947 |
|
|
case dw_val_class_die_ref:
|
9948 |
|
|
if (AT_ref_external (a))
|
9949 |
|
|
{
|
9950 |
|
|
/* In DWARF4, we use DW_FORM_sig8; for earlier versions
|
9951 |
|
|
we use DW_FORM_ref_addr. In DWARF2, DW_FORM_ref_addr
|
9952 |
|
|
is sized by target address length, whereas in DWARF3
|
9953 |
|
|
it's always sized as an offset. */
|
9954 |
|
|
if (dwarf_version >= 4)
|
9955 |
|
|
size += DWARF_TYPE_SIGNATURE_SIZE;
|
9956 |
|
|
else if (dwarf_version == 2)
|
9957 |
|
|
size += DWARF2_ADDR_SIZE;
|
9958 |
|
|
else
|
9959 |
|
|
size += DWARF_OFFSET_SIZE;
|
9960 |
|
|
}
|
9961 |
|
|
else
|
9962 |
|
|
size += DWARF_OFFSET_SIZE;
|
9963 |
|
|
break;
|
9964 |
|
|
case dw_val_class_fde_ref:
|
9965 |
|
|
size += DWARF_OFFSET_SIZE;
|
9966 |
|
|
break;
|
9967 |
|
|
case dw_val_class_lbl_id:
|
9968 |
|
|
size += DWARF2_ADDR_SIZE;
|
9969 |
|
|
break;
|
9970 |
|
|
case dw_val_class_lineptr:
|
9971 |
|
|
case dw_val_class_macptr:
|
9972 |
|
|
size += DWARF_OFFSET_SIZE;
|
9973 |
|
|
break;
|
9974 |
|
|
case dw_val_class_str:
|
9975 |
|
|
if (AT_string_form (a) == DW_FORM_strp)
|
9976 |
|
|
size += DWARF_OFFSET_SIZE;
|
9977 |
|
|
else
|
9978 |
|
|
size += strlen (a->dw_attr_val.v.val_str->str) + 1;
|
9979 |
|
|
break;
|
9980 |
|
|
case dw_val_class_file:
|
9981 |
|
|
size += constant_size (maybe_emit_file (a->dw_attr_val.v.val_file));
|
9982 |
|
|
break;
|
9983 |
|
|
case dw_val_class_data8:
|
9984 |
|
|
size += 8;
|
9985 |
|
|
break;
|
9986 |
|
|
default:
|
9987 |
|
|
gcc_unreachable ();
|
9988 |
|
|
}
|
9989 |
|
|
}
|
9990 |
|
|
|
9991 |
|
|
return size;
|
9992 |
|
|
}
|
9993 |
|
|
|
9994 |
|
|
/* Size the debugging information associated with a given DIE. Visits the
|
9995 |
|
|
DIE's children recursively. Updates the global variable next_die_offset, on
|
9996 |
|
|
each time through. Uses the current value of next_die_offset to update the
|
9997 |
|
|
die_offset field in each DIE. */
|
9998 |
|
|
|
9999 |
|
|
static void
|
10000 |
|
|
calc_die_sizes (dw_die_ref die)
|
10001 |
|
|
{
|
10002 |
|
|
dw_die_ref c;
|
10003 |
|
|
|
10004 |
|
|
die->die_offset = next_die_offset;
|
10005 |
|
|
next_die_offset += size_of_die (die);
|
10006 |
|
|
|
10007 |
|
|
FOR_EACH_CHILD (die, c, calc_die_sizes (c));
|
10008 |
|
|
|
10009 |
|
|
if (die->die_child != NULL)
|
10010 |
|
|
/* Count the null byte used to terminate sibling lists. */
|
10011 |
|
|
next_die_offset += 1;
|
10012 |
|
|
}
|
10013 |
|
|
|
10014 |
|
|
/* Set the marks for a die and its children. We do this so
|
10015 |
|
|
that we know whether or not a reference needs to use FORM_ref_addr; only
|
10016 |
|
|
DIEs in the same CU will be marked. We used to clear out the offset
|
10017 |
|
|
and use that as the flag, but ran into ordering problems. */
|
10018 |
|
|
|
10019 |
|
|
static void
|
10020 |
|
|
mark_dies (dw_die_ref die)
|
10021 |
|
|
{
|
10022 |
|
|
dw_die_ref c;
|
10023 |
|
|
|
10024 |
|
|
gcc_assert (!die->die_mark);
|
10025 |
|
|
|
10026 |
|
|
die->die_mark = 1;
|
10027 |
|
|
FOR_EACH_CHILD (die, c, mark_dies (c));
|
10028 |
|
|
}
|
10029 |
|
|
|
10030 |
|
|
/* Clear the marks for a die and its children. */
|
10031 |
|
|
|
10032 |
|
|
static void
|
10033 |
|
|
unmark_dies (dw_die_ref die)
|
10034 |
|
|
{
|
10035 |
|
|
dw_die_ref c;
|
10036 |
|
|
|
10037 |
|
|
if (dwarf_version < 4)
|
10038 |
|
|
gcc_assert (die->die_mark);
|
10039 |
|
|
|
10040 |
|
|
die->die_mark = 0;
|
10041 |
|
|
FOR_EACH_CHILD (die, c, unmark_dies (c));
|
10042 |
|
|
}
|
10043 |
|
|
|
10044 |
|
|
/* Clear the marks for a die, its children and referred dies. */
|
10045 |
|
|
|
10046 |
|
|
static void
|
10047 |
|
|
unmark_all_dies (dw_die_ref die)
|
10048 |
|
|
{
|
10049 |
|
|
dw_die_ref c;
|
10050 |
|
|
dw_attr_ref a;
|
10051 |
|
|
unsigned ix;
|
10052 |
|
|
|
10053 |
|
|
if (!die->die_mark)
|
10054 |
|
|
return;
|
10055 |
|
|
die->die_mark = 0;
|
10056 |
|
|
|
10057 |
|
|
FOR_EACH_CHILD (die, c, unmark_all_dies (c));
|
10058 |
|
|
|
10059 |
|
|
for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
|
10060 |
|
|
if (AT_class (a) == dw_val_class_die_ref)
|
10061 |
|
|
unmark_all_dies (AT_ref (a));
|
10062 |
|
|
}
|
10063 |
|
|
|
10064 |
|
|
/* Return the size of the .debug_pubnames or .debug_pubtypes table
|
10065 |
|
|
generated for the compilation unit. */
|
10066 |
|
|
|
10067 |
|
|
static unsigned long
|
10068 |
|
|
size_of_pubnames (VEC (pubname_entry, gc) * names)
|
10069 |
|
|
{
|
10070 |
|
|
unsigned long size;
|
10071 |
|
|
unsigned i;
|
10072 |
|
|
pubname_ref p;
|
10073 |
|
|
|
10074 |
|
|
size = DWARF_PUBNAMES_HEADER_SIZE;
|
10075 |
|
|
for (i = 0; VEC_iterate (pubname_entry, names, i, p); i++)
|
10076 |
|
|
if (names != pubtype_table
|
10077 |
|
|
|| p->die->die_offset != 0
|
10078 |
|
|
|| !flag_eliminate_unused_debug_types)
|
10079 |
|
|
size += strlen (p->name) + DWARF_OFFSET_SIZE + 1;
|
10080 |
|
|
|
10081 |
|
|
size += DWARF_OFFSET_SIZE;
|
10082 |
|
|
return size;
|
10083 |
|
|
}
|
10084 |
|
|
|
10085 |
|
|
/* Return the size of the information in the .debug_aranges section. */
|
10086 |
|
|
|
10087 |
|
|
static unsigned long
|
10088 |
|
|
size_of_aranges (void)
|
10089 |
|
|
{
|
10090 |
|
|
unsigned long size;
|
10091 |
|
|
|
10092 |
|
|
size = DWARF_ARANGES_HEADER_SIZE;
|
10093 |
|
|
|
10094 |
|
|
/* Count the address/length pair for this compilation unit. */
|
10095 |
|
|
if (text_section_used)
|
10096 |
|
|
size += 2 * DWARF2_ADDR_SIZE;
|
10097 |
|
|
if (cold_text_section_used)
|
10098 |
|
|
size += 2 * DWARF2_ADDR_SIZE;
|
10099 |
|
|
size += 2 * DWARF2_ADDR_SIZE * arange_table_in_use;
|
10100 |
|
|
|
10101 |
|
|
/* Count the two zero words used to terminated the address range table. */
|
10102 |
|
|
size += 2 * DWARF2_ADDR_SIZE;
|
10103 |
|
|
return size;
|
10104 |
|
|
}
|
10105 |
|
|
|
10106 |
|
|
/* Select the encoding of an attribute value. */
|
10107 |
|
|
|
10108 |
|
|
static enum dwarf_form
|
10109 |
|
|
value_format (dw_attr_ref a)
|
10110 |
|
|
{
|
10111 |
|
|
switch (a->dw_attr_val.val_class)
|
10112 |
|
|
{
|
10113 |
|
|
case dw_val_class_addr:
|
10114 |
|
|
/* Only very few attributes allow DW_FORM_addr. */
|
10115 |
|
|
switch (a->dw_attr)
|
10116 |
|
|
{
|
10117 |
|
|
case DW_AT_low_pc:
|
10118 |
|
|
case DW_AT_high_pc:
|
10119 |
|
|
case DW_AT_entry_pc:
|
10120 |
|
|
case DW_AT_trampoline:
|
10121 |
|
|
return DW_FORM_addr;
|
10122 |
|
|
default:
|
10123 |
|
|
break;
|
10124 |
|
|
}
|
10125 |
|
|
switch (DWARF2_ADDR_SIZE)
|
10126 |
|
|
{
|
10127 |
|
|
case 1:
|
10128 |
|
|
return DW_FORM_data1;
|
10129 |
|
|
case 2:
|
10130 |
|
|
return DW_FORM_data2;
|
10131 |
|
|
case 4:
|
10132 |
|
|
return DW_FORM_data4;
|
10133 |
|
|
case 8:
|
10134 |
|
|
return DW_FORM_data8;
|
10135 |
|
|
default:
|
10136 |
|
|
gcc_unreachable ();
|
10137 |
|
|
}
|
10138 |
|
|
case dw_val_class_range_list:
|
10139 |
|
|
case dw_val_class_loc_list:
|
10140 |
|
|
if (dwarf_version >= 4)
|
10141 |
|
|
return DW_FORM_sec_offset;
|
10142 |
|
|
/* FALLTHRU */
|
10143 |
|
|
case dw_val_class_offset:
|
10144 |
|
|
switch (DWARF_OFFSET_SIZE)
|
10145 |
|
|
{
|
10146 |
|
|
case 4:
|
10147 |
|
|
return DW_FORM_data4;
|
10148 |
|
|
case 8:
|
10149 |
|
|
return DW_FORM_data8;
|
10150 |
|
|
default:
|
10151 |
|
|
gcc_unreachable ();
|
10152 |
|
|
}
|
10153 |
|
|
case dw_val_class_loc:
|
10154 |
|
|
if (dwarf_version >= 4)
|
10155 |
|
|
return DW_FORM_exprloc;
|
10156 |
|
|
switch (constant_size (size_of_locs (AT_loc (a))))
|
10157 |
|
|
{
|
10158 |
|
|
case 1:
|
10159 |
|
|
return DW_FORM_block1;
|
10160 |
|
|
case 2:
|
10161 |
|
|
return DW_FORM_block2;
|
10162 |
|
|
default:
|
10163 |
|
|
gcc_unreachable ();
|
10164 |
|
|
}
|
10165 |
|
|
case dw_val_class_const:
|
10166 |
|
|
return DW_FORM_sdata;
|
10167 |
|
|
case dw_val_class_unsigned_const:
|
10168 |
|
|
switch (constant_size (AT_unsigned (a)))
|
10169 |
|
|
{
|
10170 |
|
|
case 1:
|
10171 |
|
|
return DW_FORM_data1;
|
10172 |
|
|
case 2:
|
10173 |
|
|
return DW_FORM_data2;
|
10174 |
|
|
case 4:
|
10175 |
|
|
return DW_FORM_data4;
|
10176 |
|
|
case 8:
|
10177 |
|
|
return DW_FORM_data8;
|
10178 |
|
|
default:
|
10179 |
|
|
gcc_unreachable ();
|
10180 |
|
|
}
|
10181 |
|
|
case dw_val_class_const_double:
|
10182 |
|
|
switch (HOST_BITS_PER_WIDE_INT)
|
10183 |
|
|
{
|
10184 |
|
|
case 8:
|
10185 |
|
|
return DW_FORM_data2;
|
10186 |
|
|
case 16:
|
10187 |
|
|
return DW_FORM_data4;
|
10188 |
|
|
case 32:
|
10189 |
|
|
return DW_FORM_data8;
|
10190 |
|
|
case 64:
|
10191 |
|
|
default:
|
10192 |
|
|
return DW_FORM_block1;
|
10193 |
|
|
}
|
10194 |
|
|
case dw_val_class_vec:
|
10195 |
|
|
switch (constant_size (a->dw_attr_val.v.val_vec.length
|
10196 |
|
|
* a->dw_attr_val.v.val_vec.elt_size))
|
10197 |
|
|
{
|
10198 |
|
|
case 1:
|
10199 |
|
|
return DW_FORM_block1;
|
10200 |
|
|
case 2:
|
10201 |
|
|
return DW_FORM_block2;
|
10202 |
|
|
case 4:
|
10203 |
|
|
return DW_FORM_block4;
|
10204 |
|
|
default:
|
10205 |
|
|
gcc_unreachable ();
|
10206 |
|
|
}
|
10207 |
|
|
case dw_val_class_flag:
|
10208 |
|
|
if (dwarf_version >= 4)
|
10209 |
|
|
{
|
10210 |
|
|
/* Currently all add_AT_flag calls pass in 1 as last argument,
|
10211 |
|
|
so DW_FORM_flag_present can be used. If that ever changes,
|
10212 |
|
|
we'll need to use DW_FORM_flag and have some optimization
|
10213 |
|
|
in build_abbrev_table that will change those to
|
10214 |
|
|
DW_FORM_flag_present if it is set to 1 in all DIEs using
|
10215 |
|
|
the same abbrev entry. */
|
10216 |
|
|
gcc_assert (a->dw_attr_val.v.val_flag == 1);
|
10217 |
|
|
return DW_FORM_flag_present;
|
10218 |
|
|
}
|
10219 |
|
|
return DW_FORM_flag;
|
10220 |
|
|
case dw_val_class_die_ref:
|
10221 |
|
|
if (AT_ref_external (a))
|
10222 |
|
|
return dwarf_version >= 4 ? DW_FORM_sig8 : DW_FORM_ref_addr;
|
10223 |
|
|
else
|
10224 |
|
|
return DW_FORM_ref;
|
10225 |
|
|
case dw_val_class_fde_ref:
|
10226 |
|
|
return DW_FORM_data;
|
10227 |
|
|
case dw_val_class_lbl_id:
|
10228 |
|
|
return DW_FORM_addr;
|
10229 |
|
|
case dw_val_class_lineptr:
|
10230 |
|
|
case dw_val_class_macptr:
|
10231 |
|
|
return dwarf_version >= 4 ? DW_FORM_sec_offset : DW_FORM_data;
|
10232 |
|
|
case dw_val_class_str:
|
10233 |
|
|
return AT_string_form (a);
|
10234 |
|
|
case dw_val_class_file:
|
10235 |
|
|
switch (constant_size (maybe_emit_file (a->dw_attr_val.v.val_file)))
|
10236 |
|
|
{
|
10237 |
|
|
case 1:
|
10238 |
|
|
return DW_FORM_data1;
|
10239 |
|
|
case 2:
|
10240 |
|
|
return DW_FORM_data2;
|
10241 |
|
|
case 4:
|
10242 |
|
|
return DW_FORM_data4;
|
10243 |
|
|
default:
|
10244 |
|
|
gcc_unreachable ();
|
10245 |
|
|
}
|
10246 |
|
|
|
10247 |
|
|
case dw_val_class_data8:
|
10248 |
|
|
return DW_FORM_data8;
|
10249 |
|
|
|
10250 |
|
|
default:
|
10251 |
|
|
gcc_unreachable ();
|
10252 |
|
|
}
|
10253 |
|
|
}
|
10254 |
|
|
|
10255 |
|
|
/* Output the encoding of an attribute value. */
|
10256 |
|
|
|
10257 |
|
|
static void
|
10258 |
|
|
output_value_format (dw_attr_ref a)
|
10259 |
|
|
{
|
10260 |
|
|
enum dwarf_form form = value_format (a);
|
10261 |
|
|
|
10262 |
|
|
dw2_asm_output_data_uleb128 (form, "(%s)", dwarf_form_name (form));
|
10263 |
|
|
}
|
10264 |
|
|
|
10265 |
|
|
/* Output the .debug_abbrev section which defines the DIE abbreviation
|
10266 |
|
|
table. */
|
10267 |
|
|
|
10268 |
|
|
static void
|
10269 |
|
|
output_abbrev_section (void)
|
10270 |
|
|
{
|
10271 |
|
|
unsigned long abbrev_id;
|
10272 |
|
|
|
10273 |
|
|
for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id)
|
10274 |
|
|
{
|
10275 |
|
|
dw_die_ref abbrev = abbrev_die_table[abbrev_id];
|
10276 |
|
|
unsigned ix;
|
10277 |
|
|
dw_attr_ref a_attr;
|
10278 |
|
|
|
10279 |
|
|
dw2_asm_output_data_uleb128 (abbrev_id, "(abbrev code)");
|
10280 |
|
|
dw2_asm_output_data_uleb128 (abbrev->die_tag, "(TAG: %s)",
|
10281 |
|
|
dwarf_tag_name (abbrev->die_tag));
|
10282 |
|
|
|
10283 |
|
|
if (abbrev->die_child != NULL)
|
10284 |
|
|
dw2_asm_output_data (1, DW_children_yes, "DW_children_yes");
|
10285 |
|
|
else
|
10286 |
|
|
dw2_asm_output_data (1, DW_children_no, "DW_children_no");
|
10287 |
|
|
|
10288 |
|
|
for (ix = 0; VEC_iterate (dw_attr_node, abbrev->die_attr, ix, a_attr);
|
10289 |
|
|
ix++)
|
10290 |
|
|
{
|
10291 |
|
|
dw2_asm_output_data_uleb128 (a_attr->dw_attr, "(%s)",
|
10292 |
|
|
dwarf_attr_name (a_attr->dw_attr));
|
10293 |
|
|
output_value_format (a_attr);
|
10294 |
|
|
}
|
10295 |
|
|
|
10296 |
|
|
dw2_asm_output_data (1, 0, NULL);
|
10297 |
|
|
dw2_asm_output_data (1, 0, NULL);
|
10298 |
|
|
}
|
10299 |
|
|
|
10300 |
|
|
/* Terminate the table. */
|
10301 |
|
|
dw2_asm_output_data (1, 0, NULL);
|
10302 |
|
|
}
|
10303 |
|
|
|
10304 |
|
|
/* Output a symbol we can use to refer to this DIE from another CU. */
|
10305 |
|
|
|
10306 |
|
|
static inline void
|
10307 |
|
|
output_die_symbol (dw_die_ref die)
|
10308 |
|
|
{
|
10309 |
|
|
char *sym = die->die_id.die_symbol;
|
10310 |
|
|
|
10311 |
|
|
if (sym == 0)
|
10312 |
|
|
return;
|
10313 |
|
|
|
10314 |
|
|
if (strncmp (sym, DIE_LABEL_PREFIX, sizeof (DIE_LABEL_PREFIX) - 1) == 0)
|
10315 |
|
|
/* We make these global, not weak; if the target doesn't support
|
10316 |
|
|
.linkonce, it doesn't support combining the sections, so debugging
|
10317 |
|
|
will break. */
|
10318 |
|
|
targetm.asm_out.globalize_label (asm_out_file, sym);
|
10319 |
|
|
|
10320 |
|
|
ASM_OUTPUT_LABEL (asm_out_file, sym);
|
10321 |
|
|
}
|
10322 |
|
|
|
10323 |
|
|
/* Return a new location list, given the begin and end range, and the
|
10324 |
|
|
expression. */
|
10325 |
|
|
|
10326 |
|
|
static inline dw_loc_list_ref
|
10327 |
|
|
new_loc_list (dw_loc_descr_ref expr, const char *begin, const char *end,
|
10328 |
|
|
const char *section)
|
10329 |
|
|
{
|
10330 |
|
|
dw_loc_list_ref retlist = GGC_CNEW (dw_loc_list_node);
|
10331 |
|
|
|
10332 |
|
|
retlist->begin = begin;
|
10333 |
|
|
retlist->end = end;
|
10334 |
|
|
retlist->expr = expr;
|
10335 |
|
|
retlist->section = section;
|
10336 |
|
|
|
10337 |
|
|
return retlist;
|
10338 |
|
|
}
|
10339 |
|
|
|
10340 |
|
|
/* Generate a new internal symbol for this location list node, if it
|
10341 |
|
|
hasn't got one yet. */
|
10342 |
|
|
|
10343 |
|
|
static inline void
|
10344 |
|
|
gen_llsym (dw_loc_list_ref list)
|
10345 |
|
|
{
|
10346 |
|
|
gcc_assert (!list->ll_symbol);
|
10347 |
|
|
list->ll_symbol = gen_internal_sym ("LLST");
|
10348 |
|
|
}
|
10349 |
|
|
|
10350 |
|
|
/* Output the location list given to us. */
|
10351 |
|
|
|
10352 |
|
|
static void
|
10353 |
|
|
output_loc_list (dw_loc_list_ref list_head)
|
10354 |
|
|
{
|
10355 |
|
|
dw_loc_list_ref curr = list_head;
|
10356 |
|
|
|
10357 |
|
|
ASM_OUTPUT_LABEL (asm_out_file, list_head->ll_symbol);
|
10358 |
|
|
|
10359 |
|
|
/* Walk the location list, and output each range + expression. */
|
10360 |
|
|
for (curr = list_head; curr != NULL; curr = curr->dw_loc_next)
|
10361 |
|
|
{
|
10362 |
|
|
unsigned long size;
|
10363 |
|
|
/* Don't output an entry that starts and ends at the same address. */
|
10364 |
|
|
if (strcmp (curr->begin, curr->end) == 0)
|
10365 |
|
|
continue;
|
10366 |
|
|
if (!have_multiple_function_sections)
|
10367 |
|
|
{
|
10368 |
|
|
dw2_asm_output_delta (DWARF2_ADDR_SIZE, curr->begin, curr->section,
|
10369 |
|
|
"Location list begin address (%s)",
|
10370 |
|
|
list_head->ll_symbol);
|
10371 |
|
|
dw2_asm_output_delta (DWARF2_ADDR_SIZE, curr->end, curr->section,
|
10372 |
|
|
"Location list end address (%s)",
|
10373 |
|
|
list_head->ll_symbol);
|
10374 |
|
|
}
|
10375 |
|
|
else
|
10376 |
|
|
{
|
10377 |
|
|
dw2_asm_output_addr (DWARF2_ADDR_SIZE, curr->begin,
|
10378 |
|
|
"Location list begin address (%s)",
|
10379 |
|
|
list_head->ll_symbol);
|
10380 |
|
|
dw2_asm_output_addr (DWARF2_ADDR_SIZE, curr->end,
|
10381 |
|
|
"Location list end address (%s)",
|
10382 |
|
|
list_head->ll_symbol);
|
10383 |
|
|
}
|
10384 |
|
|
size = size_of_locs (curr->expr);
|
10385 |
|
|
|
10386 |
|
|
/* Output the block length for this list of location operations. */
|
10387 |
|
|
gcc_assert (size <= 0xffff);
|
10388 |
|
|
dw2_asm_output_data (2, size, "%s", "Location expression size");
|
10389 |
|
|
|
10390 |
|
|
output_loc_sequence (curr->expr);
|
10391 |
|
|
}
|
10392 |
|
|
|
10393 |
|
|
dw2_asm_output_data (DWARF2_ADDR_SIZE, 0,
|
10394 |
|
|
"Location list terminator begin (%s)",
|
10395 |
|
|
list_head->ll_symbol);
|
10396 |
|
|
dw2_asm_output_data (DWARF2_ADDR_SIZE, 0,
|
10397 |
|
|
"Location list terminator end (%s)",
|
10398 |
|
|
list_head->ll_symbol);
|
10399 |
|
|
}
|
10400 |
|
|
|
10401 |
|
|
/* Output a type signature. */
|
10402 |
|
|
|
10403 |
|
|
static inline void
|
10404 |
|
|
output_signature (const char *sig, const char *name)
|
10405 |
|
|
{
|
10406 |
|
|
int i;
|
10407 |
|
|
|
10408 |
|
|
for (i = 0; i < DWARF_TYPE_SIGNATURE_SIZE; i++)
|
10409 |
|
|
dw2_asm_output_data (1, sig[i], i == 0 ? "%s" : NULL, name);
|
10410 |
|
|
}
|
10411 |
|
|
|
10412 |
|
|
/* Output the DIE and its attributes. Called recursively to generate
|
10413 |
|
|
the definitions of each child DIE. */
|
10414 |
|
|
|
10415 |
|
|
static void
|
10416 |
|
|
output_die (dw_die_ref die)
|
10417 |
|
|
{
|
10418 |
|
|
dw_attr_ref a;
|
10419 |
|
|
dw_die_ref c;
|
10420 |
|
|
unsigned long size;
|
10421 |
|
|
unsigned ix;
|
10422 |
|
|
|
10423 |
|
|
/* If someone in another CU might refer to us, set up a symbol for
|
10424 |
|
|
them to point to. */
|
10425 |
|
|
if (dwarf_version < 4 && die->die_id.die_symbol)
|
10426 |
|
|
output_die_symbol (die);
|
10427 |
|
|
|
10428 |
|
|
dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (0x%lx) %s)",
|
10429 |
|
|
(unsigned long)die->die_offset,
|
10430 |
|
|
dwarf_tag_name (die->die_tag));
|
10431 |
|
|
|
10432 |
|
|
for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
|
10433 |
|
|
{
|
10434 |
|
|
const char *name = dwarf_attr_name (a->dw_attr);
|
10435 |
|
|
|
10436 |
|
|
switch (AT_class (a))
|
10437 |
|
|
{
|
10438 |
|
|
case dw_val_class_addr:
|
10439 |
|
|
dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, AT_addr (a), "%s", name);
|
10440 |
|
|
break;
|
10441 |
|
|
|
10442 |
|
|
case dw_val_class_offset:
|
10443 |
|
|
dw2_asm_output_data (DWARF_OFFSET_SIZE, a->dw_attr_val.v.val_offset,
|
10444 |
|
|
"%s", name);
|
10445 |
|
|
break;
|
10446 |
|
|
|
10447 |
|
|
case dw_val_class_range_list:
|
10448 |
|
|
{
|
10449 |
|
|
char *p = strchr (ranges_section_label, '\0');
|
10450 |
|
|
|
10451 |
|
|
sprintf (p, "+" HOST_WIDE_INT_PRINT_HEX,
|
10452 |
|
|
a->dw_attr_val.v.val_offset);
|
10453 |
|
|
dw2_asm_output_offset (DWARF_OFFSET_SIZE, ranges_section_label,
|
10454 |
|
|
debug_ranges_section, "%s", name);
|
10455 |
|
|
*p = '\0';
|
10456 |
|
|
}
|
10457 |
|
|
break;
|
10458 |
|
|
|
10459 |
|
|
case dw_val_class_loc:
|
10460 |
|
|
size = size_of_locs (AT_loc (a));
|
10461 |
|
|
|
10462 |
|
|
/* Output the block length for this list of location operations. */
|
10463 |
|
|
if (dwarf_version >= 4)
|
10464 |
|
|
dw2_asm_output_data_uleb128 (size, "%s", name);
|
10465 |
|
|
else
|
10466 |
|
|
dw2_asm_output_data (constant_size (size), size, "%s", name);
|
10467 |
|
|
|
10468 |
|
|
output_loc_sequence (AT_loc (a));
|
10469 |
|
|
break;
|
10470 |
|
|
|
10471 |
|
|
case dw_val_class_const:
|
10472 |
|
|
/* ??? It would be slightly more efficient to use a scheme like is
|
10473 |
|
|
used for unsigned constants below, but gdb 4.x does not sign
|
10474 |
|
|
extend. Gdb 5.x does sign extend. */
|
10475 |
|
|
dw2_asm_output_data_sleb128 (AT_int (a), "%s", name);
|
10476 |
|
|
break;
|
10477 |
|
|
|
10478 |
|
|
case dw_val_class_unsigned_const:
|
10479 |
|
|
dw2_asm_output_data (constant_size (AT_unsigned (a)),
|
10480 |
|
|
AT_unsigned (a), "%s", name);
|
10481 |
|
|
break;
|
10482 |
|
|
|
10483 |
|
|
case dw_val_class_const_double:
|
10484 |
|
|
{
|
10485 |
|
|
unsigned HOST_WIDE_INT first, second;
|
10486 |
|
|
|
10487 |
|
|
if (HOST_BITS_PER_WIDE_INT >= 64)
|
10488 |
|
|
dw2_asm_output_data (1,
|
10489 |
|
|
2 * HOST_BITS_PER_WIDE_INT
|
10490 |
|
|
/ HOST_BITS_PER_CHAR,
|
10491 |
|
|
NULL);
|
10492 |
|
|
|
10493 |
|
|
if (WORDS_BIG_ENDIAN)
|
10494 |
|
|
{
|
10495 |
|
|
first = a->dw_attr_val.v.val_double.high;
|
10496 |
|
|
second = a->dw_attr_val.v.val_double.low;
|
10497 |
|
|
}
|
10498 |
|
|
else
|
10499 |
|
|
{
|
10500 |
|
|
first = a->dw_attr_val.v.val_double.low;
|
10501 |
|
|
second = a->dw_attr_val.v.val_double.high;
|
10502 |
|
|
}
|
10503 |
|
|
|
10504 |
|
|
dw2_asm_output_data (HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR,
|
10505 |
|
|
first, name);
|
10506 |
|
|
dw2_asm_output_data (HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR,
|
10507 |
|
|
second, NULL);
|
10508 |
|
|
}
|
10509 |
|
|
break;
|
10510 |
|
|
|
10511 |
|
|
case dw_val_class_vec:
|
10512 |
|
|
{
|
10513 |
|
|
unsigned int elt_size = a->dw_attr_val.v.val_vec.elt_size;
|
10514 |
|
|
unsigned int len = a->dw_attr_val.v.val_vec.length;
|
10515 |
|
|
unsigned int i;
|
10516 |
|
|
unsigned char *p;
|
10517 |
|
|
|
10518 |
|
|
dw2_asm_output_data (constant_size (len * elt_size),
|
10519 |
|
|
len * elt_size, "%s", name);
|
10520 |
|
|
if (elt_size > sizeof (HOST_WIDE_INT))
|
10521 |
|
|
{
|
10522 |
|
|
elt_size /= 2;
|
10523 |
|
|
len *= 2;
|
10524 |
|
|
}
|
10525 |
|
|
for (i = 0, p = a->dw_attr_val.v.val_vec.array;
|
10526 |
|
|
i < len;
|
10527 |
|
|
i++, p += elt_size)
|
10528 |
|
|
dw2_asm_output_data (elt_size, extract_int (p, elt_size),
|
10529 |
|
|
"fp or vector constant word %u", i);
|
10530 |
|
|
break;
|
10531 |
|
|
}
|
10532 |
|
|
|
10533 |
|
|
case dw_val_class_flag:
|
10534 |
|
|
if (dwarf_version >= 4)
|
10535 |
|
|
{
|
10536 |
|
|
/* Currently all add_AT_flag calls pass in 1 as last argument,
|
10537 |
|
|
so DW_FORM_flag_present can be used. If that ever changes,
|
10538 |
|
|
we'll need to use DW_FORM_flag and have some optimization
|
10539 |
|
|
in build_abbrev_table that will change those to
|
10540 |
|
|
DW_FORM_flag_present if it is set to 1 in all DIEs using
|
10541 |
|
|
the same abbrev entry. */
|
10542 |
|
|
gcc_assert (AT_flag (a) == 1);
|
10543 |
|
|
if (flag_debug_asm)
|
10544 |
|
|
fprintf (asm_out_file, "\t\t\t%s %s\n",
|
10545 |
|
|
ASM_COMMENT_START, name);
|
10546 |
|
|
break;
|
10547 |
|
|
}
|
10548 |
|
|
dw2_asm_output_data (1, AT_flag (a), "%s", name);
|
10549 |
|
|
break;
|
10550 |
|
|
|
10551 |
|
|
case dw_val_class_loc_list:
|
10552 |
|
|
{
|
10553 |
|
|
char *sym = AT_loc_list (a)->ll_symbol;
|
10554 |
|
|
|
10555 |
|
|
gcc_assert (sym);
|
10556 |
|
|
dw2_asm_output_offset (DWARF_OFFSET_SIZE, sym, debug_loc_section,
|
10557 |
|
|
"%s", name);
|
10558 |
|
|
}
|
10559 |
|
|
break;
|
10560 |
|
|
|
10561 |
|
|
case dw_val_class_die_ref:
|
10562 |
|
|
if (AT_ref_external (a))
|
10563 |
|
|
{
|
10564 |
|
|
if (dwarf_version >= 4)
|
10565 |
|
|
{
|
10566 |
|
|
comdat_type_node_ref type_node =
|
10567 |
|
|
AT_ref (a)->die_id.die_type_node;
|
10568 |
|
|
|
10569 |
|
|
gcc_assert (type_node);
|
10570 |
|
|
output_signature (type_node->signature, name);
|
10571 |
|
|
}
|
10572 |
|
|
else
|
10573 |
|
|
{
|
10574 |
|
|
char *sym = AT_ref (a)->die_id.die_symbol;
|
10575 |
|
|
int size;
|
10576 |
|
|
|
10577 |
|
|
gcc_assert (sym);
|
10578 |
|
|
/* In DWARF2, DW_FORM_ref_addr is sized by target address
|
10579 |
|
|
length, whereas in DWARF3 it's always sized as an
|
10580 |
|
|
offset. */
|
10581 |
|
|
if (dwarf_version == 2)
|
10582 |
|
|
size = DWARF2_ADDR_SIZE;
|
10583 |
|
|
else
|
10584 |
|
|
size = DWARF_OFFSET_SIZE;
|
10585 |
|
|
dw2_asm_output_offset (size, sym, debug_info_section, "%s",
|
10586 |
|
|
name);
|
10587 |
|
|
}
|
10588 |
|
|
}
|
10589 |
|
|
else
|
10590 |
|
|
{
|
10591 |
|
|
gcc_assert (AT_ref (a)->die_offset);
|
10592 |
|
|
dw2_asm_output_data (DWARF_OFFSET_SIZE, AT_ref (a)->die_offset,
|
10593 |
|
|
"%s", name);
|
10594 |
|
|
}
|
10595 |
|
|
break;
|
10596 |
|
|
|
10597 |
|
|
case dw_val_class_fde_ref:
|
10598 |
|
|
{
|
10599 |
|
|
char l1[20];
|
10600 |
|
|
|
10601 |
|
|
ASM_GENERATE_INTERNAL_LABEL (l1, FDE_LABEL,
|
10602 |
|
|
a->dw_attr_val.v.val_fde_index * 2);
|
10603 |
|
|
dw2_asm_output_offset (DWARF_OFFSET_SIZE, l1, debug_frame_section,
|
10604 |
|
|
"%s", name);
|
10605 |
|
|
}
|
10606 |
|
|
break;
|
10607 |
|
|
|
10608 |
|
|
case dw_val_class_lbl_id:
|
10609 |
|
|
dw2_asm_output_addr (DWARF2_ADDR_SIZE, AT_lbl (a), "%s", name);
|
10610 |
|
|
break;
|
10611 |
|
|
|
10612 |
|
|
case dw_val_class_lineptr:
|
10613 |
|
|
dw2_asm_output_offset (DWARF_OFFSET_SIZE, AT_lbl (a),
|
10614 |
|
|
debug_line_section, "%s", name);
|
10615 |
|
|
break;
|
10616 |
|
|
|
10617 |
|
|
case dw_val_class_macptr:
|
10618 |
|
|
dw2_asm_output_offset (DWARF_OFFSET_SIZE, AT_lbl (a),
|
10619 |
|
|
debug_macinfo_section, "%s", name);
|
10620 |
|
|
break;
|
10621 |
|
|
|
10622 |
|
|
case dw_val_class_str:
|
10623 |
|
|
if (AT_string_form (a) == DW_FORM_strp)
|
10624 |
|
|
dw2_asm_output_offset (DWARF_OFFSET_SIZE,
|
10625 |
|
|
a->dw_attr_val.v.val_str->label,
|
10626 |
|
|
debug_str_section,
|
10627 |
|
|
"%s: \"%s\"", name, AT_string (a));
|
10628 |
|
|
else
|
10629 |
|
|
dw2_asm_output_nstring (AT_string (a), -1, "%s", name);
|
10630 |
|
|
break;
|
10631 |
|
|
|
10632 |
|
|
case dw_val_class_file:
|
10633 |
|
|
{
|
10634 |
|
|
int f = maybe_emit_file (a->dw_attr_val.v.val_file);
|
10635 |
|
|
|
10636 |
|
|
dw2_asm_output_data (constant_size (f), f, "%s (%s)", name,
|
10637 |
|
|
a->dw_attr_val.v.val_file->filename);
|
10638 |
|
|
break;
|
10639 |
|
|
}
|
10640 |
|
|
|
10641 |
|
|
case dw_val_class_data8:
|
10642 |
|
|
{
|
10643 |
|
|
int i;
|
10644 |
|
|
|
10645 |
|
|
for (i = 0; i < 8; i++)
|
10646 |
|
|
dw2_asm_output_data (1, a->dw_attr_val.v.val_data8[i],
|
10647 |
|
|
i == 0 ? "%s" : NULL, name);
|
10648 |
|
|
break;
|
10649 |
|
|
}
|
10650 |
|
|
|
10651 |
|
|
default:
|
10652 |
|
|
gcc_unreachable ();
|
10653 |
|
|
}
|
10654 |
|
|
}
|
10655 |
|
|
|
10656 |
|
|
FOR_EACH_CHILD (die, c, output_die (c));
|
10657 |
|
|
|
10658 |
|
|
/* Add null byte to terminate sibling list. */
|
10659 |
|
|
if (die->die_child != NULL)
|
10660 |
|
|
dw2_asm_output_data (1, 0, "end of children of DIE 0x%lx",
|
10661 |
|
|
(unsigned long) die->die_offset);
|
10662 |
|
|
}
|
10663 |
|
|
|
10664 |
|
|
/* Output the compilation unit that appears at the beginning of the
|
10665 |
|
|
.debug_info section, and precedes the DIE descriptions. */
|
10666 |
|
|
|
10667 |
|
|
static void
|
10668 |
|
|
output_compilation_unit_header (void)
|
10669 |
|
|
{
|
10670 |
|
|
int ver = dwarf_version;
|
10671 |
|
|
|
10672 |
|
|
if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
|
10673 |
|
|
dw2_asm_output_data (4, 0xffffffff,
|
10674 |
|
|
"Initial length escape value indicating 64-bit DWARF extension");
|
10675 |
|
|
dw2_asm_output_data (DWARF_OFFSET_SIZE,
|
10676 |
|
|
next_die_offset - DWARF_INITIAL_LENGTH_SIZE,
|
10677 |
|
|
"Length of Compilation Unit Info");
|
10678 |
|
|
dw2_asm_output_data (2, ver, "DWARF version number");
|
10679 |
|
|
dw2_asm_output_offset (DWARF_OFFSET_SIZE, abbrev_section_label,
|
10680 |
|
|
debug_abbrev_section,
|
10681 |
|
|
"Offset Into Abbrev. Section");
|
10682 |
|
|
dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Pointer Size (in bytes)");
|
10683 |
|
|
}
|
10684 |
|
|
|
10685 |
|
|
/* Output the compilation unit DIE and its children. */
|
10686 |
|
|
|
10687 |
|
|
static void
|
10688 |
|
|
output_comp_unit (dw_die_ref die, int output_if_empty)
|
10689 |
|
|
{
|
10690 |
|
|
const char *secname;
|
10691 |
|
|
char *oldsym, *tmp;
|
10692 |
|
|
|
10693 |
|
|
/* Unless we are outputting main CU, we may throw away empty ones. */
|
10694 |
|
|
if (!output_if_empty && die->die_child == NULL)
|
10695 |
|
|
return;
|
10696 |
|
|
|
10697 |
|
|
/* Even if there are no children of this DIE, we must output the information
|
10698 |
|
|
about the compilation unit. Otherwise, on an empty translation unit, we
|
10699 |
|
|
will generate a present, but empty, .debug_info section. IRIX 6.5 `nm'
|
10700 |
|
|
will then complain when examining the file. First mark all the DIEs in
|
10701 |
|
|
this CU so we know which get local refs. */
|
10702 |
|
|
mark_dies (die);
|
10703 |
|
|
|
10704 |
|
|
build_abbrev_table (die);
|
10705 |
|
|
|
10706 |
|
|
/* Initialize the beginning DIE offset - and calculate sizes/offsets. */
|
10707 |
|
|
next_die_offset = DWARF_COMPILE_UNIT_HEADER_SIZE;
|
10708 |
|
|
calc_die_sizes (die);
|
10709 |
|
|
|
10710 |
|
|
oldsym = die->die_id.die_symbol;
|
10711 |
|
|
if (oldsym)
|
10712 |
|
|
{
|
10713 |
|
|
tmp = XALLOCAVEC (char, strlen (oldsym) + 24);
|
10714 |
|
|
|
10715 |
|
|
sprintf (tmp, ".gnu.linkonce.wi.%s", oldsym);
|
10716 |
|
|
secname = tmp;
|
10717 |
|
|
die->die_id.die_symbol = NULL;
|
10718 |
|
|
switch_to_section (get_section (secname, SECTION_DEBUG, NULL));
|
10719 |
|
|
}
|
10720 |
|
|
else
|
10721 |
|
|
switch_to_section (debug_info_section);
|
10722 |
|
|
|
10723 |
|
|
/* Output debugging information. */
|
10724 |
|
|
output_compilation_unit_header ();
|
10725 |
|
|
output_die (die);
|
10726 |
|
|
|
10727 |
|
|
/* Leave the marks on the main CU, so we can check them in
|
10728 |
|
|
output_pubnames. */
|
10729 |
|
|
if (oldsym)
|
10730 |
|
|
{
|
10731 |
|
|
unmark_dies (die);
|
10732 |
|
|
die->die_id.die_symbol = oldsym;
|
10733 |
|
|
}
|
10734 |
|
|
}
|
10735 |
|
|
|
10736 |
|
|
/* Output a comdat type unit DIE and its children. */
|
10737 |
|
|
|
10738 |
|
|
static void
|
10739 |
|
|
output_comdat_type_unit (comdat_type_node *node)
|
10740 |
|
|
{
|
10741 |
|
|
const char *secname;
|
10742 |
|
|
char *tmp;
|
10743 |
|
|
int i;
|
10744 |
|
|
#if defined (OBJECT_FORMAT_ELF)
|
10745 |
|
|
tree comdat_key;
|
10746 |
|
|
#endif
|
10747 |
|
|
|
10748 |
|
|
/* First mark all the DIEs in this CU so we know which get local refs. */
|
10749 |
|
|
mark_dies (node->root_die);
|
10750 |
|
|
|
10751 |
|
|
build_abbrev_table (node->root_die);
|
10752 |
|
|
|
10753 |
|
|
/* Initialize the beginning DIE offset - and calculate sizes/offsets. */
|
10754 |
|
|
next_die_offset = DWARF_COMDAT_TYPE_UNIT_HEADER_SIZE;
|
10755 |
|
|
calc_die_sizes (node->root_die);
|
10756 |
|
|
|
10757 |
|
|
#if defined (OBJECT_FORMAT_ELF)
|
10758 |
|
|
secname = ".debug_types";
|
10759 |
|
|
tmp = XALLOCAVEC (char, 4 + DWARF_TYPE_SIGNATURE_SIZE * 2);
|
10760 |
|
|
sprintf (tmp, "wt.");
|
10761 |
|
|
for (i = 0; i < DWARF_TYPE_SIGNATURE_SIZE; i++)
|
10762 |
|
|
sprintf (tmp + 3 + i * 2, "%02x", node->signature[i] & 0xff);
|
10763 |
|
|
comdat_key = get_identifier (tmp);
|
10764 |
|
|
targetm.asm_out.named_section (secname,
|
10765 |
|
|
SECTION_DEBUG | SECTION_LINKONCE,
|
10766 |
|
|
comdat_key);
|
10767 |
|
|
#else
|
10768 |
|
|
tmp = XALLOCAVEC (char, 18 + DWARF_TYPE_SIGNATURE_SIZE * 2);
|
10769 |
|
|
sprintf (tmp, ".gnu.linkonce.wt.");
|
10770 |
|
|
for (i = 0; i < DWARF_TYPE_SIGNATURE_SIZE; i++)
|
10771 |
|
|
sprintf (tmp + 17 + i * 2, "%02x", node->signature[i] & 0xff);
|
10772 |
|
|
secname = tmp;
|
10773 |
|
|
switch_to_section (get_section (secname, SECTION_DEBUG, NULL));
|
10774 |
|
|
#endif
|
10775 |
|
|
|
10776 |
|
|
/* Output debugging information. */
|
10777 |
|
|
output_compilation_unit_header ();
|
10778 |
|
|
output_signature (node->signature, "Type Signature");
|
10779 |
|
|
dw2_asm_output_data (DWARF_OFFSET_SIZE, node->type_die->die_offset,
|
10780 |
|
|
"Offset to Type DIE");
|
10781 |
|
|
output_die (node->root_die);
|
10782 |
|
|
|
10783 |
|
|
unmark_dies (node->root_die);
|
10784 |
|
|
}
|
10785 |
|
|
|
10786 |
|
|
/* Return the DWARF2/3 pubname associated with a decl. */
|
10787 |
|
|
|
10788 |
|
|
static const char *
|
10789 |
|
|
dwarf2_name (tree decl, int scope)
|
10790 |
|
|
{
|
10791 |
|
|
return lang_hooks.dwarf_name (decl, scope ? 1 : 0);
|
10792 |
|
|
}
|
10793 |
|
|
|
10794 |
|
|
/* Add a new entry to .debug_pubnames if appropriate. */
|
10795 |
|
|
|
10796 |
|
|
static void
|
10797 |
|
|
add_pubname_string (const char *str, dw_die_ref die)
|
10798 |
|
|
{
|
10799 |
|
|
pubname_entry e;
|
10800 |
|
|
|
10801 |
|
|
e.die = die;
|
10802 |
|
|
e.name = xstrdup (str);
|
10803 |
|
|
VEC_safe_push (pubname_entry, gc, pubname_table, &e);
|
10804 |
|
|
}
|
10805 |
|
|
|
10806 |
|
|
static void
|
10807 |
|
|
add_pubname (tree decl, dw_die_ref die)
|
10808 |
|
|
{
|
10809 |
|
|
if (TREE_PUBLIC (decl))
|
10810 |
|
|
{
|
10811 |
|
|
const char *name = dwarf2_name (decl, 1);
|
10812 |
|
|
if (name)
|
10813 |
|
|
add_pubname_string (name, die);
|
10814 |
|
|
}
|
10815 |
|
|
}
|
10816 |
|
|
|
10817 |
|
|
/* Add a new entry to .debug_pubtypes if appropriate. */
|
10818 |
|
|
|
10819 |
|
|
static void
|
10820 |
|
|
add_pubtype (tree decl, dw_die_ref die)
|
10821 |
|
|
{
|
10822 |
|
|
pubname_entry e;
|
10823 |
|
|
|
10824 |
|
|
e.name = NULL;
|
10825 |
|
|
if ((TREE_PUBLIC (decl)
|
10826 |
|
|
|| die->die_parent == comp_unit_die)
|
10827 |
|
|
&& (die->die_tag == DW_TAG_typedef || COMPLETE_TYPE_P (decl)))
|
10828 |
|
|
{
|
10829 |
|
|
e.die = die;
|
10830 |
|
|
if (TYPE_P (decl))
|
10831 |
|
|
{
|
10832 |
|
|
if (TYPE_NAME (decl))
|
10833 |
|
|
{
|
10834 |
|
|
if (TREE_CODE (TYPE_NAME (decl)) == IDENTIFIER_NODE)
|
10835 |
|
|
e.name = IDENTIFIER_POINTER (TYPE_NAME (decl));
|
10836 |
|
|
else if (TREE_CODE (TYPE_NAME (decl)) == TYPE_DECL
|
10837 |
|
|
&& DECL_NAME (TYPE_NAME (decl)))
|
10838 |
|
|
e.name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (decl)));
|
10839 |
|
|
else
|
10840 |
|
|
e.name = xstrdup ((const char *) get_AT_string (die, DW_AT_name));
|
10841 |
|
|
}
|
10842 |
|
|
}
|
10843 |
|
|
else
|
10844 |
|
|
{
|
10845 |
|
|
e.name = dwarf2_name (decl, 1);
|
10846 |
|
|
if (e.name)
|
10847 |
|
|
e.name = xstrdup (e.name);
|
10848 |
|
|
}
|
10849 |
|
|
|
10850 |
|
|
/* If we don't have a name for the type, there's no point in adding
|
10851 |
|
|
it to the table. */
|
10852 |
|
|
if (e.name && e.name[0] != '\0')
|
10853 |
|
|
VEC_safe_push (pubname_entry, gc, pubtype_table, &e);
|
10854 |
|
|
}
|
10855 |
|
|
}
|
10856 |
|
|
|
10857 |
|
|
/* Output the public names table used to speed up access to externally
|
10858 |
|
|
visible names; or the public types table used to find type definitions. */
|
10859 |
|
|
|
10860 |
|
|
static void
|
10861 |
|
|
output_pubnames (VEC (pubname_entry, gc) * names)
|
10862 |
|
|
{
|
10863 |
|
|
unsigned i;
|
10864 |
|
|
unsigned long pubnames_length = size_of_pubnames (names);
|
10865 |
|
|
pubname_ref pub;
|
10866 |
|
|
|
10867 |
|
|
if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
|
10868 |
|
|
dw2_asm_output_data (4, 0xffffffff,
|
10869 |
|
|
"Initial length escape value indicating 64-bit DWARF extension");
|
10870 |
|
|
if (names == pubname_table)
|
10871 |
|
|
dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length,
|
10872 |
|
|
"Length of Public Names Info");
|
10873 |
|
|
else
|
10874 |
|
|
dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length,
|
10875 |
|
|
"Length of Public Type Names Info");
|
10876 |
|
|
/* Version number for pubnames/pubtypes is still 2, even in DWARF3. */
|
10877 |
|
|
dw2_asm_output_data (2, 2, "DWARF Version");
|
10878 |
|
|
dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_info_section_label,
|
10879 |
|
|
debug_info_section,
|
10880 |
|
|
"Offset of Compilation Unit Info");
|
10881 |
|
|
dw2_asm_output_data (DWARF_OFFSET_SIZE, next_die_offset,
|
10882 |
|
|
"Compilation Unit Length");
|
10883 |
|
|
|
10884 |
|
|
for (i = 0; VEC_iterate (pubname_entry, names, i, pub); i++)
|
10885 |
|
|
{
|
10886 |
|
|
/* We shouldn't see pubnames for DIEs outside of the main CU. */
|
10887 |
|
|
if (names == pubname_table)
|
10888 |
|
|
gcc_assert (pub->die->die_mark);
|
10889 |
|
|
|
10890 |
|
|
if (names != pubtype_table
|
10891 |
|
|
|| pub->die->die_offset != 0
|
10892 |
|
|
|| !flag_eliminate_unused_debug_types)
|
10893 |
|
|
{
|
10894 |
|
|
dw2_asm_output_data (DWARF_OFFSET_SIZE, pub->die->die_offset,
|
10895 |
|
|
"DIE offset");
|
10896 |
|
|
|
10897 |
|
|
dw2_asm_output_nstring (pub->name, -1, "external name");
|
10898 |
|
|
}
|
10899 |
|
|
}
|
10900 |
|
|
|
10901 |
|
|
dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, NULL);
|
10902 |
|
|
}
|
10903 |
|
|
|
10904 |
|
|
/* Add a new entry to .debug_aranges if appropriate. */
|
10905 |
|
|
|
10906 |
|
|
static void
|
10907 |
|
|
add_arange (tree decl, dw_die_ref die)
|
10908 |
|
|
{
|
10909 |
|
|
if (! DECL_SECTION_NAME (decl))
|
10910 |
|
|
return;
|
10911 |
|
|
|
10912 |
|
|
if (arange_table_in_use == arange_table_allocated)
|
10913 |
|
|
{
|
10914 |
|
|
arange_table_allocated += ARANGE_TABLE_INCREMENT;
|
10915 |
|
|
arange_table = GGC_RESIZEVEC (dw_die_ref, arange_table,
|
10916 |
|
|
arange_table_allocated);
|
10917 |
|
|
memset (arange_table + arange_table_in_use, 0,
|
10918 |
|
|
ARANGE_TABLE_INCREMENT * sizeof (dw_die_ref));
|
10919 |
|
|
}
|
10920 |
|
|
|
10921 |
|
|
arange_table[arange_table_in_use++] = die;
|
10922 |
|
|
}
|
10923 |
|
|
|
10924 |
|
|
/* Output the information that goes into the .debug_aranges table.
|
10925 |
|
|
Namely, define the beginning and ending address range of the
|
10926 |
|
|
text section generated for this compilation unit. */
|
10927 |
|
|
|
10928 |
|
|
static void
|
10929 |
|
|
output_aranges (void)
|
10930 |
|
|
{
|
10931 |
|
|
unsigned i;
|
10932 |
|
|
unsigned long aranges_length = size_of_aranges ();
|
10933 |
|
|
|
10934 |
|
|
if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
|
10935 |
|
|
dw2_asm_output_data (4, 0xffffffff,
|
10936 |
|
|
"Initial length escape value indicating 64-bit DWARF extension");
|
10937 |
|
|
dw2_asm_output_data (DWARF_OFFSET_SIZE, aranges_length,
|
10938 |
|
|
"Length of Address Ranges Info");
|
10939 |
|
|
/* Version number for aranges is still 2, even in DWARF3. */
|
10940 |
|
|
dw2_asm_output_data (2, 2, "DWARF Version");
|
10941 |
|
|
dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_info_section_label,
|
10942 |
|
|
debug_info_section,
|
10943 |
|
|
"Offset of Compilation Unit Info");
|
10944 |
|
|
dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Size of Address");
|
10945 |
|
|
dw2_asm_output_data (1, 0, "Size of Segment Descriptor");
|
10946 |
|
|
|
10947 |
|
|
/* We need to align to twice the pointer size here. */
|
10948 |
|
|
if (DWARF_ARANGES_PAD_SIZE)
|
10949 |
|
|
{
|
10950 |
|
|
/* Pad using a 2 byte words so that padding is correct for any
|
10951 |
|
|
pointer size. */
|
10952 |
|
|
dw2_asm_output_data (2, 0, "Pad to %d byte boundary",
|
10953 |
|
|
2 * DWARF2_ADDR_SIZE);
|
10954 |
|
|
for (i = 2; i < (unsigned) DWARF_ARANGES_PAD_SIZE; i += 2)
|
10955 |
|
|
dw2_asm_output_data (2, 0, NULL);
|
10956 |
|
|
}
|
10957 |
|
|
|
10958 |
|
|
/* It is necessary not to output these entries if the sections were
|
10959 |
|
|
not used; if the sections were not used, the length will be 0 and
|
10960 |
|
|
the address may end up as 0 if the section is discarded by ld
|
10961 |
|
|
--gc-sections, leaving an invalid (0, 0) entry that can be
|
10962 |
|
|
confused with the terminator. */
|
10963 |
|
|
if (text_section_used)
|
10964 |
|
|
{
|
10965 |
|
|
dw2_asm_output_addr (DWARF2_ADDR_SIZE, text_section_label, "Address");
|
10966 |
|
|
dw2_asm_output_delta (DWARF2_ADDR_SIZE, text_end_label,
|
10967 |
|
|
text_section_label, "Length");
|
10968 |
|
|
}
|
10969 |
|
|
if (cold_text_section_used)
|
10970 |
|
|
{
|
10971 |
|
|
dw2_asm_output_addr (DWARF2_ADDR_SIZE, cold_text_section_label,
|
10972 |
|
|
"Address");
|
10973 |
|
|
dw2_asm_output_delta (DWARF2_ADDR_SIZE, cold_end_label,
|
10974 |
|
|
cold_text_section_label, "Length");
|
10975 |
|
|
}
|
10976 |
|
|
|
10977 |
|
|
for (i = 0; i < arange_table_in_use; i++)
|
10978 |
|
|
{
|
10979 |
|
|
dw_die_ref die = arange_table[i];
|
10980 |
|
|
|
10981 |
|
|
/* We shouldn't see aranges for DIEs outside of the main CU. */
|
10982 |
|
|
gcc_assert (die->die_mark);
|
10983 |
|
|
|
10984 |
|
|
if (die->die_tag == DW_TAG_subprogram)
|
10985 |
|
|
{
|
10986 |
|
|
dw2_asm_output_addr (DWARF2_ADDR_SIZE, get_AT_low_pc (die),
|
10987 |
|
|
"Address");
|
10988 |
|
|
dw2_asm_output_delta (DWARF2_ADDR_SIZE, get_AT_hi_pc (die),
|
10989 |
|
|
get_AT_low_pc (die), "Length");
|
10990 |
|
|
}
|
10991 |
|
|
else
|
10992 |
|
|
{
|
10993 |
|
|
/* A static variable; extract the symbol from DW_AT_location.
|
10994 |
|
|
Note that this code isn't currently hit, as we only emit
|
10995 |
|
|
aranges for functions (jason 9/23/99). */
|
10996 |
|
|
dw_attr_ref a = get_AT (die, DW_AT_location);
|
10997 |
|
|
dw_loc_descr_ref loc;
|
10998 |
|
|
|
10999 |
|
|
gcc_assert (a && AT_class (a) == dw_val_class_loc);
|
11000 |
|
|
|
11001 |
|
|
loc = AT_loc (a);
|
11002 |
|
|
gcc_assert (loc->dw_loc_opc == DW_OP_addr);
|
11003 |
|
|
|
11004 |
|
|
dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE,
|
11005 |
|
|
loc->dw_loc_oprnd1.v.val_addr, "Address");
|
11006 |
|
|
dw2_asm_output_data (DWARF2_ADDR_SIZE,
|
11007 |
|
|
get_AT_unsigned (die, DW_AT_byte_size),
|
11008 |
|
|
"Length");
|
11009 |
|
|
}
|
11010 |
|
|
}
|
11011 |
|
|
|
11012 |
|
|
/* Output the terminator words. */
|
11013 |
|
|
dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, NULL);
|
11014 |
|
|
dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, NULL);
|
11015 |
|
|
}
|
11016 |
|
|
|
11017 |
|
|
/* Add a new entry to .debug_ranges. Return the offset at which it
|
11018 |
|
|
was placed. */
|
11019 |
|
|
|
11020 |
|
|
static unsigned int
|
11021 |
|
|
add_ranges_num (int num)
|
11022 |
|
|
{
|
11023 |
|
|
unsigned int in_use = ranges_table_in_use;
|
11024 |
|
|
|
11025 |
|
|
if (in_use == ranges_table_allocated)
|
11026 |
|
|
{
|
11027 |
|
|
ranges_table_allocated += RANGES_TABLE_INCREMENT;
|
11028 |
|
|
ranges_table = GGC_RESIZEVEC (struct dw_ranges_struct, ranges_table,
|
11029 |
|
|
ranges_table_allocated);
|
11030 |
|
|
memset (ranges_table + ranges_table_in_use, 0,
|
11031 |
|
|
RANGES_TABLE_INCREMENT * sizeof (struct dw_ranges_struct));
|
11032 |
|
|
}
|
11033 |
|
|
|
11034 |
|
|
ranges_table[in_use].num = num;
|
11035 |
|
|
ranges_table_in_use = in_use + 1;
|
11036 |
|
|
|
11037 |
|
|
return in_use * 2 * DWARF2_ADDR_SIZE;
|
11038 |
|
|
}
|
11039 |
|
|
|
11040 |
|
|
/* Add a new entry to .debug_ranges corresponding to a block, or a
|
11041 |
|
|
range terminator if BLOCK is NULL. */
|
11042 |
|
|
|
11043 |
|
|
static unsigned int
|
11044 |
|
|
add_ranges (const_tree block)
|
11045 |
|
|
{
|
11046 |
|
|
return add_ranges_num (block ? BLOCK_NUMBER (block) : 0);
|
11047 |
|
|
}
|
11048 |
|
|
|
11049 |
|
|
/* Add a new entry to .debug_ranges corresponding to a pair of
|
11050 |
|
|
labels. */
|
11051 |
|
|
|
11052 |
|
|
static void
|
11053 |
|
|
add_ranges_by_labels (dw_die_ref die, const char *begin, const char *end,
|
11054 |
|
|
bool *added)
|
11055 |
|
|
{
|
11056 |
|
|
unsigned int in_use = ranges_by_label_in_use;
|
11057 |
|
|
unsigned int offset;
|
11058 |
|
|
|
11059 |
|
|
if (in_use == ranges_by_label_allocated)
|
11060 |
|
|
{
|
11061 |
|
|
ranges_by_label_allocated += RANGES_TABLE_INCREMENT;
|
11062 |
|
|
ranges_by_label = GGC_RESIZEVEC (struct dw_ranges_by_label_struct,
|
11063 |
|
|
ranges_by_label,
|
11064 |
|
|
ranges_by_label_allocated);
|
11065 |
|
|
memset (ranges_by_label + ranges_by_label_in_use, 0,
|
11066 |
|
|
RANGES_TABLE_INCREMENT
|
11067 |
|
|
* sizeof (struct dw_ranges_by_label_struct));
|
11068 |
|
|
}
|
11069 |
|
|
|
11070 |
|
|
ranges_by_label[in_use].begin = begin;
|
11071 |
|
|
ranges_by_label[in_use].end = end;
|
11072 |
|
|
ranges_by_label_in_use = in_use + 1;
|
11073 |
|
|
|
11074 |
|
|
offset = add_ranges_num (-(int)in_use - 1);
|
11075 |
|
|
if (!*added)
|
11076 |
|
|
{
|
11077 |
|
|
add_AT_range_list (die, DW_AT_ranges, offset);
|
11078 |
|
|
*added = true;
|
11079 |
|
|
}
|
11080 |
|
|
}
|
11081 |
|
|
|
11082 |
|
|
static void
|
11083 |
|
|
output_ranges (void)
|
11084 |
|
|
{
|
11085 |
|
|
unsigned i;
|
11086 |
|
|
static const char *const start_fmt = "Offset 0x%x";
|
11087 |
|
|
const char *fmt = start_fmt;
|
11088 |
|
|
|
11089 |
|
|
for (i = 0; i < ranges_table_in_use; i++)
|
11090 |
|
|
{
|
11091 |
|
|
int block_num = ranges_table[i].num;
|
11092 |
|
|
|
11093 |
|
|
if (block_num > 0)
|
11094 |
|
|
{
|
11095 |
|
|
char blabel[MAX_ARTIFICIAL_LABEL_BYTES];
|
11096 |
|
|
char elabel[MAX_ARTIFICIAL_LABEL_BYTES];
|
11097 |
|
|
|
11098 |
|
|
ASM_GENERATE_INTERNAL_LABEL (blabel, BLOCK_BEGIN_LABEL, block_num);
|
11099 |
|
|
ASM_GENERATE_INTERNAL_LABEL (elabel, BLOCK_END_LABEL, block_num);
|
11100 |
|
|
|
11101 |
|
|
/* If all code is in the text section, then the compilation
|
11102 |
|
|
unit base address defaults to DW_AT_low_pc, which is the
|
11103 |
|
|
base of the text section. */
|
11104 |
|
|
if (!have_multiple_function_sections)
|
11105 |
|
|
{
|
11106 |
|
|
dw2_asm_output_delta (DWARF2_ADDR_SIZE, blabel,
|
11107 |
|
|
text_section_label,
|
11108 |
|
|
fmt, i * 2 * DWARF2_ADDR_SIZE);
|
11109 |
|
|
dw2_asm_output_delta (DWARF2_ADDR_SIZE, elabel,
|
11110 |
|
|
text_section_label, NULL);
|
11111 |
|
|
}
|
11112 |
|
|
|
11113 |
|
|
/* Otherwise, the compilation unit base address is zero,
|
11114 |
|
|
which allows us to use absolute addresses, and not worry
|
11115 |
|
|
about whether the target supports cross-section
|
11116 |
|
|
arithmetic. */
|
11117 |
|
|
else
|
11118 |
|
|
{
|
11119 |
|
|
dw2_asm_output_addr (DWARF2_ADDR_SIZE, blabel,
|
11120 |
|
|
fmt, i * 2 * DWARF2_ADDR_SIZE);
|
11121 |
|
|
dw2_asm_output_addr (DWARF2_ADDR_SIZE, elabel, NULL);
|
11122 |
|
|
}
|
11123 |
|
|
|
11124 |
|
|
fmt = NULL;
|
11125 |
|
|
}
|
11126 |
|
|
|
11127 |
|
|
/* Negative block_num stands for an index into ranges_by_label. */
|
11128 |
|
|
else if (block_num < 0)
|
11129 |
|
|
{
|
11130 |
|
|
int lab_idx = - block_num - 1;
|
11131 |
|
|
|
11132 |
|
|
if (!have_multiple_function_sections)
|
11133 |
|
|
{
|
11134 |
|
|
gcc_unreachable ();
|
11135 |
|
|
#if 0
|
11136 |
|
|
/* If we ever use add_ranges_by_labels () for a single
|
11137 |
|
|
function section, all we have to do is to take out
|
11138 |
|
|
the #if 0 above. */
|
11139 |
|
|
dw2_asm_output_delta (DWARF2_ADDR_SIZE,
|
11140 |
|
|
ranges_by_label[lab_idx].begin,
|
11141 |
|
|
text_section_label,
|
11142 |
|
|
fmt, i * 2 * DWARF2_ADDR_SIZE);
|
11143 |
|
|
dw2_asm_output_delta (DWARF2_ADDR_SIZE,
|
11144 |
|
|
ranges_by_label[lab_idx].end,
|
11145 |
|
|
text_section_label, NULL);
|
11146 |
|
|
#endif
|
11147 |
|
|
}
|
11148 |
|
|
else
|
11149 |
|
|
{
|
11150 |
|
|
dw2_asm_output_addr (DWARF2_ADDR_SIZE,
|
11151 |
|
|
ranges_by_label[lab_idx].begin,
|
11152 |
|
|
fmt, i * 2 * DWARF2_ADDR_SIZE);
|
11153 |
|
|
dw2_asm_output_addr (DWARF2_ADDR_SIZE,
|
11154 |
|
|
ranges_by_label[lab_idx].end,
|
11155 |
|
|
NULL);
|
11156 |
|
|
}
|
11157 |
|
|
}
|
11158 |
|
|
else
|
11159 |
|
|
{
|
11160 |
|
|
dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, NULL);
|
11161 |
|
|
dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, NULL);
|
11162 |
|
|
fmt = start_fmt;
|
11163 |
|
|
}
|
11164 |
|
|
}
|
11165 |
|
|
}
|
11166 |
|
|
|
11167 |
|
|
/* Data structure containing information about input files. */
|
11168 |
|
|
struct file_info
|
11169 |
|
|
{
|
11170 |
|
|
const char *path; /* Complete file name. */
|
11171 |
|
|
const char *fname; /* File name part. */
|
11172 |
|
|
int length; /* Length of entire string. */
|
11173 |
|
|
struct dwarf_file_data * file_idx; /* Index in input file table. */
|
11174 |
|
|
int dir_idx; /* Index in directory table. */
|
11175 |
|
|
};
|
11176 |
|
|
|
11177 |
|
|
/* Data structure containing information about directories with source
|
11178 |
|
|
files. */
|
11179 |
|
|
struct dir_info
|
11180 |
|
|
{
|
11181 |
|
|
const char *path; /* Path including directory name. */
|
11182 |
|
|
int length; /* Path length. */
|
11183 |
|
|
int prefix; /* Index of directory entry which is a prefix. */
|
11184 |
|
|
int count; /* Number of files in this directory. */
|
11185 |
|
|
int dir_idx; /* Index of directory used as base. */
|
11186 |
|
|
};
|
11187 |
|
|
|
11188 |
|
|
/* Callback function for file_info comparison. We sort by looking at
|
11189 |
|
|
the directories in the path. */
|
11190 |
|
|
|
11191 |
|
|
static int
|
11192 |
|
|
file_info_cmp (const void *p1, const void *p2)
|
11193 |
|
|
{
|
11194 |
|
|
const struct file_info *const s1 = (const struct file_info *) p1;
|
11195 |
|
|
const struct file_info *const s2 = (const struct file_info *) p2;
|
11196 |
|
|
const unsigned char *cp1;
|
11197 |
|
|
const unsigned char *cp2;
|
11198 |
|
|
|
11199 |
|
|
/* Take care of file names without directories. We need to make sure that
|
11200 |
|
|
we return consistent values to qsort since some will get confused if
|
11201 |
|
|
we return the same value when identical operands are passed in opposite
|
11202 |
|
|
orders. So if neither has a directory, return 0 and otherwise return
|
11203 |
|
|
1 or -1 depending on which one has the directory. */
|
11204 |
|
|
if ((s1->path == s1->fname || s2->path == s2->fname))
|
11205 |
|
|
return (s2->path == s2->fname) - (s1->path == s1->fname);
|
11206 |
|
|
|
11207 |
|
|
cp1 = (const unsigned char *) s1->path;
|
11208 |
|
|
cp2 = (const unsigned char *) s2->path;
|
11209 |
|
|
|
11210 |
|
|
while (1)
|
11211 |
|
|
{
|
11212 |
|
|
++cp1;
|
11213 |
|
|
++cp2;
|
11214 |
|
|
/* Reached the end of the first path? If so, handle like above. */
|
11215 |
|
|
if ((cp1 == (const unsigned char *) s1->fname)
|
11216 |
|
|
|| (cp2 == (const unsigned char *) s2->fname))
|
11217 |
|
|
return ((cp2 == (const unsigned char *) s2->fname)
|
11218 |
|
|
- (cp1 == (const unsigned char *) s1->fname));
|
11219 |
|
|
|
11220 |
|
|
/* Character of current path component the same? */
|
11221 |
|
|
else if (*cp1 != *cp2)
|
11222 |
|
|
return *cp1 - *cp2;
|
11223 |
|
|
}
|
11224 |
|
|
}
|
11225 |
|
|
|
11226 |
|
|
struct file_name_acquire_data
|
11227 |
|
|
{
|
11228 |
|
|
struct file_info *files;
|
11229 |
|
|
int used_files;
|
11230 |
|
|
int max_files;
|
11231 |
|
|
};
|
11232 |
|
|
|
11233 |
|
|
/* Traversal function for the hash table. */
|
11234 |
|
|
|
11235 |
|
|
static int
|
11236 |
|
|
file_name_acquire (void ** slot, void *data)
|
11237 |
|
|
{
|
11238 |
|
|
struct file_name_acquire_data *fnad = (struct file_name_acquire_data *) data;
|
11239 |
|
|
struct dwarf_file_data *d = (struct dwarf_file_data *) *slot;
|
11240 |
|
|
struct file_info *fi;
|
11241 |
|
|
const char *f;
|
11242 |
|
|
|
11243 |
|
|
gcc_assert (fnad->max_files >= d->emitted_number);
|
11244 |
|
|
|
11245 |
|
|
if (! d->emitted_number)
|
11246 |
|
|
return 1;
|
11247 |
|
|
|
11248 |
|
|
gcc_assert (fnad->max_files != fnad->used_files);
|
11249 |
|
|
|
11250 |
|
|
fi = fnad->files + fnad->used_files++;
|
11251 |
|
|
|
11252 |
|
|
/* Skip all leading "./". */
|
11253 |
|
|
f = d->filename;
|
11254 |
|
|
while (f[0] == '.' && IS_DIR_SEPARATOR (f[1]))
|
11255 |
|
|
f += 2;
|
11256 |
|
|
|
11257 |
|
|
/* Create a new array entry. */
|
11258 |
|
|
fi->path = f;
|
11259 |
|
|
fi->length = strlen (f);
|
11260 |
|
|
fi->file_idx = d;
|
11261 |
|
|
|
11262 |
|
|
/* Search for the file name part. */
|
11263 |
|
|
f = strrchr (f, DIR_SEPARATOR);
|
11264 |
|
|
#if defined (DIR_SEPARATOR_2)
|
11265 |
|
|
{
|
11266 |
|
|
char *g = strrchr (fi->path, DIR_SEPARATOR_2);
|
11267 |
|
|
|
11268 |
|
|
if (g != NULL)
|
11269 |
|
|
{
|
11270 |
|
|
if (f == NULL || f < g)
|
11271 |
|
|
f = g;
|
11272 |
|
|
}
|
11273 |
|
|
}
|
11274 |
|
|
#endif
|
11275 |
|
|
|
11276 |
|
|
fi->fname = f == NULL ? fi->path : f + 1;
|
11277 |
|
|
return 1;
|
11278 |
|
|
}
|
11279 |
|
|
|
11280 |
|
|
/* Output the directory table and the file name table. We try to minimize
|
11281 |
|
|
the total amount of memory needed. A heuristic is used to avoid large
|
11282 |
|
|
slowdowns with many input files. */
|
11283 |
|
|
|
11284 |
|
|
static void
|
11285 |
|
|
output_file_names (void)
|
11286 |
|
|
{
|
11287 |
|
|
struct file_name_acquire_data fnad;
|
11288 |
|
|
int numfiles;
|
11289 |
|
|
struct file_info *files;
|
11290 |
|
|
struct dir_info *dirs;
|
11291 |
|
|
int *saved;
|
11292 |
|
|
int *savehere;
|
11293 |
|
|
int *backmap;
|
11294 |
|
|
int ndirs;
|
11295 |
|
|
int idx_offset;
|
11296 |
|
|
int i;
|
11297 |
|
|
|
11298 |
|
|
if (!last_emitted_file)
|
11299 |
|
|
{
|
11300 |
|
|
dw2_asm_output_data (1, 0, "End directory table");
|
11301 |
|
|
dw2_asm_output_data (1, 0, "End file name table");
|
11302 |
|
|
return;
|
11303 |
|
|
}
|
11304 |
|
|
|
11305 |
|
|
numfiles = last_emitted_file->emitted_number;
|
11306 |
|
|
|
11307 |
|
|
/* Allocate the various arrays we need. */
|
11308 |
|
|
files = XALLOCAVEC (struct file_info, numfiles);
|
11309 |
|
|
dirs = XALLOCAVEC (struct dir_info, numfiles);
|
11310 |
|
|
|
11311 |
|
|
fnad.files = files;
|
11312 |
|
|
fnad.used_files = 0;
|
11313 |
|
|
fnad.max_files = numfiles;
|
11314 |
|
|
htab_traverse (file_table, file_name_acquire, &fnad);
|
11315 |
|
|
gcc_assert (fnad.used_files == fnad.max_files);
|
11316 |
|
|
|
11317 |
|
|
qsort (files, numfiles, sizeof (files[0]), file_info_cmp);
|
11318 |
|
|
|
11319 |
|
|
/* Find all the different directories used. */
|
11320 |
|
|
dirs[0].path = files[0].path;
|
11321 |
|
|
dirs[0].length = files[0].fname - files[0].path;
|
11322 |
|
|
dirs[0].prefix = -1;
|
11323 |
|
|
dirs[0].count = 1;
|
11324 |
|
|
dirs[0].dir_idx = 0;
|
11325 |
|
|
files[0].dir_idx = 0;
|
11326 |
|
|
ndirs = 1;
|
11327 |
|
|
|
11328 |
|
|
for (i = 1; i < numfiles; i++)
|
11329 |
|
|
if (files[i].fname - files[i].path == dirs[ndirs - 1].length
|
11330 |
|
|
&& memcmp (dirs[ndirs - 1].path, files[i].path,
|
11331 |
|
|
dirs[ndirs - 1].length) == 0)
|
11332 |
|
|
{
|
11333 |
|
|
/* Same directory as last entry. */
|
11334 |
|
|
files[i].dir_idx = ndirs - 1;
|
11335 |
|
|
++dirs[ndirs - 1].count;
|
11336 |
|
|
}
|
11337 |
|
|
else
|
11338 |
|
|
{
|
11339 |
|
|
int j;
|
11340 |
|
|
|
11341 |
|
|
/* This is a new directory. */
|
11342 |
|
|
dirs[ndirs].path = files[i].path;
|
11343 |
|
|
dirs[ndirs].length = files[i].fname - files[i].path;
|
11344 |
|
|
dirs[ndirs].count = 1;
|
11345 |
|
|
dirs[ndirs].dir_idx = ndirs;
|
11346 |
|
|
files[i].dir_idx = ndirs;
|
11347 |
|
|
|
11348 |
|
|
/* Search for a prefix. */
|
11349 |
|
|
dirs[ndirs].prefix = -1;
|
11350 |
|
|
for (j = 0; j < ndirs; j++)
|
11351 |
|
|
if (dirs[j].length < dirs[ndirs].length
|
11352 |
|
|
&& dirs[j].length > 1
|
11353 |
|
|
&& (dirs[ndirs].prefix == -1
|
11354 |
|
|
|| dirs[j].length > dirs[dirs[ndirs].prefix].length)
|
11355 |
|
|
&& memcmp (dirs[j].path, dirs[ndirs].path, dirs[j].length) == 0)
|
11356 |
|
|
dirs[ndirs].prefix = j;
|
11357 |
|
|
|
11358 |
|
|
++ndirs;
|
11359 |
|
|
}
|
11360 |
|
|
|
11361 |
|
|
/* Now to the actual work. We have to find a subset of the directories which
|
11362 |
|
|
allow expressing the file name using references to the directory table
|
11363 |
|
|
with the least amount of characters. We do not do an exhaustive search
|
11364 |
|
|
where we would have to check out every combination of every single
|
11365 |
|
|
possible prefix. Instead we use a heuristic which provides nearly optimal
|
11366 |
|
|
results in most cases and never is much off. */
|
11367 |
|
|
saved = XALLOCAVEC (int, ndirs);
|
11368 |
|
|
savehere = XALLOCAVEC (int, ndirs);
|
11369 |
|
|
|
11370 |
|
|
memset (saved, '\0', ndirs * sizeof (saved[0]));
|
11371 |
|
|
for (i = 0; i < ndirs; i++)
|
11372 |
|
|
{
|
11373 |
|
|
int j;
|
11374 |
|
|
int total;
|
11375 |
|
|
|
11376 |
|
|
/* We can always save some space for the current directory. But this
|
11377 |
|
|
does not mean it will be enough to justify adding the directory. */
|
11378 |
|
|
savehere[i] = dirs[i].length;
|
11379 |
|
|
total = (savehere[i] - saved[i]) * dirs[i].count;
|
11380 |
|
|
|
11381 |
|
|
for (j = i + 1; j < ndirs; j++)
|
11382 |
|
|
{
|
11383 |
|
|
savehere[j] = 0;
|
11384 |
|
|
if (saved[j] < dirs[i].length)
|
11385 |
|
|
{
|
11386 |
|
|
/* Determine whether the dirs[i] path is a prefix of the
|
11387 |
|
|
dirs[j] path. */
|
11388 |
|
|
int k;
|
11389 |
|
|
|
11390 |
|
|
k = dirs[j].prefix;
|
11391 |
|
|
while (k != -1 && k != (int) i)
|
11392 |
|
|
k = dirs[k].prefix;
|
11393 |
|
|
|
11394 |
|
|
if (k == (int) i)
|
11395 |
|
|
{
|
11396 |
|
|
/* Yes it is. We can possibly save some memory by
|
11397 |
|
|
writing the filenames in dirs[j] relative to
|
11398 |
|
|
dirs[i]. */
|
11399 |
|
|
savehere[j] = dirs[i].length;
|
11400 |
|
|
total += (savehere[j] - saved[j]) * dirs[j].count;
|
11401 |
|
|
}
|
11402 |
|
|
}
|
11403 |
|
|
}
|
11404 |
|
|
|
11405 |
|
|
/* Check whether we can save enough to justify adding the dirs[i]
|
11406 |
|
|
directory. */
|
11407 |
|
|
if (total > dirs[i].length + 1)
|
11408 |
|
|
{
|
11409 |
|
|
/* It's worthwhile adding. */
|
11410 |
|
|
for (j = i; j < ndirs; j++)
|
11411 |
|
|
if (savehere[j] > 0)
|
11412 |
|
|
{
|
11413 |
|
|
/* Remember how much we saved for this directory so far. */
|
11414 |
|
|
saved[j] = savehere[j];
|
11415 |
|
|
|
11416 |
|
|
/* Remember the prefix directory. */
|
11417 |
|
|
dirs[j].dir_idx = i;
|
11418 |
|
|
}
|
11419 |
|
|
}
|
11420 |
|
|
}
|
11421 |
|
|
|
11422 |
|
|
/* Emit the directory name table. */
|
11423 |
|
|
idx_offset = dirs[0].length > 0 ? 1 : 0;
|
11424 |
|
|
for (i = 1 - idx_offset; i < ndirs; i++)
|
11425 |
|
|
dw2_asm_output_nstring (dirs[i].path,
|
11426 |
|
|
dirs[i].length
|
11427 |
|
|
- !DWARF2_DIR_SHOULD_END_WITH_SEPARATOR,
|
11428 |
|
|
"Directory Entry: 0x%x", i + idx_offset);
|
11429 |
|
|
|
11430 |
|
|
dw2_asm_output_data (1, 0, "End directory table");
|
11431 |
|
|
|
11432 |
|
|
/* We have to emit them in the order of emitted_number since that's
|
11433 |
|
|
used in the debug info generation. To do this efficiently we
|
11434 |
|
|
generate a back-mapping of the indices first. */
|
11435 |
|
|
backmap = XALLOCAVEC (int, numfiles);
|
11436 |
|
|
for (i = 0; i < numfiles; i++)
|
11437 |
|
|
backmap[files[i].file_idx->emitted_number - 1] = i;
|
11438 |
|
|
|
11439 |
|
|
/* Now write all the file names. */
|
11440 |
|
|
for (i = 0; i < numfiles; i++)
|
11441 |
|
|
{
|
11442 |
|
|
int file_idx = backmap[i];
|
11443 |
|
|
int dir_idx = dirs[files[file_idx].dir_idx].dir_idx;
|
11444 |
|
|
|
11445 |
|
|
#ifdef VMS_DEBUGGING_INFO
|
11446 |
|
|
#define MAX_VMS_VERSION_LEN 6 /* ";32768" */
|
11447 |
|
|
|
11448 |
|
|
/* Setting these fields can lead to debugger miscomparisons,
|
11449 |
|
|
but VMS Debug requires them to be set correctly. */
|
11450 |
|
|
|
11451 |
|
|
int ver;
|
11452 |
|
|
long long cdt;
|
11453 |
|
|
long siz;
|
11454 |
|
|
int maxfilelen = strlen (files[file_idx].path)
|
11455 |
|
|
+ dirs[dir_idx].length
|
11456 |
|
|
+ MAX_VMS_VERSION_LEN + 1;
|
11457 |
|
|
char *filebuf = XALLOCAVEC (char, maxfilelen);
|
11458 |
|
|
|
11459 |
|
|
vms_file_stats_name (files[file_idx].path, 0, 0, 0, &ver);
|
11460 |
|
|
snprintf (filebuf, maxfilelen, "%s;%d",
|
11461 |
|
|
files[file_idx].path + dirs[dir_idx].length, ver);
|
11462 |
|
|
|
11463 |
|
|
dw2_asm_output_nstring
|
11464 |
|
|
(filebuf, -1, "File Entry: 0x%x", (unsigned) i + 1);
|
11465 |
|
|
|
11466 |
|
|
/* Include directory index. */
|
11467 |
|
|
dw2_asm_output_data_uleb128 (dir_idx + idx_offset, NULL);
|
11468 |
|
|
|
11469 |
|
|
/* Modification time. */
|
11470 |
|
|
dw2_asm_output_data_uleb128
|
11471 |
|
|
((vms_file_stats_name (files[file_idx].path, &cdt, 0, 0, 0) == 0)
|
11472 |
|
|
? cdt : 0,
|
11473 |
|
|
NULL);
|
11474 |
|
|
|
11475 |
|
|
/* File length in bytes. */
|
11476 |
|
|
dw2_asm_output_data_uleb128
|
11477 |
|
|
((vms_file_stats_name (files[file_idx].path, 0, &siz, 0, 0) == 0)
|
11478 |
|
|
? siz : 0,
|
11479 |
|
|
NULL);
|
11480 |
|
|
#else
|
11481 |
|
|
dw2_asm_output_nstring (files[file_idx].path + dirs[dir_idx].length, -1,
|
11482 |
|
|
"File Entry: 0x%x", (unsigned) i + 1);
|
11483 |
|
|
|
11484 |
|
|
/* Include directory index. */
|
11485 |
|
|
dw2_asm_output_data_uleb128 (dir_idx + idx_offset, NULL);
|
11486 |
|
|
|
11487 |
|
|
/* Modification time. */
|
11488 |
|
|
dw2_asm_output_data_uleb128 (0, NULL);
|
11489 |
|
|
|
11490 |
|
|
/* File length in bytes. */
|
11491 |
|
|
dw2_asm_output_data_uleb128 (0, NULL);
|
11492 |
|
|
#endif
|
11493 |
|
|
}
|
11494 |
|
|
|
11495 |
|
|
dw2_asm_output_data (1, 0, "End file name table");
|
11496 |
|
|
}
|
11497 |
|
|
|
11498 |
|
|
|
11499 |
|
|
/* Output the source line number correspondence information. This
|
11500 |
|
|
information goes into the .debug_line section. */
|
11501 |
|
|
|
11502 |
|
|
static void
|
11503 |
|
|
output_line_info (void)
|
11504 |
|
|
{
|
11505 |
|
|
char l1[20], l2[20], p1[20], p2[20];
|
11506 |
|
|
char line_label[MAX_ARTIFICIAL_LABEL_BYTES];
|
11507 |
|
|
char prev_line_label[MAX_ARTIFICIAL_LABEL_BYTES];
|
11508 |
|
|
unsigned opc;
|
11509 |
|
|
unsigned n_op_args;
|
11510 |
|
|
unsigned long lt_index;
|
11511 |
|
|
unsigned long current_line;
|
11512 |
|
|
long line_offset;
|
11513 |
|
|
long line_delta;
|
11514 |
|
|
unsigned long current_file;
|
11515 |
|
|
unsigned long function;
|
11516 |
|
|
int ver = dwarf_version;
|
11517 |
|
|
|
11518 |
|
|
ASM_GENERATE_INTERNAL_LABEL (l1, LINE_NUMBER_BEGIN_LABEL, 0);
|
11519 |
|
|
ASM_GENERATE_INTERNAL_LABEL (l2, LINE_NUMBER_END_LABEL, 0);
|
11520 |
|
|
ASM_GENERATE_INTERNAL_LABEL (p1, LN_PROLOG_AS_LABEL, 0);
|
11521 |
|
|
ASM_GENERATE_INTERNAL_LABEL (p2, LN_PROLOG_END_LABEL, 0);
|
11522 |
|
|
|
11523 |
|
|
if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
|
11524 |
|
|
dw2_asm_output_data (4, 0xffffffff,
|
11525 |
|
|
"Initial length escape value indicating 64-bit DWARF extension");
|
11526 |
|
|
dw2_asm_output_delta (DWARF_OFFSET_SIZE, l2, l1,
|
11527 |
|
|
"Length of Source Line Info");
|
11528 |
|
|
ASM_OUTPUT_LABEL (asm_out_file, l1);
|
11529 |
|
|
|
11530 |
|
|
dw2_asm_output_data (2, ver, "DWARF Version");
|
11531 |
|
|
dw2_asm_output_delta (DWARF_OFFSET_SIZE, p2, p1, "Prolog Length");
|
11532 |
|
|
ASM_OUTPUT_LABEL (asm_out_file, p1);
|
11533 |
|
|
|
11534 |
|
|
/* Define the architecture-dependent minimum instruction length (in
|
11535 |
|
|
bytes). In this implementation of DWARF, this field is used for
|
11536 |
|
|
information purposes only. Since GCC generates assembly language,
|
11537 |
|
|
we have no a priori knowledge of how many instruction bytes are
|
11538 |
|
|
generated for each source line, and therefore can use only the
|
11539 |
|
|
DW_LNE_set_address and DW_LNS_fixed_advance_pc line information
|
11540 |
|
|
commands. Accordingly, we fix this as `1', which is "correct
|
11541 |
|
|
enough" for all architectures, and don't let the target override. */
|
11542 |
|
|
dw2_asm_output_data (1, 1,
|
11543 |
|
|
"Minimum Instruction Length");
|
11544 |
|
|
|
11545 |
|
|
if (ver >= 4)
|
11546 |
|
|
dw2_asm_output_data (1, DWARF_LINE_DEFAULT_MAX_OPS_PER_INSN,
|
11547 |
|
|
"Maximum Operations Per Instruction");
|
11548 |
|
|
dw2_asm_output_data (1, DWARF_LINE_DEFAULT_IS_STMT_START,
|
11549 |
|
|
"Default is_stmt_start flag");
|
11550 |
|
|
dw2_asm_output_data (1, DWARF_LINE_BASE,
|
11551 |
|
|
"Line Base Value (Special Opcodes)");
|
11552 |
|
|
dw2_asm_output_data (1, DWARF_LINE_RANGE,
|
11553 |
|
|
"Line Range Value (Special Opcodes)");
|
11554 |
|
|
dw2_asm_output_data (1, DWARF_LINE_OPCODE_BASE,
|
11555 |
|
|
"Special Opcode Base");
|
11556 |
|
|
|
11557 |
|
|
for (opc = 1; opc < DWARF_LINE_OPCODE_BASE; opc++)
|
11558 |
|
|
{
|
11559 |
|
|
switch (opc)
|
11560 |
|
|
{
|
11561 |
|
|
case DW_LNS_advance_pc:
|
11562 |
|
|
case DW_LNS_advance_line:
|
11563 |
|
|
case DW_LNS_set_file:
|
11564 |
|
|
case DW_LNS_set_column:
|
11565 |
|
|
case DW_LNS_fixed_advance_pc:
|
11566 |
|
|
n_op_args = 1;
|
11567 |
|
|
break;
|
11568 |
|
|
default:
|
11569 |
|
|
n_op_args = 0;
|
11570 |
|
|
break;
|
11571 |
|
|
}
|
11572 |
|
|
|
11573 |
|
|
dw2_asm_output_data (1, n_op_args, "opcode: 0x%x has %d args",
|
11574 |
|
|
opc, n_op_args);
|
11575 |
|
|
}
|
11576 |
|
|
|
11577 |
|
|
/* Write out the information about the files we use. */
|
11578 |
|
|
output_file_names ();
|
11579 |
|
|
ASM_OUTPUT_LABEL (asm_out_file, p2);
|
11580 |
|
|
|
11581 |
|
|
/* We used to set the address register to the first location in the text
|
11582 |
|
|
section here, but that didn't accomplish anything since we already
|
11583 |
|
|
have a line note for the opening brace of the first function. */
|
11584 |
|
|
|
11585 |
|
|
/* Generate the line number to PC correspondence table, encoded as
|
11586 |
|
|
a series of state machine operations. */
|
11587 |
|
|
current_file = 1;
|
11588 |
|
|
current_line = 1;
|
11589 |
|
|
|
11590 |
|
|
if (cfun && in_cold_section_p)
|
11591 |
|
|
strcpy (prev_line_label, crtl->subsections.cold_section_label);
|
11592 |
|
|
else
|
11593 |
|
|
strcpy (prev_line_label, text_section_label);
|
11594 |
|
|
for (lt_index = 1; lt_index < line_info_table_in_use; ++lt_index)
|
11595 |
|
|
{
|
11596 |
|
|
dw_line_info_ref line_info = &line_info_table[lt_index];
|
11597 |
|
|
|
11598 |
|
|
#if 0
|
11599 |
|
|
/* Disable this optimization for now; GDB wants to see two line notes
|
11600 |
|
|
at the beginning of a function so it can find the end of the
|
11601 |
|
|
prologue. */
|
11602 |
|
|
|
11603 |
|
|
/* Don't emit anything for redundant notes. Just updating the
|
11604 |
|
|
address doesn't accomplish anything, because we already assume
|
11605 |
|
|
that anything after the last address is this line. */
|
11606 |
|
|
if (line_info->dw_line_num == current_line
|
11607 |
|
|
&& line_info->dw_file_num == current_file)
|
11608 |
|
|
continue;
|
11609 |
|
|
#endif
|
11610 |
|
|
|
11611 |
|
|
/* Emit debug info for the address of the current line.
|
11612 |
|
|
|
11613 |
|
|
Unfortunately, we have little choice here currently, and must always
|
11614 |
|
|
use the most general form. GCC does not know the address delta
|
11615 |
|
|
itself, so we can't use DW_LNS_advance_pc. Many ports do have length
|
11616 |
|
|
attributes which will give an upper bound on the address range. We
|
11617 |
|
|
could perhaps use length attributes to determine when it is safe to
|
11618 |
|
|
use DW_LNS_fixed_advance_pc. */
|
11619 |
|
|
|
11620 |
|
|
ASM_GENERATE_INTERNAL_LABEL (line_label, LINE_CODE_LABEL, lt_index);
|
11621 |
|
|
if (0)
|
11622 |
|
|
{
|
11623 |
|
|
/* This can handle deltas up to 0xffff. This takes 3 bytes. */
|
11624 |
|
|
dw2_asm_output_data (1, DW_LNS_fixed_advance_pc,
|
11625 |
|
|
"DW_LNS_fixed_advance_pc");
|
11626 |
|
|
dw2_asm_output_delta (2, line_label, prev_line_label, NULL);
|
11627 |
|
|
}
|
11628 |
|
|
else
|
11629 |
|
|
{
|
11630 |
|
|
/* This can handle any delta. This takes
|
11631 |
|
|
4+DWARF2_ADDR_SIZE bytes. */
|
11632 |
|
|
dw2_asm_output_data (1, 0, "DW_LNE_set_address");
|
11633 |
|
|
dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL);
|
11634 |
|
|
dw2_asm_output_data (1, DW_LNE_set_address, NULL);
|
11635 |
|
|
dw2_asm_output_addr (DWARF2_ADDR_SIZE, line_label, NULL);
|
11636 |
|
|
}
|
11637 |
|
|
|
11638 |
|
|
strcpy (prev_line_label, line_label);
|
11639 |
|
|
|
11640 |
|
|
/* Emit debug info for the source file of the current line, if
|
11641 |
|
|
different from the previous line. */
|
11642 |
|
|
if (line_info->dw_file_num != current_file)
|
11643 |
|
|
{
|
11644 |
|
|
current_file = line_info->dw_file_num;
|
11645 |
|
|
dw2_asm_output_data (1, DW_LNS_set_file, "DW_LNS_set_file");
|
11646 |
|
|
dw2_asm_output_data_uleb128 (current_file, "%lu", current_file);
|
11647 |
|
|
}
|
11648 |
|
|
|
11649 |
|
|
/* Emit debug info for the current line number, choosing the encoding
|
11650 |
|
|
that uses the least amount of space. */
|
11651 |
|
|
if (line_info->dw_line_num != current_line)
|
11652 |
|
|
{
|
11653 |
|
|
line_offset = line_info->dw_line_num - current_line;
|
11654 |
|
|
line_delta = line_offset - DWARF_LINE_BASE;
|
11655 |
|
|
current_line = line_info->dw_line_num;
|
11656 |
|
|
if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1))
|
11657 |
|
|
/* This can handle deltas from -10 to 234, using the current
|
11658 |
|
|
definitions of DWARF_LINE_BASE and DWARF_LINE_RANGE. This
|
11659 |
|
|
takes 1 byte. */
|
11660 |
|
|
dw2_asm_output_data (1, DWARF_LINE_OPCODE_BASE + line_delta,
|
11661 |
|
|
"line %lu", current_line);
|
11662 |
|
|
else
|
11663 |
|
|
{
|
11664 |
|
|
/* This can handle any delta. This takes at least 4 bytes,
|
11665 |
|
|
depending on the value being encoded. */
|
11666 |
|
|
dw2_asm_output_data (1, DW_LNS_advance_line,
|
11667 |
|
|
"advance to line %lu", current_line);
|
11668 |
|
|
dw2_asm_output_data_sleb128 (line_offset, NULL);
|
11669 |
|
|
dw2_asm_output_data (1, DW_LNS_copy, "DW_LNS_copy");
|
11670 |
|
|
}
|
11671 |
|
|
}
|
11672 |
|
|
else
|
11673 |
|
|
/* We still need to start a new row, so output a copy insn. */
|
11674 |
|
|
dw2_asm_output_data (1, DW_LNS_copy, "DW_LNS_copy");
|
11675 |
|
|
}
|
11676 |
|
|
|
11677 |
|
|
/* Emit debug info for the address of the end of the function. */
|
11678 |
|
|
if (0)
|
11679 |
|
|
{
|
11680 |
|
|
dw2_asm_output_data (1, DW_LNS_fixed_advance_pc,
|
11681 |
|
|
"DW_LNS_fixed_advance_pc");
|
11682 |
|
|
dw2_asm_output_delta (2, text_end_label, prev_line_label, NULL);
|
11683 |
|
|
}
|
11684 |
|
|
else
|
11685 |
|
|
{
|
11686 |
|
|
dw2_asm_output_data (1, 0, "DW_LNE_set_address");
|
11687 |
|
|
dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL);
|
11688 |
|
|
dw2_asm_output_data (1, DW_LNE_set_address, NULL);
|
11689 |
|
|
dw2_asm_output_addr (DWARF2_ADDR_SIZE, text_end_label, NULL);
|
11690 |
|
|
}
|
11691 |
|
|
|
11692 |
|
|
dw2_asm_output_data (1, 0, "DW_LNE_end_sequence");
|
11693 |
|
|
dw2_asm_output_data_uleb128 (1, NULL);
|
11694 |
|
|
dw2_asm_output_data (1, DW_LNE_end_sequence, NULL);
|
11695 |
|
|
|
11696 |
|
|
function = 0;
|
11697 |
|
|
current_file = 1;
|
11698 |
|
|
current_line = 1;
|
11699 |
|
|
for (lt_index = 0; lt_index < separate_line_info_table_in_use;)
|
11700 |
|
|
{
|
11701 |
|
|
dw_separate_line_info_ref line_info
|
11702 |
|
|
= &separate_line_info_table[lt_index];
|
11703 |
|
|
|
11704 |
|
|
#if 0
|
11705 |
|
|
/* Don't emit anything for redundant notes. */
|
11706 |
|
|
if (line_info->dw_line_num == current_line
|
11707 |
|
|
&& line_info->dw_file_num == current_file
|
11708 |
|
|
&& line_info->function == function)
|
11709 |
|
|
goto cont;
|
11710 |
|
|
#endif
|
11711 |
|
|
|
11712 |
|
|
/* Emit debug info for the address of the current line. If this is
|
11713 |
|
|
a new function, or the first line of a function, then we need
|
11714 |
|
|
to handle it differently. */
|
11715 |
|
|
ASM_GENERATE_INTERNAL_LABEL (line_label, SEPARATE_LINE_CODE_LABEL,
|
11716 |
|
|
lt_index);
|
11717 |
|
|
if (function != line_info->function)
|
11718 |
|
|
{
|
11719 |
|
|
function = line_info->function;
|
11720 |
|
|
|
11721 |
|
|
/* Set the address register to the first line in the function. */
|
11722 |
|
|
dw2_asm_output_data (1, 0, "DW_LNE_set_address");
|
11723 |
|
|
dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL);
|
11724 |
|
|
dw2_asm_output_data (1, DW_LNE_set_address, NULL);
|
11725 |
|
|
dw2_asm_output_addr (DWARF2_ADDR_SIZE, line_label, NULL);
|
11726 |
|
|
}
|
11727 |
|
|
else
|
11728 |
|
|
{
|
11729 |
|
|
/* ??? See the DW_LNS_advance_pc comment above. */
|
11730 |
|
|
if (0)
|
11731 |
|
|
{
|
11732 |
|
|
dw2_asm_output_data (1, DW_LNS_fixed_advance_pc,
|
11733 |
|
|
"DW_LNS_fixed_advance_pc");
|
11734 |
|
|
dw2_asm_output_delta (2, line_label, prev_line_label, NULL);
|
11735 |
|
|
}
|
11736 |
|
|
else
|
11737 |
|
|
{
|
11738 |
|
|
dw2_asm_output_data (1, 0, "DW_LNE_set_address");
|
11739 |
|
|
dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL);
|
11740 |
|
|
dw2_asm_output_data (1, DW_LNE_set_address, NULL);
|
11741 |
|
|
dw2_asm_output_addr (DWARF2_ADDR_SIZE, line_label, NULL);
|
11742 |
|
|
}
|
11743 |
|
|
}
|
11744 |
|
|
|
11745 |
|
|
strcpy (prev_line_label, line_label);
|
11746 |
|
|
|
11747 |
|
|
/* Emit debug info for the source file of the current line, if
|
11748 |
|
|
different from the previous line. */
|
11749 |
|
|
if (line_info->dw_file_num != current_file)
|
11750 |
|
|
{
|
11751 |
|
|
current_file = line_info->dw_file_num;
|
11752 |
|
|
dw2_asm_output_data (1, DW_LNS_set_file, "DW_LNS_set_file");
|
11753 |
|
|
dw2_asm_output_data_uleb128 (current_file, "%lu", current_file);
|
11754 |
|
|
}
|
11755 |
|
|
|
11756 |
|
|
/* Emit debug info for the current line number, choosing the encoding
|
11757 |
|
|
that uses the least amount of space. */
|
11758 |
|
|
if (line_info->dw_line_num != current_line)
|
11759 |
|
|
{
|
11760 |
|
|
line_offset = line_info->dw_line_num - current_line;
|
11761 |
|
|
line_delta = line_offset - DWARF_LINE_BASE;
|
11762 |
|
|
current_line = line_info->dw_line_num;
|
11763 |
|
|
if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1))
|
11764 |
|
|
dw2_asm_output_data (1, DWARF_LINE_OPCODE_BASE + line_delta,
|
11765 |
|
|
"line %lu", current_line);
|
11766 |
|
|
else
|
11767 |
|
|
{
|
11768 |
|
|
dw2_asm_output_data (1, DW_LNS_advance_line,
|
11769 |
|
|
"advance to line %lu", current_line);
|
11770 |
|
|
dw2_asm_output_data_sleb128 (line_offset, NULL);
|
11771 |
|
|
dw2_asm_output_data (1, DW_LNS_copy, "DW_LNS_copy");
|
11772 |
|
|
}
|
11773 |
|
|
}
|
11774 |
|
|
else
|
11775 |
|
|
dw2_asm_output_data (1, DW_LNS_copy, "DW_LNS_copy");
|
11776 |
|
|
|
11777 |
|
|
#if 0
|
11778 |
|
|
cont:
|
11779 |
|
|
#endif
|
11780 |
|
|
|
11781 |
|
|
lt_index++;
|
11782 |
|
|
|
11783 |
|
|
/* If we're done with a function, end its sequence. */
|
11784 |
|
|
if (lt_index == separate_line_info_table_in_use
|
11785 |
|
|
|| separate_line_info_table[lt_index].function != function)
|
11786 |
|
|
{
|
11787 |
|
|
current_file = 1;
|
11788 |
|
|
current_line = 1;
|
11789 |
|
|
|
11790 |
|
|
/* Emit debug info for the address of the end of the function. */
|
11791 |
|
|
ASM_GENERATE_INTERNAL_LABEL (line_label, FUNC_END_LABEL, function);
|
11792 |
|
|
if (0)
|
11793 |
|
|
{
|
11794 |
|
|
dw2_asm_output_data (1, DW_LNS_fixed_advance_pc,
|
11795 |
|
|
"DW_LNS_fixed_advance_pc");
|
11796 |
|
|
dw2_asm_output_delta (2, line_label, prev_line_label, NULL);
|
11797 |
|
|
}
|
11798 |
|
|
else
|
11799 |
|
|
{
|
11800 |
|
|
dw2_asm_output_data (1, 0, "DW_LNE_set_address");
|
11801 |
|
|
dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL);
|
11802 |
|
|
dw2_asm_output_data (1, DW_LNE_set_address, NULL);
|
11803 |
|
|
dw2_asm_output_addr (DWARF2_ADDR_SIZE, line_label, NULL);
|
11804 |
|
|
}
|
11805 |
|
|
|
11806 |
|
|
/* Output the marker for the end of this sequence. */
|
11807 |
|
|
dw2_asm_output_data (1, 0, "DW_LNE_end_sequence");
|
11808 |
|
|
dw2_asm_output_data_uleb128 (1, NULL);
|
11809 |
|
|
dw2_asm_output_data (1, DW_LNE_end_sequence, NULL);
|
11810 |
|
|
}
|
11811 |
|
|
}
|
11812 |
|
|
|
11813 |
|
|
/* Output the marker for the end of the line number info. */
|
11814 |
|
|
ASM_OUTPUT_LABEL (asm_out_file, l2);
|
11815 |
|
|
}
|
11816 |
|
|
|
11817 |
|
|
/* Return the size of the .debug_dcall table for the compilation unit. */
|
11818 |
|
|
|
11819 |
|
|
static unsigned long
|
11820 |
|
|
size_of_dcall_table (void)
|
11821 |
|
|
{
|
11822 |
|
|
unsigned long size;
|
11823 |
|
|
unsigned int i;
|
11824 |
|
|
dcall_entry *p;
|
11825 |
|
|
tree last_poc_decl = NULL;
|
11826 |
|
|
|
11827 |
|
|
/* Header: version + debug info section pointer + pointer size. */
|
11828 |
|
|
size = 2 + DWARF_OFFSET_SIZE + 1;
|
11829 |
|
|
|
11830 |
|
|
/* Each entry: code label + DIE offset. */
|
11831 |
|
|
for (i = 0; VEC_iterate (dcall_entry, dcall_table, i, p); i++)
|
11832 |
|
|
{
|
11833 |
|
|
gcc_assert (p->targ_die != NULL);
|
11834 |
|
|
/* Insert a "from" entry when the point-of-call DIE offset changes. */
|
11835 |
|
|
if (p->poc_decl != last_poc_decl)
|
11836 |
|
|
{
|
11837 |
|
|
dw_die_ref poc_die = lookup_decl_die (p->poc_decl);
|
11838 |
|
|
gcc_assert (poc_die);
|
11839 |
|
|
last_poc_decl = p->poc_decl;
|
11840 |
|
|
if (poc_die)
|
11841 |
|
|
size += (DWARF_OFFSET_SIZE
|
11842 |
|
|
+ size_of_uleb128 (poc_die->die_offset));
|
11843 |
|
|
}
|
11844 |
|
|
size += DWARF_OFFSET_SIZE + size_of_uleb128 (p->targ_die->die_offset);
|
11845 |
|
|
}
|
11846 |
|
|
|
11847 |
|
|
return size;
|
11848 |
|
|
}
|
11849 |
|
|
|
11850 |
|
|
/* Output the direct call table used to disambiguate PC values when
|
11851 |
|
|
identical function have been merged. */
|
11852 |
|
|
|
11853 |
|
|
static void
|
11854 |
|
|
output_dcall_table (void)
|
11855 |
|
|
{
|
11856 |
|
|
unsigned i;
|
11857 |
|
|
unsigned long dcall_length = size_of_dcall_table ();
|
11858 |
|
|
dcall_entry *p;
|
11859 |
|
|
char poc_label[MAX_ARTIFICIAL_LABEL_BYTES];
|
11860 |
|
|
tree last_poc_decl = NULL;
|
11861 |
|
|
|
11862 |
|
|
if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
|
11863 |
|
|
dw2_asm_output_data (4, 0xffffffff,
|
11864 |
|
|
"Initial length escape value indicating 64-bit DWARF extension");
|
11865 |
|
|
dw2_asm_output_data (DWARF_OFFSET_SIZE, dcall_length,
|
11866 |
|
|
"Length of Direct Call Table");
|
11867 |
|
|
dw2_asm_output_data (2, 4, "Version number");
|
11868 |
|
|
dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_info_section_label,
|
11869 |
|
|
debug_info_section,
|
11870 |
|
|
"Offset of Compilation Unit Info");
|
11871 |
|
|
dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Pointer Size (in bytes)");
|
11872 |
|
|
|
11873 |
|
|
for (i = 0; VEC_iterate (dcall_entry, dcall_table, i, p); i++)
|
11874 |
|
|
{
|
11875 |
|
|
/* Insert a "from" entry when the point-of-call DIE offset changes. */
|
11876 |
|
|
if (p->poc_decl != last_poc_decl)
|
11877 |
|
|
{
|
11878 |
|
|
dw_die_ref poc_die = lookup_decl_die (p->poc_decl);
|
11879 |
|
|
last_poc_decl = p->poc_decl;
|
11880 |
|
|
if (poc_die)
|
11881 |
|
|
{
|
11882 |
|
|
dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, "New caller");
|
11883 |
|
|
dw2_asm_output_data_uleb128 (poc_die->die_offset,
|
11884 |
|
|
"Caller DIE offset");
|
11885 |
|
|
}
|
11886 |
|
|
}
|
11887 |
|
|
ASM_GENERATE_INTERNAL_LABEL (poc_label, "LPOC", p->poc_label_num);
|
11888 |
|
|
dw2_asm_output_addr (DWARF_OFFSET_SIZE, poc_label, "Point of call");
|
11889 |
|
|
dw2_asm_output_data_uleb128 (p->targ_die->die_offset,
|
11890 |
|
|
"Callee DIE offset");
|
11891 |
|
|
}
|
11892 |
|
|
}
|
11893 |
|
|
|
11894 |
|
|
/* Return the size of the .debug_vcall table for the compilation unit. */
|
11895 |
|
|
|
11896 |
|
|
static unsigned long
|
11897 |
|
|
size_of_vcall_table (void)
|
11898 |
|
|
{
|
11899 |
|
|
unsigned long size;
|
11900 |
|
|
unsigned int i;
|
11901 |
|
|
vcall_entry *p;
|
11902 |
|
|
|
11903 |
|
|
/* Header: version + pointer size. */
|
11904 |
|
|
size = 2 + 1;
|
11905 |
|
|
|
11906 |
|
|
/* Each entry: code label + vtable slot index. */
|
11907 |
|
|
for (i = 0; VEC_iterate (vcall_entry, vcall_table, i, p); i++)
|
11908 |
|
|
size += DWARF_OFFSET_SIZE + size_of_uleb128 (p->vtable_slot);
|
11909 |
|
|
|
11910 |
|
|
return size;
|
11911 |
|
|
}
|
11912 |
|
|
|
11913 |
|
|
/* Output the virtual call table used to disambiguate PC values when
|
11914 |
|
|
identical function have been merged. */
|
11915 |
|
|
|
11916 |
|
|
static void
|
11917 |
|
|
output_vcall_table (void)
|
11918 |
|
|
{
|
11919 |
|
|
unsigned i;
|
11920 |
|
|
unsigned long vcall_length = size_of_vcall_table ();
|
11921 |
|
|
vcall_entry *p;
|
11922 |
|
|
char poc_label[MAX_ARTIFICIAL_LABEL_BYTES];
|
11923 |
|
|
|
11924 |
|
|
if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
|
11925 |
|
|
dw2_asm_output_data (4, 0xffffffff,
|
11926 |
|
|
"Initial length escape value indicating 64-bit DWARF extension");
|
11927 |
|
|
dw2_asm_output_data (DWARF_OFFSET_SIZE, vcall_length,
|
11928 |
|
|
"Length of Virtual Call Table");
|
11929 |
|
|
dw2_asm_output_data (2, 4, "Version number");
|
11930 |
|
|
dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Pointer Size (in bytes)");
|
11931 |
|
|
|
11932 |
|
|
for (i = 0; VEC_iterate (vcall_entry, vcall_table, i, p); i++)
|
11933 |
|
|
{
|
11934 |
|
|
ASM_GENERATE_INTERNAL_LABEL (poc_label, "LPOC", p->poc_label_num);
|
11935 |
|
|
dw2_asm_output_addr (DWARF_OFFSET_SIZE, poc_label, "Point of call");
|
11936 |
|
|
dw2_asm_output_data_uleb128 (p->vtable_slot, "Vtable slot");
|
11937 |
|
|
}
|
11938 |
|
|
}
|
11939 |
|
|
|
11940 |
|
|
/* Given a pointer to a tree node for some base type, return a pointer to
|
11941 |
|
|
a DIE that describes the given type.
|
11942 |
|
|
|
11943 |
|
|
This routine must only be called for GCC type nodes that correspond to
|
11944 |
|
|
Dwarf base (fundamental) types. */
|
11945 |
|
|
|
11946 |
|
|
static dw_die_ref
|
11947 |
|
|
base_type_die (tree type)
|
11948 |
|
|
{
|
11949 |
|
|
dw_die_ref base_type_result;
|
11950 |
|
|
enum dwarf_type encoding;
|
11951 |
|
|
|
11952 |
|
|
if (TREE_CODE (type) == ERROR_MARK || TREE_CODE (type) == VOID_TYPE)
|
11953 |
|
|
return 0;
|
11954 |
|
|
|
11955 |
|
|
/* If this is a subtype that should not be emitted as a subrange type,
|
11956 |
|
|
use the base type. See subrange_type_for_debug_p. */
|
11957 |
|
|
if (TREE_CODE (type) == INTEGER_TYPE && TREE_TYPE (type) != NULL_TREE)
|
11958 |
|
|
type = TREE_TYPE (type);
|
11959 |
|
|
|
11960 |
|
|
switch (TREE_CODE (type))
|
11961 |
|
|
{
|
11962 |
|
|
case INTEGER_TYPE:
|
11963 |
|
|
if (TYPE_STRING_FLAG (type))
|
11964 |
|
|
{
|
11965 |
|
|
if (TYPE_UNSIGNED (type))
|
11966 |
|
|
encoding = DW_ATE_unsigned_char;
|
11967 |
|
|
else
|
11968 |
|
|
encoding = DW_ATE_signed_char;
|
11969 |
|
|
}
|
11970 |
|
|
else if (TYPE_UNSIGNED (type))
|
11971 |
|
|
encoding = DW_ATE_unsigned;
|
11972 |
|
|
else
|
11973 |
|
|
encoding = DW_ATE_signed;
|
11974 |
|
|
break;
|
11975 |
|
|
|
11976 |
|
|
case REAL_TYPE:
|
11977 |
|
|
if (DECIMAL_FLOAT_MODE_P (TYPE_MODE (type)))
|
11978 |
|
|
{
|
11979 |
|
|
if (dwarf_version >= 3 || !dwarf_strict)
|
11980 |
|
|
encoding = DW_ATE_decimal_float;
|
11981 |
|
|
else
|
11982 |
|
|
encoding = DW_ATE_lo_user;
|
11983 |
|
|
}
|
11984 |
|
|
else
|
11985 |
|
|
encoding = DW_ATE_float;
|
11986 |
|
|
break;
|
11987 |
|
|
|
11988 |
|
|
case FIXED_POINT_TYPE:
|
11989 |
|
|
if (!(dwarf_version >= 3 || !dwarf_strict))
|
11990 |
|
|
encoding = DW_ATE_lo_user;
|
11991 |
|
|
else if (TYPE_UNSIGNED (type))
|
11992 |
|
|
encoding = DW_ATE_unsigned_fixed;
|
11993 |
|
|
else
|
11994 |
|
|
encoding = DW_ATE_signed_fixed;
|
11995 |
|
|
break;
|
11996 |
|
|
|
11997 |
|
|
/* Dwarf2 doesn't know anything about complex ints, so use
|
11998 |
|
|
a user defined type for it. */
|
11999 |
|
|
case COMPLEX_TYPE:
|
12000 |
|
|
if (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE)
|
12001 |
|
|
encoding = DW_ATE_complex_float;
|
12002 |
|
|
else
|
12003 |
|
|
encoding = DW_ATE_lo_user;
|
12004 |
|
|
break;
|
12005 |
|
|
|
12006 |
|
|
case BOOLEAN_TYPE:
|
12007 |
|
|
/* GNU FORTRAN/Ada/C++ BOOLEAN type. */
|
12008 |
|
|
encoding = DW_ATE_boolean;
|
12009 |
|
|
break;
|
12010 |
|
|
|
12011 |
|
|
default:
|
12012 |
|
|
/* No other TREE_CODEs are Dwarf fundamental types. */
|
12013 |
|
|
gcc_unreachable ();
|
12014 |
|
|
}
|
12015 |
|
|
|
12016 |
|
|
base_type_result = new_die (DW_TAG_base_type, comp_unit_die, type);
|
12017 |
|
|
|
12018 |
|
|
add_AT_unsigned (base_type_result, DW_AT_byte_size,
|
12019 |
|
|
int_size_in_bytes (type));
|
12020 |
|
|
add_AT_unsigned (base_type_result, DW_AT_encoding, encoding);
|
12021 |
|
|
|
12022 |
|
|
return base_type_result;
|
12023 |
|
|
}
|
12024 |
|
|
|
12025 |
|
|
/* Given a pointer to an arbitrary ..._TYPE tree node, return nonzero if the
|
12026 |
|
|
given input type is a Dwarf "fundamental" type. Otherwise return null. */
|
12027 |
|
|
|
12028 |
|
|
static inline int
|
12029 |
|
|
is_base_type (tree type)
|
12030 |
|
|
{
|
12031 |
|
|
switch (TREE_CODE (type))
|
12032 |
|
|
{
|
12033 |
|
|
case ERROR_MARK:
|
12034 |
|
|
case VOID_TYPE:
|
12035 |
|
|
case INTEGER_TYPE:
|
12036 |
|
|
case REAL_TYPE:
|
12037 |
|
|
case FIXED_POINT_TYPE:
|
12038 |
|
|
case COMPLEX_TYPE:
|
12039 |
|
|
case BOOLEAN_TYPE:
|
12040 |
|
|
return 1;
|
12041 |
|
|
|
12042 |
|
|
case ARRAY_TYPE:
|
12043 |
|
|
case RECORD_TYPE:
|
12044 |
|
|
case UNION_TYPE:
|
12045 |
|
|
case QUAL_UNION_TYPE:
|
12046 |
|
|
case ENUMERAL_TYPE:
|
12047 |
|
|
case FUNCTION_TYPE:
|
12048 |
|
|
case METHOD_TYPE:
|
12049 |
|
|
case POINTER_TYPE:
|
12050 |
|
|
case REFERENCE_TYPE:
|
12051 |
|
|
case OFFSET_TYPE:
|
12052 |
|
|
case LANG_TYPE:
|
12053 |
|
|
case VECTOR_TYPE:
|
12054 |
|
|
return 0;
|
12055 |
|
|
|
12056 |
|
|
default:
|
12057 |
|
|
gcc_unreachable ();
|
12058 |
|
|
}
|
12059 |
|
|
|
12060 |
|
|
return 0;
|
12061 |
|
|
}
|
12062 |
|
|
|
12063 |
|
|
/* Given a pointer to a tree node, assumed to be some kind of a ..._TYPE
|
12064 |
|
|
node, return the size in bits for the type if it is a constant, or else
|
12065 |
|
|
return the alignment for the type if the type's size is not constant, or
|
12066 |
|
|
else return BITS_PER_WORD if the type actually turns out to be an
|
12067 |
|
|
ERROR_MARK node. */
|
12068 |
|
|
|
12069 |
|
|
static inline unsigned HOST_WIDE_INT
|
12070 |
|
|
simple_type_size_in_bits (const_tree type)
|
12071 |
|
|
{
|
12072 |
|
|
if (TREE_CODE (type) == ERROR_MARK)
|
12073 |
|
|
return BITS_PER_WORD;
|
12074 |
|
|
else if (TYPE_SIZE (type) == NULL_TREE)
|
12075 |
|
|
return 0;
|
12076 |
|
|
else if (host_integerp (TYPE_SIZE (type), 1))
|
12077 |
|
|
return tree_low_cst (TYPE_SIZE (type), 1);
|
12078 |
|
|
else
|
12079 |
|
|
return TYPE_ALIGN (type);
|
12080 |
|
|
}
|
12081 |
|
|
|
12082 |
|
|
/* Given a pointer to a tree node for a subrange type, return a pointer
|
12083 |
|
|
to a DIE that describes the given type. */
|
12084 |
|
|
|
12085 |
|
|
static dw_die_ref
|
12086 |
|
|
subrange_type_die (tree type, tree low, tree high, dw_die_ref context_die)
|
12087 |
|
|
{
|
12088 |
|
|
dw_die_ref subrange_die;
|
12089 |
|
|
const HOST_WIDE_INT size_in_bytes = int_size_in_bytes (type);
|
12090 |
|
|
|
12091 |
|
|
if (context_die == NULL)
|
12092 |
|
|
context_die = comp_unit_die;
|
12093 |
|
|
|
12094 |
|
|
subrange_die = new_die (DW_TAG_subrange_type, context_die, type);
|
12095 |
|
|
|
12096 |
|
|
if (int_size_in_bytes (TREE_TYPE (type)) != size_in_bytes)
|
12097 |
|
|
{
|
12098 |
|
|
/* The size of the subrange type and its base type do not match,
|
12099 |
|
|
so we need to generate a size attribute for the subrange type. */
|
12100 |
|
|
add_AT_unsigned (subrange_die, DW_AT_byte_size, size_in_bytes);
|
12101 |
|
|
}
|
12102 |
|
|
|
12103 |
|
|
if (low)
|
12104 |
|
|
add_bound_info (subrange_die, DW_AT_lower_bound, low);
|
12105 |
|
|
if (high)
|
12106 |
|
|
add_bound_info (subrange_die, DW_AT_upper_bound, high);
|
12107 |
|
|
|
12108 |
|
|
return subrange_die;
|
12109 |
|
|
}
|
12110 |
|
|
|
12111 |
|
|
/* Given a pointer to an arbitrary ..._TYPE tree node, return a debugging
|
12112 |
|
|
entry that chains various modifiers in front of the given type. */
|
12113 |
|
|
|
12114 |
|
|
static dw_die_ref
|
12115 |
|
|
modified_type_die (tree type, int is_const_type, int is_volatile_type,
|
12116 |
|
|
dw_die_ref context_die)
|
12117 |
|
|
{
|
12118 |
|
|
enum tree_code code = TREE_CODE (type);
|
12119 |
|
|
dw_die_ref mod_type_die;
|
12120 |
|
|
dw_die_ref sub_die = NULL;
|
12121 |
|
|
tree item_type = NULL;
|
12122 |
|
|
tree qualified_type;
|
12123 |
|
|
tree name, low, high;
|
12124 |
|
|
|
12125 |
|
|
if (code == ERROR_MARK)
|
12126 |
|
|
return NULL;
|
12127 |
|
|
|
12128 |
|
|
/* See if we already have the appropriately qualified variant of
|
12129 |
|
|
this type. */
|
12130 |
|
|
qualified_type
|
12131 |
|
|
= get_qualified_type (type,
|
12132 |
|
|
((is_const_type ? TYPE_QUAL_CONST : 0)
|
12133 |
|
|
| (is_volatile_type ? TYPE_QUAL_VOLATILE : 0)));
|
12134 |
|
|
|
12135 |
|
|
if (qualified_type == sizetype
|
12136 |
|
|
&& TYPE_NAME (qualified_type)
|
12137 |
|
|
&& TREE_CODE (TYPE_NAME (qualified_type)) == TYPE_DECL)
|
12138 |
|
|
{
|
12139 |
|
|
#ifdef ENABLE_CHECKING
|
12140 |
|
|
gcc_assert (TREE_CODE (TREE_TYPE (TYPE_NAME (qualified_type)))
|
12141 |
|
|
== INTEGER_TYPE
|
12142 |
|
|
&& TYPE_PRECISION (TREE_TYPE (TYPE_NAME (qualified_type)))
|
12143 |
|
|
== TYPE_PRECISION (qualified_type)
|
12144 |
|
|
&& TYPE_UNSIGNED (TREE_TYPE (TYPE_NAME (qualified_type)))
|
12145 |
|
|
== TYPE_UNSIGNED (qualified_type));
|
12146 |
|
|
#endif
|
12147 |
|
|
qualified_type = TREE_TYPE (TYPE_NAME (qualified_type));
|
12148 |
|
|
}
|
12149 |
|
|
|
12150 |
|
|
/* If we do, then we can just use its DIE, if it exists. */
|
12151 |
|
|
if (qualified_type)
|
12152 |
|
|
{
|
12153 |
|
|
mod_type_die = lookup_type_die (qualified_type);
|
12154 |
|
|
if (mod_type_die)
|
12155 |
|
|
return mod_type_die;
|
12156 |
|
|
}
|
12157 |
|
|
|
12158 |
|
|
name = qualified_type ? TYPE_NAME (qualified_type) : NULL;
|
12159 |
|
|
|
12160 |
|
|
/* Handle C typedef types. */
|
12161 |
|
|
if (name && TREE_CODE (name) == TYPE_DECL && DECL_ORIGINAL_TYPE (name))
|
12162 |
|
|
{
|
12163 |
|
|
tree dtype = TREE_TYPE (name);
|
12164 |
|
|
|
12165 |
|
|
if (qualified_type == dtype)
|
12166 |
|
|
{
|
12167 |
|
|
/* For a named type, use the typedef. */
|
12168 |
|
|
gen_type_die (qualified_type, context_die);
|
12169 |
|
|
return lookup_type_die (qualified_type);
|
12170 |
|
|
}
|
12171 |
|
|
else if (is_const_type < TYPE_READONLY (dtype)
|
12172 |
|
|
|| is_volatile_type < TYPE_VOLATILE (dtype)
|
12173 |
|
|
|| (is_const_type <= TYPE_READONLY (dtype)
|
12174 |
|
|
&& is_volatile_type <= TYPE_VOLATILE (dtype)
|
12175 |
|
|
&& DECL_ORIGINAL_TYPE (name) != type))
|
12176 |
|
|
/* cv-unqualified version of named type. Just use the unnamed
|
12177 |
|
|
type to which it refers. */
|
12178 |
|
|
return modified_type_die (DECL_ORIGINAL_TYPE (name),
|
12179 |
|
|
is_const_type, is_volatile_type,
|
12180 |
|
|
context_die);
|
12181 |
|
|
/* Else cv-qualified version of named type; fall through. */
|
12182 |
|
|
}
|
12183 |
|
|
|
12184 |
|
|
if (is_const_type)
|
12185 |
|
|
{
|
12186 |
|
|
mod_type_die = new_die (DW_TAG_const_type, comp_unit_die, type);
|
12187 |
|
|
sub_die = modified_type_die (type, 0, is_volatile_type, context_die);
|
12188 |
|
|
}
|
12189 |
|
|
else if (is_volatile_type)
|
12190 |
|
|
{
|
12191 |
|
|
mod_type_die = new_die (DW_TAG_volatile_type, comp_unit_die, type);
|
12192 |
|
|
sub_die = modified_type_die (type, 0, 0, context_die);
|
12193 |
|
|
}
|
12194 |
|
|
else if (code == POINTER_TYPE)
|
12195 |
|
|
{
|
12196 |
|
|
mod_type_die = new_die (DW_TAG_pointer_type, comp_unit_die, type);
|
12197 |
|
|
add_AT_unsigned (mod_type_die, DW_AT_byte_size,
|
12198 |
|
|
simple_type_size_in_bits (type) / BITS_PER_UNIT);
|
12199 |
|
|
item_type = TREE_TYPE (type);
|
12200 |
|
|
if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (item_type)))
|
12201 |
|
|
add_AT_unsigned (mod_type_die, DW_AT_address_class,
|
12202 |
|
|
TYPE_ADDR_SPACE (item_type));
|
12203 |
|
|
}
|
12204 |
|
|
else if (code == REFERENCE_TYPE)
|
12205 |
|
|
{
|
12206 |
|
|
mod_type_die = new_die (DW_TAG_reference_type, comp_unit_die, type);
|
12207 |
|
|
add_AT_unsigned (mod_type_die, DW_AT_byte_size,
|
12208 |
|
|
simple_type_size_in_bits (type) / BITS_PER_UNIT);
|
12209 |
|
|
item_type = TREE_TYPE (type);
|
12210 |
|
|
if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (item_type)))
|
12211 |
|
|
add_AT_unsigned (mod_type_die, DW_AT_address_class,
|
12212 |
|
|
TYPE_ADDR_SPACE (item_type));
|
12213 |
|
|
}
|
12214 |
|
|
else if (code == INTEGER_TYPE
|
12215 |
|
|
&& TREE_TYPE (type) != NULL_TREE
|
12216 |
|
|
&& subrange_type_for_debug_p (type, &low, &high))
|
12217 |
|
|
{
|
12218 |
|
|
mod_type_die = subrange_type_die (type, low, high, context_die);
|
12219 |
|
|
item_type = TREE_TYPE (type);
|
12220 |
|
|
}
|
12221 |
|
|
else if (is_base_type (type))
|
12222 |
|
|
mod_type_die = base_type_die (type);
|
12223 |
|
|
else
|
12224 |
|
|
{
|
12225 |
|
|
gen_type_die (type, context_die);
|
12226 |
|
|
|
12227 |
|
|
/* We have to get the type_main_variant here (and pass that to the
|
12228 |
|
|
`lookup_type_die' routine) because the ..._TYPE node we have
|
12229 |
|
|
might simply be a *copy* of some original type node (where the
|
12230 |
|
|
copy was created to help us keep track of typedef names) and
|
12231 |
|
|
that copy might have a different TYPE_UID from the original
|
12232 |
|
|
..._TYPE node. */
|
12233 |
|
|
if (TREE_CODE (type) != VECTOR_TYPE)
|
12234 |
|
|
return lookup_type_die (type_main_variant (type));
|
12235 |
|
|
else
|
12236 |
|
|
/* Vectors have the debugging information in the type,
|
12237 |
|
|
not the main variant. */
|
12238 |
|
|
return lookup_type_die (type);
|
12239 |
|
|
}
|
12240 |
|
|
|
12241 |
|
|
/* Builtin types don't have a DECL_ORIGINAL_TYPE. For those,
|
12242 |
|
|
don't output a DW_TAG_typedef, since there isn't one in the
|
12243 |
|
|
user's program; just attach a DW_AT_name to the type.
|
12244 |
|
|
Don't attach a DW_AT_name to DW_TAG_const_type or DW_TAG_volatile_type
|
12245 |
|
|
if the base type already has the same name. */
|
12246 |
|
|
if (name
|
12247 |
|
|
&& ((TREE_CODE (name) != TYPE_DECL
|
12248 |
|
|
&& (qualified_type == TYPE_MAIN_VARIANT (type)
|
12249 |
|
|
|| (!is_const_type && !is_volatile_type)))
|
12250 |
|
|
|| (TREE_CODE (name) == TYPE_DECL
|
12251 |
|
|
&& TREE_TYPE (name) == qualified_type
|
12252 |
|
|
&& DECL_NAME (name))))
|
12253 |
|
|
{
|
12254 |
|
|
if (TREE_CODE (name) == TYPE_DECL)
|
12255 |
|
|
/* Could just call add_name_and_src_coords_attributes here,
|
12256 |
|
|
but since this is a builtin type it doesn't have any
|
12257 |
|
|
useful source coordinates anyway. */
|
12258 |
|
|
name = DECL_NAME (name);
|
12259 |
|
|
add_name_attribute (mod_type_die, IDENTIFIER_POINTER (name));
|
12260 |
|
|
}
|
12261 |
|
|
/* This probably indicates a bug. */
|
12262 |
|
|
else if (mod_type_die && mod_type_die->die_tag == DW_TAG_base_type)
|
12263 |
|
|
add_name_attribute (mod_type_die, "__unknown__");
|
12264 |
|
|
|
12265 |
|
|
if (qualified_type)
|
12266 |
|
|
equate_type_number_to_die (qualified_type, mod_type_die);
|
12267 |
|
|
|
12268 |
|
|
if (item_type)
|
12269 |
|
|
/* We must do this after the equate_type_number_to_die call, in case
|
12270 |
|
|
this is a recursive type. This ensures that the modified_type_die
|
12271 |
|
|
recursion will terminate even if the type is recursive. Recursive
|
12272 |
|
|
types are possible in Ada. */
|
12273 |
|
|
sub_die = modified_type_die (item_type,
|
12274 |
|
|
TYPE_READONLY (item_type),
|
12275 |
|
|
TYPE_VOLATILE (item_type),
|
12276 |
|
|
context_die);
|
12277 |
|
|
|
12278 |
|
|
if (sub_die != NULL)
|
12279 |
|
|
add_AT_die_ref (mod_type_die, DW_AT_type, sub_die);
|
12280 |
|
|
|
12281 |
|
|
return mod_type_die;
|
12282 |
|
|
}
|
12283 |
|
|
|
12284 |
|
|
/* Generate DIEs for the generic parameters of T.
|
12285 |
|
|
T must be either a generic type or a generic function.
|
12286 |
|
|
See http://gcc.gnu.org/wiki/TemplateParmsDwarf for more. */
|
12287 |
|
|
|
12288 |
|
|
static void
|
12289 |
|
|
gen_generic_params_dies (tree t)
|
12290 |
|
|
{
|
12291 |
|
|
tree parms, args;
|
12292 |
|
|
int parms_num, i;
|
12293 |
|
|
dw_die_ref die = NULL;
|
12294 |
|
|
|
12295 |
|
|
if (!t || (TYPE_P (t) && !COMPLETE_TYPE_P (t)))
|
12296 |
|
|
return;
|
12297 |
|
|
|
12298 |
|
|
if (TYPE_P (t))
|
12299 |
|
|
die = lookup_type_die (t);
|
12300 |
|
|
else if (DECL_P (t))
|
12301 |
|
|
die = lookup_decl_die (t);
|
12302 |
|
|
|
12303 |
|
|
gcc_assert (die);
|
12304 |
|
|
|
12305 |
|
|
parms = lang_hooks.get_innermost_generic_parms (t);
|
12306 |
|
|
if (!parms)
|
12307 |
|
|
/* T has no generic parameter. It means T is neither a generic type
|
12308 |
|
|
or function. End of story. */
|
12309 |
|
|
return;
|
12310 |
|
|
|
12311 |
|
|
parms_num = TREE_VEC_LENGTH (parms);
|
12312 |
|
|
args = lang_hooks.get_innermost_generic_args (t);
|
12313 |
|
|
for (i = 0; i < parms_num; i++)
|
12314 |
|
|
{
|
12315 |
|
|
tree parm, arg, arg_pack_elems;
|
12316 |
|
|
|
12317 |
|
|
parm = TREE_VEC_ELT (parms, i);
|
12318 |
|
|
arg = TREE_VEC_ELT (args, i);
|
12319 |
|
|
arg_pack_elems = lang_hooks.types.get_argument_pack_elems (arg);
|
12320 |
|
|
gcc_assert (parm && TREE_VALUE (parm) && arg);
|
12321 |
|
|
|
12322 |
|
|
if (parm && TREE_VALUE (parm) && arg)
|
12323 |
|
|
{
|
12324 |
|
|
/* If PARM represents a template parameter pack,
|
12325 |
|
|
emit a DW_TAG_GNU_template_parameter_pack DIE, followed
|
12326 |
|
|
by DW_TAG_template_*_parameter DIEs for the argument
|
12327 |
|
|
pack elements of ARG. Note that ARG would then be
|
12328 |
|
|
an argument pack. */
|
12329 |
|
|
if (arg_pack_elems)
|
12330 |
|
|
template_parameter_pack_die (TREE_VALUE (parm),
|
12331 |
|
|
arg_pack_elems,
|
12332 |
|
|
die);
|
12333 |
|
|
else
|
12334 |
|
|
generic_parameter_die (TREE_VALUE (parm), arg,
|
12335 |
|
|
true /* Emit DW_AT_name */, die);
|
12336 |
|
|
}
|
12337 |
|
|
}
|
12338 |
|
|
}
|
12339 |
|
|
|
12340 |
|
|
/* Create and return a DIE for PARM which should be
|
12341 |
|
|
the representation of a generic type parameter.
|
12342 |
|
|
For instance, in the C++ front end, PARM would be a template parameter.
|
12343 |
|
|
ARG is the argument to PARM.
|
12344 |
|
|
EMIT_NAME_P if tree, the DIE will have DW_AT_name attribute set to the
|
12345 |
|
|
name of the PARM.
|
12346 |
|
|
PARENT_DIE is the parent DIE which the new created DIE should be added to,
|
12347 |
|
|
as a child node. */
|
12348 |
|
|
|
12349 |
|
|
static dw_die_ref
|
12350 |
|
|
generic_parameter_die (tree parm, tree arg,
|
12351 |
|
|
bool emit_name_p,
|
12352 |
|
|
dw_die_ref parent_die)
|
12353 |
|
|
{
|
12354 |
|
|
dw_die_ref tmpl_die = NULL;
|
12355 |
|
|
const char *name = NULL;
|
12356 |
|
|
|
12357 |
|
|
if (!parm || !DECL_NAME (parm) || !arg)
|
12358 |
|
|
return NULL;
|
12359 |
|
|
|
12360 |
|
|
/* We support non-type generic parameters and arguments,
|
12361 |
|
|
type generic parameters and arguments, as well as
|
12362 |
|
|
generic generic parameters (a.k.a. template template parameters in C++)
|
12363 |
|
|
and arguments. */
|
12364 |
|
|
if (TREE_CODE (parm) == PARM_DECL)
|
12365 |
|
|
/* PARM is a nontype generic parameter */
|
12366 |
|
|
tmpl_die = new_die (DW_TAG_template_value_param, parent_die, parm);
|
12367 |
|
|
else if (TREE_CODE (parm) == TYPE_DECL)
|
12368 |
|
|
/* PARM is a type generic parameter. */
|
12369 |
|
|
tmpl_die = new_die (DW_TAG_template_type_param, parent_die, parm);
|
12370 |
|
|
else if (lang_hooks.decls.generic_generic_parameter_decl_p (parm))
|
12371 |
|
|
/* PARM is a generic generic parameter.
|
12372 |
|
|
Its DIE is a GNU extension. It shall have a
|
12373 |
|
|
DW_AT_name attribute to represent the name of the template template
|
12374 |
|
|
parameter, and a DW_AT_GNU_template_name attribute to represent the
|
12375 |
|
|
name of the template template argument. */
|
12376 |
|
|
tmpl_die = new_die (DW_TAG_GNU_template_template_param,
|
12377 |
|
|
parent_die, parm);
|
12378 |
|
|
else
|
12379 |
|
|
gcc_unreachable ();
|
12380 |
|
|
|
12381 |
|
|
if (tmpl_die)
|
12382 |
|
|
{
|
12383 |
|
|
tree tmpl_type;
|
12384 |
|
|
|
12385 |
|
|
/* If PARM is a generic parameter pack, it means we are
|
12386 |
|
|
emitting debug info for a template argument pack element.
|
12387 |
|
|
In other terms, ARG is a template argument pack element.
|
12388 |
|
|
In that case, we don't emit any DW_AT_name attribute for
|
12389 |
|
|
the die. */
|
12390 |
|
|
if (emit_name_p)
|
12391 |
|
|
{
|
12392 |
|
|
name = IDENTIFIER_POINTER (DECL_NAME (parm));
|
12393 |
|
|
gcc_assert (name);
|
12394 |
|
|
add_AT_string (tmpl_die, DW_AT_name, name);
|
12395 |
|
|
}
|
12396 |
|
|
|
12397 |
|
|
if (!lang_hooks.decls.generic_generic_parameter_decl_p (parm))
|
12398 |
|
|
{
|
12399 |
|
|
/* DWARF3, 5.6.8 says if PARM is a non-type generic parameter
|
12400 |
|
|
TMPL_DIE should have a child DW_AT_type attribute that is set
|
12401 |
|
|
to the type of the argument to PARM, which is ARG.
|
12402 |
|
|
If PARM is a type generic parameter, TMPL_DIE should have a
|
12403 |
|
|
child DW_AT_type that is set to ARG. */
|
12404 |
|
|
tmpl_type = TYPE_P (arg) ? arg : TREE_TYPE (arg);
|
12405 |
|
|
add_type_attribute (tmpl_die, tmpl_type, 0,
|
12406 |
|
|
TREE_THIS_VOLATILE (tmpl_type),
|
12407 |
|
|
parent_die);
|
12408 |
|
|
}
|
12409 |
|
|
else
|
12410 |
|
|
{
|
12411 |
|
|
/* So TMPL_DIE is a DIE representing a
|
12412 |
|
|
a generic generic template parameter, a.k.a template template
|
12413 |
|
|
parameter in C++ and arg is a template. */
|
12414 |
|
|
|
12415 |
|
|
/* The DW_AT_GNU_template_name attribute of the DIE must be set
|
12416 |
|
|
to the name of the argument. */
|
12417 |
|
|
name = dwarf2_name (TYPE_P (arg) ? TYPE_NAME (arg) : arg, 1);
|
12418 |
|
|
if (name)
|
12419 |
|
|
add_AT_string (tmpl_die, DW_AT_GNU_template_name, name);
|
12420 |
|
|
}
|
12421 |
|
|
|
12422 |
|
|
if (TREE_CODE (parm) == PARM_DECL)
|
12423 |
|
|
/* So PARM is a non-type generic parameter.
|
12424 |
|
|
DWARF3 5.6.8 says we must set a DW_AT_const_value child
|
12425 |
|
|
attribute of TMPL_DIE which value represents the value
|
12426 |
|
|
of ARG.
|
12427 |
|
|
We must be careful here:
|
12428 |
|
|
The value of ARG might reference some function decls.
|
12429 |
|
|
We might currently be emitting debug info for a generic
|
12430 |
|
|
type and types are emitted before function decls, we don't
|
12431 |
|
|
know if the function decls referenced by ARG will actually be
|
12432 |
|
|
emitted after cgraph computations.
|
12433 |
|
|
So must defer the generation of the DW_AT_const_value to
|
12434 |
|
|
after cgraph is ready. */
|
12435 |
|
|
append_entry_to_tmpl_value_parm_die_table (tmpl_die, arg);
|
12436 |
|
|
}
|
12437 |
|
|
|
12438 |
|
|
return tmpl_die;
|
12439 |
|
|
}
|
12440 |
|
|
|
12441 |
|
|
/* Generate and return a DW_TAG_GNU_template_parameter_pack DIE representing.
|
12442 |
|
|
PARM_PACK must be a template parameter pack. The returned DIE
|
12443 |
|
|
will be child DIE of PARENT_DIE. */
|
12444 |
|
|
|
12445 |
|
|
static dw_die_ref
|
12446 |
|
|
template_parameter_pack_die (tree parm_pack,
|
12447 |
|
|
tree parm_pack_args,
|
12448 |
|
|
dw_die_ref parent_die)
|
12449 |
|
|
{
|
12450 |
|
|
dw_die_ref die;
|
12451 |
|
|
int j;
|
12452 |
|
|
|
12453 |
|
|
gcc_assert (parent_die && parm_pack);
|
12454 |
|
|
|
12455 |
|
|
die = new_die (DW_TAG_GNU_template_parameter_pack, parent_die, parm_pack);
|
12456 |
|
|
add_name_and_src_coords_attributes (die, parm_pack);
|
12457 |
|
|
for (j = 0; j < TREE_VEC_LENGTH (parm_pack_args); j++)
|
12458 |
|
|
generic_parameter_die (parm_pack,
|
12459 |
|
|
TREE_VEC_ELT (parm_pack_args, j),
|
12460 |
|
|
false /* Don't emit DW_AT_name */,
|
12461 |
|
|
die);
|
12462 |
|
|
return die;
|
12463 |
|
|
}
|
12464 |
|
|
|
12465 |
|
|
/* Given a pointer to an arbitrary ..._TYPE tree node, return true if it is
|
12466 |
|
|
an enumerated type. */
|
12467 |
|
|
|
12468 |
|
|
static inline int
|
12469 |
|
|
type_is_enum (const_tree type)
|
12470 |
|
|
{
|
12471 |
|
|
return TREE_CODE (type) == ENUMERAL_TYPE;
|
12472 |
|
|
}
|
12473 |
|
|
|
12474 |
|
|
/* Return the DBX register number described by a given RTL node. */
|
12475 |
|
|
|
12476 |
|
|
static unsigned int
|
12477 |
|
|
dbx_reg_number (const_rtx rtl)
|
12478 |
|
|
{
|
12479 |
|
|
unsigned regno = REGNO (rtl);
|
12480 |
|
|
|
12481 |
|
|
gcc_assert (regno < FIRST_PSEUDO_REGISTER);
|
12482 |
|
|
|
12483 |
|
|
#ifdef LEAF_REG_REMAP
|
12484 |
|
|
if (current_function_uses_only_leaf_regs)
|
12485 |
|
|
{
|
12486 |
|
|
int leaf_reg = LEAF_REG_REMAP (regno);
|
12487 |
|
|
if (leaf_reg != -1)
|
12488 |
|
|
regno = (unsigned) leaf_reg;
|
12489 |
|
|
}
|
12490 |
|
|
#endif
|
12491 |
|
|
|
12492 |
|
|
return DBX_REGISTER_NUMBER (regno);
|
12493 |
|
|
}
|
12494 |
|
|
|
12495 |
|
|
/* Optionally add a DW_OP_piece term to a location description expression.
|
12496 |
|
|
DW_OP_piece is only added if the location description expression already
|
12497 |
|
|
doesn't end with DW_OP_piece. */
|
12498 |
|
|
|
12499 |
|
|
static void
|
12500 |
|
|
add_loc_descr_op_piece (dw_loc_descr_ref *list_head, int size)
|
12501 |
|
|
{
|
12502 |
|
|
dw_loc_descr_ref loc;
|
12503 |
|
|
|
12504 |
|
|
if (*list_head != NULL)
|
12505 |
|
|
{
|
12506 |
|
|
/* Find the end of the chain. */
|
12507 |
|
|
for (loc = *list_head; loc->dw_loc_next != NULL; loc = loc->dw_loc_next)
|
12508 |
|
|
;
|
12509 |
|
|
|
12510 |
|
|
if (loc->dw_loc_opc != DW_OP_piece)
|
12511 |
|
|
loc->dw_loc_next = new_loc_descr (DW_OP_piece, size, 0);
|
12512 |
|
|
}
|
12513 |
|
|
}
|
12514 |
|
|
|
12515 |
|
|
/* Return a location descriptor that designates a machine register or
|
12516 |
|
|
zero if there is none. */
|
12517 |
|
|
|
12518 |
|
|
static dw_loc_descr_ref
|
12519 |
|
|
reg_loc_descriptor (rtx rtl, enum var_init_status initialized)
|
12520 |
|
|
{
|
12521 |
|
|
rtx regs;
|
12522 |
|
|
|
12523 |
|
|
if (REGNO (rtl) >= FIRST_PSEUDO_REGISTER)
|
12524 |
|
|
return 0;
|
12525 |
|
|
|
12526 |
|
|
/* We only use "frame base" when we're sure we're talking about the
|
12527 |
|
|
post-prologue local stack frame. We do this by *not* running
|
12528 |
|
|
register elimination until this point, and recognizing the special
|
12529 |
|
|
argument pointer and soft frame pointer rtx's.
|
12530 |
|
|
Use DW_OP_fbreg offset DW_OP_stack_value in this case. */
|
12531 |
|
|
if ((rtl == arg_pointer_rtx || rtl == frame_pointer_rtx)
|
12532 |
|
|
&& eliminate_regs (rtl, VOIDmode, NULL_RTX) != rtl)
|
12533 |
|
|
{
|
12534 |
|
|
dw_loc_descr_ref result = NULL;
|
12535 |
|
|
|
12536 |
|
|
if (dwarf_version >= 4 || !dwarf_strict)
|
12537 |
|
|
{
|
12538 |
|
|
result = mem_loc_descriptor (rtl, VOIDmode, initialized);
|
12539 |
|
|
if (result)
|
12540 |
|
|
add_loc_descr (&result,
|
12541 |
|
|
new_loc_descr (DW_OP_stack_value, 0, 0));
|
12542 |
|
|
}
|
12543 |
|
|
return result;
|
12544 |
|
|
}
|
12545 |
|
|
|
12546 |
|
|
regs = targetm.dwarf_register_span (rtl);
|
12547 |
|
|
|
12548 |
|
|
if (hard_regno_nregs[REGNO (rtl)][GET_MODE (rtl)] > 1 || regs)
|
12549 |
|
|
return multiple_reg_loc_descriptor (rtl, regs, initialized);
|
12550 |
|
|
else
|
12551 |
|
|
return one_reg_loc_descriptor (dbx_reg_number (rtl), initialized);
|
12552 |
|
|
}
|
12553 |
|
|
|
12554 |
|
|
/* Return a location descriptor that designates a machine register for
|
12555 |
|
|
a given hard register number. */
|
12556 |
|
|
|
12557 |
|
|
static dw_loc_descr_ref
|
12558 |
|
|
one_reg_loc_descriptor (unsigned int regno, enum var_init_status initialized)
|
12559 |
|
|
{
|
12560 |
|
|
dw_loc_descr_ref reg_loc_descr;
|
12561 |
|
|
|
12562 |
|
|
if (regno <= 31)
|
12563 |
|
|
reg_loc_descr
|
12564 |
|
|
= new_loc_descr ((enum dwarf_location_atom) (DW_OP_reg0 + regno), 0, 0);
|
12565 |
|
|
else
|
12566 |
|
|
reg_loc_descr = new_loc_descr (DW_OP_regx, regno, 0);
|
12567 |
|
|
|
12568 |
|
|
if (initialized == VAR_INIT_STATUS_UNINITIALIZED)
|
12569 |
|
|
add_loc_descr (®_loc_descr, new_loc_descr (DW_OP_GNU_uninit, 0, 0));
|
12570 |
|
|
|
12571 |
|
|
return reg_loc_descr;
|
12572 |
|
|
}
|
12573 |
|
|
|
12574 |
|
|
/* Given an RTL of a register, return a location descriptor that
|
12575 |
|
|
designates a value that spans more than one register. */
|
12576 |
|
|
|
12577 |
|
|
static dw_loc_descr_ref
|
12578 |
|
|
multiple_reg_loc_descriptor (rtx rtl, rtx regs,
|
12579 |
|
|
enum var_init_status initialized)
|
12580 |
|
|
{
|
12581 |
|
|
int nregs, size, i;
|
12582 |
|
|
unsigned reg;
|
12583 |
|
|
dw_loc_descr_ref loc_result = NULL;
|
12584 |
|
|
|
12585 |
|
|
reg = REGNO (rtl);
|
12586 |
|
|
#ifdef LEAF_REG_REMAP
|
12587 |
|
|
if (current_function_uses_only_leaf_regs)
|
12588 |
|
|
{
|
12589 |
|
|
int leaf_reg = LEAF_REG_REMAP (reg);
|
12590 |
|
|
if (leaf_reg != -1)
|
12591 |
|
|
reg = (unsigned) leaf_reg;
|
12592 |
|
|
}
|
12593 |
|
|
#endif
|
12594 |
|
|
gcc_assert ((unsigned) DBX_REGISTER_NUMBER (reg) == dbx_reg_number (rtl));
|
12595 |
|
|
nregs = hard_regno_nregs[REGNO (rtl)][GET_MODE (rtl)];
|
12596 |
|
|
|
12597 |
|
|
/* Simple, contiguous registers. */
|
12598 |
|
|
if (regs == NULL_RTX)
|
12599 |
|
|
{
|
12600 |
|
|
size = GET_MODE_SIZE (GET_MODE (rtl)) / nregs;
|
12601 |
|
|
|
12602 |
|
|
loc_result = NULL;
|
12603 |
|
|
while (nregs--)
|
12604 |
|
|
{
|
12605 |
|
|
dw_loc_descr_ref t;
|
12606 |
|
|
|
12607 |
|
|
t = one_reg_loc_descriptor (DBX_REGISTER_NUMBER (reg),
|
12608 |
|
|
VAR_INIT_STATUS_INITIALIZED);
|
12609 |
|
|
add_loc_descr (&loc_result, t);
|
12610 |
|
|
add_loc_descr_op_piece (&loc_result, size);
|
12611 |
|
|
++reg;
|
12612 |
|
|
}
|
12613 |
|
|
return loc_result;
|
12614 |
|
|
}
|
12615 |
|
|
|
12616 |
|
|
/* Now onto stupid register sets in non contiguous locations. */
|
12617 |
|
|
|
12618 |
|
|
gcc_assert (GET_CODE (regs) == PARALLEL);
|
12619 |
|
|
|
12620 |
|
|
size = GET_MODE_SIZE (GET_MODE (XVECEXP (regs, 0, 0)));
|
12621 |
|
|
loc_result = NULL;
|
12622 |
|
|
|
12623 |
|
|
for (i = 0; i < XVECLEN (regs, 0); ++i)
|
12624 |
|
|
{
|
12625 |
|
|
dw_loc_descr_ref t;
|
12626 |
|
|
|
12627 |
|
|
t = one_reg_loc_descriptor (REGNO (XVECEXP (regs, 0, i)),
|
12628 |
|
|
VAR_INIT_STATUS_INITIALIZED);
|
12629 |
|
|
add_loc_descr (&loc_result, t);
|
12630 |
|
|
size = GET_MODE_SIZE (GET_MODE (XVECEXP (regs, 0, 0)));
|
12631 |
|
|
add_loc_descr_op_piece (&loc_result, size);
|
12632 |
|
|
}
|
12633 |
|
|
|
12634 |
|
|
if (loc_result && initialized == VAR_INIT_STATUS_UNINITIALIZED)
|
12635 |
|
|
add_loc_descr (&loc_result, new_loc_descr (DW_OP_GNU_uninit, 0, 0));
|
12636 |
|
|
return loc_result;
|
12637 |
|
|
}
|
12638 |
|
|
|
12639 |
|
|
#endif /* DWARF2_DEBUGGING_INFO */
|
12640 |
|
|
|
12641 |
|
|
#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
|
12642 |
|
|
|
12643 |
|
|
/* Return a location descriptor that designates a constant. */
|
12644 |
|
|
|
12645 |
|
|
static dw_loc_descr_ref
|
12646 |
|
|
int_loc_descriptor (HOST_WIDE_INT i)
|
12647 |
|
|
{
|
12648 |
|
|
enum dwarf_location_atom op;
|
12649 |
|
|
|
12650 |
|
|
/* Pick the smallest representation of a constant, rather than just
|
12651 |
|
|
defaulting to the LEB encoding. */
|
12652 |
|
|
if (i >= 0)
|
12653 |
|
|
{
|
12654 |
|
|
if (i <= 31)
|
12655 |
|
|
op = (enum dwarf_location_atom) (DW_OP_lit0 + i);
|
12656 |
|
|
else if (i <= 0xff)
|
12657 |
|
|
op = DW_OP_const1u;
|
12658 |
|
|
else if (i <= 0xffff)
|
12659 |
|
|
op = DW_OP_const2u;
|
12660 |
|
|
else if (HOST_BITS_PER_WIDE_INT == 32
|
12661 |
|
|
|| i <= 0xffffffff)
|
12662 |
|
|
op = DW_OP_const4u;
|
12663 |
|
|
else
|
12664 |
|
|
op = DW_OP_constu;
|
12665 |
|
|
}
|
12666 |
|
|
else
|
12667 |
|
|
{
|
12668 |
|
|
if (i >= -0x80)
|
12669 |
|
|
op = DW_OP_const1s;
|
12670 |
|
|
else if (i >= -0x8000)
|
12671 |
|
|
op = DW_OP_const2s;
|
12672 |
|
|
else if (HOST_BITS_PER_WIDE_INT == 32
|
12673 |
|
|
|| i >= -0x80000000)
|
12674 |
|
|
op = DW_OP_const4s;
|
12675 |
|
|
else
|
12676 |
|
|
op = DW_OP_consts;
|
12677 |
|
|
}
|
12678 |
|
|
|
12679 |
|
|
return new_loc_descr (op, i, 0);
|
12680 |
|
|
}
|
12681 |
|
|
#endif
|
12682 |
|
|
|
12683 |
|
|
#ifdef DWARF2_DEBUGGING_INFO
|
12684 |
|
|
/* Return loc description representing "address" of integer value.
|
12685 |
|
|
This can appear only as toplevel expression. */
|
12686 |
|
|
|
12687 |
|
|
static dw_loc_descr_ref
|
12688 |
|
|
address_of_int_loc_descriptor (int size, HOST_WIDE_INT i)
|
12689 |
|
|
{
|
12690 |
|
|
int litsize;
|
12691 |
|
|
dw_loc_descr_ref loc_result = NULL;
|
12692 |
|
|
|
12693 |
|
|
if (!(dwarf_version >= 4 || !dwarf_strict))
|
12694 |
|
|
return NULL;
|
12695 |
|
|
|
12696 |
|
|
if (i >= 0)
|
12697 |
|
|
{
|
12698 |
|
|
if (i <= 31)
|
12699 |
|
|
litsize = 1;
|
12700 |
|
|
else if (i <= 0xff)
|
12701 |
|
|
litsize = 2;
|
12702 |
|
|
else if (i <= 0xffff)
|
12703 |
|
|
litsize = 3;
|
12704 |
|
|
else if (HOST_BITS_PER_WIDE_INT == 32
|
12705 |
|
|
|| i <= 0xffffffff)
|
12706 |
|
|
litsize = 5;
|
12707 |
|
|
else
|
12708 |
|
|
litsize = 1 + size_of_uleb128 ((unsigned HOST_WIDE_INT) i);
|
12709 |
|
|
}
|
12710 |
|
|
else
|
12711 |
|
|
{
|
12712 |
|
|
if (i >= -0x80)
|
12713 |
|
|
litsize = 2;
|
12714 |
|
|
else if (i >= -0x8000)
|
12715 |
|
|
litsize = 3;
|
12716 |
|
|
else if (HOST_BITS_PER_WIDE_INT == 32
|
12717 |
|
|
|| i >= -0x80000000)
|
12718 |
|
|
litsize = 5;
|
12719 |
|
|
else
|
12720 |
|
|
litsize = 1 + size_of_sleb128 (i);
|
12721 |
|
|
}
|
12722 |
|
|
/* Determine if DW_OP_stack_value or DW_OP_implicit_value
|
12723 |
|
|
is more compact. For DW_OP_stack_value we need:
|
12724 |
|
|
litsize + 1 (DW_OP_stack_value)
|
12725 |
|
|
and for DW_OP_implicit_value:
|
12726 |
|
|
1 (DW_OP_implicit_value) + 1 (length) + size. */
|
12727 |
|
|
if ((int) DWARF2_ADDR_SIZE >= size && litsize + 1 <= 1 + 1 + size)
|
12728 |
|
|
{
|
12729 |
|
|
loc_result = int_loc_descriptor (i);
|
12730 |
|
|
add_loc_descr (&loc_result,
|
12731 |
|
|
new_loc_descr (DW_OP_stack_value, 0, 0));
|
12732 |
|
|
return loc_result;
|
12733 |
|
|
}
|
12734 |
|
|
|
12735 |
|
|
loc_result = new_loc_descr (DW_OP_implicit_value,
|
12736 |
|
|
size, 0);
|
12737 |
|
|
loc_result->dw_loc_oprnd2.val_class = dw_val_class_const;
|
12738 |
|
|
loc_result->dw_loc_oprnd2.v.val_int = i;
|
12739 |
|
|
return loc_result;
|
12740 |
|
|
}
|
12741 |
|
|
|
12742 |
|
|
/* Return a location descriptor that designates a base+offset location. */
|
12743 |
|
|
|
12744 |
|
|
static dw_loc_descr_ref
|
12745 |
|
|
based_loc_descr (rtx reg, HOST_WIDE_INT offset,
|
12746 |
|
|
enum var_init_status initialized)
|
12747 |
|
|
{
|
12748 |
|
|
unsigned int regno;
|
12749 |
|
|
dw_loc_descr_ref result;
|
12750 |
|
|
dw_fde_ref fde = current_fde ();
|
12751 |
|
|
|
12752 |
|
|
/* We only use "frame base" when we're sure we're talking about the
|
12753 |
|
|
post-prologue local stack frame. We do this by *not* running
|
12754 |
|
|
register elimination until this point, and recognizing the special
|
12755 |
|
|
argument pointer and soft frame pointer rtx's. */
|
12756 |
|
|
if (reg == arg_pointer_rtx || reg == frame_pointer_rtx)
|
12757 |
|
|
{
|
12758 |
|
|
rtx elim = eliminate_regs (reg, VOIDmode, NULL_RTX);
|
12759 |
|
|
|
12760 |
|
|
if (elim != reg)
|
12761 |
|
|
{
|
12762 |
|
|
if (GET_CODE (elim) == PLUS)
|
12763 |
|
|
{
|
12764 |
|
|
offset += INTVAL (XEXP (elim, 1));
|
12765 |
|
|
elim = XEXP (elim, 0);
|
12766 |
|
|
}
|
12767 |
|
|
gcc_assert ((SUPPORTS_STACK_ALIGNMENT
|
12768 |
|
|
&& (elim == hard_frame_pointer_rtx
|
12769 |
|
|
|| elim == stack_pointer_rtx))
|
12770 |
|
|
|| elim == (frame_pointer_needed
|
12771 |
|
|
? hard_frame_pointer_rtx
|
12772 |
|
|
: stack_pointer_rtx));
|
12773 |
|
|
|
12774 |
|
|
/* If drap register is used to align stack, use frame
|
12775 |
|
|
pointer + offset to access stack variables. If stack
|
12776 |
|
|
is aligned without drap, use stack pointer + offset to
|
12777 |
|
|
access stack variables. */
|
12778 |
|
|
if (crtl->stack_realign_tried
|
12779 |
|
|
&& reg == frame_pointer_rtx)
|
12780 |
|
|
{
|
12781 |
|
|
int base_reg
|
12782 |
|
|
= DWARF_FRAME_REGNUM ((fde && fde->drap_reg != INVALID_REGNUM)
|
12783 |
|
|
? HARD_FRAME_POINTER_REGNUM
|
12784 |
|
|
: STACK_POINTER_REGNUM);
|
12785 |
|
|
return new_reg_loc_descr (base_reg, offset);
|
12786 |
|
|
}
|
12787 |
|
|
|
12788 |
|
|
offset += frame_pointer_fb_offset;
|
12789 |
|
|
return new_loc_descr (DW_OP_fbreg, offset, 0);
|
12790 |
|
|
}
|
12791 |
|
|
}
|
12792 |
|
|
else if (!optimize
|
12793 |
|
|
&& fde
|
12794 |
|
|
&& (fde->drap_reg == REGNO (reg)
|
12795 |
|
|
|| fde->vdrap_reg == REGNO (reg)))
|
12796 |
|
|
{
|
12797 |
|
|
/* Use cfa+offset to represent the location of arguments passed
|
12798 |
|
|
on the stack when drap is used to align stack.
|
12799 |
|
|
Only do this when not optimizing, for optimized code var-tracking
|
12800 |
|
|
is supposed to track where the arguments live and the register
|
12801 |
|
|
used as vdrap or drap in some spot might be used for something
|
12802 |
|
|
else in other part of the routine. */
|
12803 |
|
|
return new_loc_descr (DW_OP_fbreg, offset, 0);
|
12804 |
|
|
}
|
12805 |
|
|
|
12806 |
|
|
regno = dbx_reg_number (reg);
|
12807 |
|
|
if (regno <= 31)
|
12808 |
|
|
result = new_loc_descr ((enum dwarf_location_atom) (DW_OP_breg0 + regno),
|
12809 |
|
|
offset, 0);
|
12810 |
|
|
else
|
12811 |
|
|
result = new_loc_descr (DW_OP_bregx, regno, offset);
|
12812 |
|
|
|
12813 |
|
|
if (initialized == VAR_INIT_STATUS_UNINITIALIZED)
|
12814 |
|
|
add_loc_descr (&result, new_loc_descr (DW_OP_GNU_uninit, 0, 0));
|
12815 |
|
|
|
12816 |
|
|
return result;
|
12817 |
|
|
}
|
12818 |
|
|
|
12819 |
|
|
/* Return true if this RTL expression describes a base+offset calculation. */
|
12820 |
|
|
|
12821 |
|
|
static inline int
|
12822 |
|
|
is_based_loc (const_rtx rtl)
|
12823 |
|
|
{
|
12824 |
|
|
return (GET_CODE (rtl) == PLUS
|
12825 |
|
|
&& ((REG_P (XEXP (rtl, 0))
|
12826 |
|
|
&& REGNO (XEXP (rtl, 0)) < FIRST_PSEUDO_REGISTER
|
12827 |
|
|
&& CONST_INT_P (XEXP (rtl, 1)))));
|
12828 |
|
|
}
|
12829 |
|
|
|
12830 |
|
|
/* Try to handle TLS MEMs, for which mem_loc_descriptor on XEXP (mem, 0)
|
12831 |
|
|
failed. */
|
12832 |
|
|
|
12833 |
|
|
static dw_loc_descr_ref
|
12834 |
|
|
tls_mem_loc_descriptor (rtx mem)
|
12835 |
|
|
{
|
12836 |
|
|
tree base;
|
12837 |
|
|
dw_loc_descr_ref loc_result;
|
12838 |
|
|
|
12839 |
|
|
if (MEM_EXPR (mem) == NULL_TREE || MEM_OFFSET (mem) == NULL_RTX)
|
12840 |
|
|
return NULL;
|
12841 |
|
|
|
12842 |
|
|
base = get_base_address (MEM_EXPR (mem));
|
12843 |
|
|
if (base == NULL
|
12844 |
|
|
|| TREE_CODE (base) != VAR_DECL
|
12845 |
|
|
|| !DECL_THREAD_LOCAL_P (base))
|
12846 |
|
|
return NULL;
|
12847 |
|
|
|
12848 |
|
|
loc_result = loc_descriptor_from_tree (MEM_EXPR (mem), 1);
|
12849 |
|
|
if (loc_result == NULL)
|
12850 |
|
|
return NULL;
|
12851 |
|
|
|
12852 |
|
|
if (INTVAL (MEM_OFFSET (mem)))
|
12853 |
|
|
loc_descr_plus_const (&loc_result, INTVAL (MEM_OFFSET (mem)));
|
12854 |
|
|
|
12855 |
|
|
return loc_result;
|
12856 |
|
|
}
|
12857 |
|
|
|
12858 |
|
|
/* Output debug info about reason why we failed to expand expression as dwarf
|
12859 |
|
|
expression. */
|
12860 |
|
|
|
12861 |
|
|
static void
|
12862 |
|
|
expansion_failed (tree expr, rtx rtl, char const *reason)
|
12863 |
|
|
{
|
12864 |
|
|
if (dump_file && (dump_flags & TDF_DETAILS))
|
12865 |
|
|
{
|
12866 |
|
|
fprintf (dump_file, "Failed to expand as dwarf: ");
|
12867 |
|
|
if (expr)
|
12868 |
|
|
print_generic_expr (dump_file, expr, dump_flags);
|
12869 |
|
|
if (rtl)
|
12870 |
|
|
{
|
12871 |
|
|
fprintf (dump_file, "\n");
|
12872 |
|
|
print_rtl (dump_file, rtl);
|
12873 |
|
|
}
|
12874 |
|
|
fprintf (dump_file, "\nReason: %s\n", reason);
|
12875 |
|
|
}
|
12876 |
|
|
}
|
12877 |
|
|
|
12878 |
|
|
/* Helper function for const_ok_for_output, called either directly
|
12879 |
|
|
or via for_each_rtx. */
|
12880 |
|
|
|
12881 |
|
|
static int
|
12882 |
|
|
const_ok_for_output_1 (rtx *rtlp, void *data ATTRIBUTE_UNUSED)
|
12883 |
|
|
{
|
12884 |
|
|
rtx rtl = *rtlp;
|
12885 |
|
|
|
12886 |
|
|
if (GET_CODE (rtl) == UNSPEC)
|
12887 |
|
|
{
|
12888 |
|
|
/* If delegitimize_address couldn't do anything with the UNSPEC, assume
|
12889 |
|
|
we can't express it in the debug info. */
|
12890 |
|
|
#ifdef ENABLE_CHECKING
|
12891 |
|
|
inform (current_function_decl
|
12892 |
|
|
? DECL_SOURCE_LOCATION (current_function_decl)
|
12893 |
|
|
: UNKNOWN_LOCATION,
|
12894 |
|
|
"non-delegitimized UNSPEC %d found in variable location",
|
12895 |
|
|
XINT (rtl, 1));
|
12896 |
|
|
#endif
|
12897 |
|
|
expansion_failed (NULL_TREE, rtl,
|
12898 |
|
|
"UNSPEC hasn't been delegitimized.\n");
|
12899 |
|
|
return 1;
|
12900 |
|
|
}
|
12901 |
|
|
|
12902 |
|
|
if (GET_CODE (rtl) != SYMBOL_REF)
|
12903 |
|
|
return 0;
|
12904 |
|
|
|
12905 |
|
|
if (CONSTANT_POOL_ADDRESS_P (rtl))
|
12906 |
|
|
{
|
12907 |
|
|
bool marked;
|
12908 |
|
|
get_pool_constant_mark (rtl, &marked);
|
12909 |
|
|
/* If all references to this pool constant were optimized away,
|
12910 |
|
|
it was not output and thus we can't represent it. */
|
12911 |
|
|
if (!marked)
|
12912 |
|
|
{
|
12913 |
|
|
expansion_failed (NULL_TREE, rtl,
|
12914 |
|
|
"Constant was removed from constant pool.\n");
|
12915 |
|
|
return 1;
|
12916 |
|
|
}
|
12917 |
|
|
}
|
12918 |
|
|
|
12919 |
|
|
if (SYMBOL_REF_TLS_MODEL (rtl) != TLS_MODEL_NONE)
|
12920 |
|
|
return 1;
|
12921 |
|
|
|
12922 |
|
|
/* Avoid references to external symbols in debug info, on several targets
|
12923 |
|
|
the linker might even refuse to link when linking a shared library,
|
12924 |
|
|
and in many other cases the relocations for .debug_info/.debug_loc are
|
12925 |
|
|
dropped, so the address becomes zero anyway. Hidden symbols, guaranteed
|
12926 |
|
|
to be defined within the same shared library or executable are fine. */
|
12927 |
|
|
if (SYMBOL_REF_EXTERNAL_P (rtl))
|
12928 |
|
|
{
|
12929 |
|
|
tree decl = SYMBOL_REF_DECL (rtl);
|
12930 |
|
|
|
12931 |
|
|
if (decl == NULL || !targetm.binds_local_p (decl))
|
12932 |
|
|
{
|
12933 |
|
|
expansion_failed (NULL_TREE, rtl,
|
12934 |
|
|
"Symbol not defined in current TU.\n");
|
12935 |
|
|
return 1;
|
12936 |
|
|
}
|
12937 |
|
|
}
|
12938 |
|
|
|
12939 |
|
|
return 0;
|
12940 |
|
|
}
|
12941 |
|
|
|
12942 |
|
|
/* Return true if constant RTL can be emitted in DW_OP_addr or
|
12943 |
|
|
DW_AT_const_value. TLS SYMBOL_REFs, external SYMBOL_REFs or
|
12944 |
|
|
non-marked constant pool SYMBOL_REFs can't be referenced in it. */
|
12945 |
|
|
|
12946 |
|
|
static bool
|
12947 |
|
|
const_ok_for_output (rtx rtl)
|
12948 |
|
|
{
|
12949 |
|
|
if (GET_CODE (rtl) == SYMBOL_REF)
|
12950 |
|
|
return const_ok_for_output_1 (&rtl, NULL) == 0;
|
12951 |
|
|
|
12952 |
|
|
if (GET_CODE (rtl) == CONST)
|
12953 |
|
|
return for_each_rtx (&XEXP (rtl, 0), const_ok_for_output_1, NULL) == 0;
|
12954 |
|
|
|
12955 |
|
|
return true;
|
12956 |
|
|
}
|
12957 |
|
|
|
12958 |
|
|
/* The following routine converts the RTL for a variable or parameter
|
12959 |
|
|
(resident in memory) into an equivalent Dwarf representation of a
|
12960 |
|
|
mechanism for getting the address of that same variable onto the top of a
|
12961 |
|
|
hypothetical "address evaluation" stack.
|
12962 |
|
|
|
12963 |
|
|
When creating memory location descriptors, we are effectively transforming
|
12964 |
|
|
the RTL for a memory-resident object into its Dwarf postfix expression
|
12965 |
|
|
equivalent. This routine recursively descends an RTL tree, turning
|
12966 |
|
|
it into Dwarf postfix code as it goes.
|
12967 |
|
|
|
12968 |
|
|
MODE is the mode of the memory reference, needed to handle some
|
12969 |
|
|
autoincrement addressing modes.
|
12970 |
|
|
|
12971 |
|
|
CAN_USE_FBREG is a flag whether we can use DW_AT_frame_base in the
|
12972 |
|
|
location list for RTL.
|
12973 |
|
|
|
12974 |
|
|
Return 0 if we can't represent the location. */
|
12975 |
|
|
|
12976 |
|
|
static dw_loc_descr_ref
|
12977 |
|
|
mem_loc_descriptor (rtx rtl, enum machine_mode mode,
|
12978 |
|
|
enum var_init_status initialized)
|
12979 |
|
|
{
|
12980 |
|
|
dw_loc_descr_ref mem_loc_result = NULL;
|
12981 |
|
|
enum dwarf_location_atom op;
|
12982 |
|
|
dw_loc_descr_ref op0, op1;
|
12983 |
|
|
|
12984 |
|
|
/* Note that for a dynamically sized array, the location we will generate a
|
12985 |
|
|
description of here will be the lowest numbered location which is
|
12986 |
|
|
actually within the array. That's *not* necessarily the same as the
|
12987 |
|
|
zeroth element of the array. */
|
12988 |
|
|
|
12989 |
|
|
rtl = targetm.delegitimize_address (rtl);
|
12990 |
|
|
|
12991 |
|
|
switch (GET_CODE (rtl))
|
12992 |
|
|
{
|
12993 |
|
|
case POST_INC:
|
12994 |
|
|
case POST_DEC:
|
12995 |
|
|
case POST_MODIFY:
|
12996 |
|
|
return mem_loc_descriptor (XEXP (rtl, 0), mode, initialized);
|
12997 |
|
|
|
12998 |
|
|
case SUBREG:
|
12999 |
|
|
/* The case of a subreg may arise when we have a local (register)
|
13000 |
|
|
variable or a formal (register) parameter which doesn't quite fill
|
13001 |
|
|
up an entire register. For now, just assume that it is
|
13002 |
|
|
legitimate to make the Dwarf info refer to the whole register which
|
13003 |
|
|
contains the given subreg. */
|
13004 |
|
|
if (!subreg_lowpart_p (rtl))
|
13005 |
|
|
break;
|
13006 |
|
|
rtl = SUBREG_REG (rtl);
|
13007 |
|
|
if (GET_MODE_SIZE (GET_MODE (rtl)) > DWARF2_ADDR_SIZE)
|
13008 |
|
|
break;
|
13009 |
|
|
if (GET_MODE_CLASS (GET_MODE (rtl)) != MODE_INT)
|
13010 |
|
|
break;
|
13011 |
|
|
mem_loc_result = mem_loc_descriptor (rtl, mode, initialized);
|
13012 |
|
|
break;
|
13013 |
|
|
|
13014 |
|
|
case REG:
|
13015 |
|
|
/* Whenever a register number forms a part of the description of the
|
13016 |
|
|
method for calculating the (dynamic) address of a memory resident
|
13017 |
|
|
object, DWARF rules require the register number be referred to as
|
13018 |
|
|
a "base register". This distinction is not based in any way upon
|
13019 |
|
|
what category of register the hardware believes the given register
|
13020 |
|
|
belongs to. This is strictly DWARF terminology we're dealing with
|
13021 |
|
|
here. Note that in cases where the location of a memory-resident
|
13022 |
|
|
data object could be expressed as: OP_ADD (OP_BASEREG (basereg),
|
13023 |
|
|
OP_CONST (0)) the actual DWARF location descriptor that we generate
|
13024 |
|
|
may just be OP_BASEREG (basereg). This may look deceptively like
|
13025 |
|
|
the object in question was allocated to a register (rather than in
|
13026 |
|
|
memory) so DWARF consumers need to be aware of the subtle
|
13027 |
|
|
distinction between OP_REG and OP_BASEREG. */
|
13028 |
|
|
if (REGNO (rtl) < FIRST_PSEUDO_REGISTER)
|
13029 |
|
|
mem_loc_result = based_loc_descr (rtl, 0, VAR_INIT_STATUS_INITIALIZED);
|
13030 |
|
|
else if (stack_realign_drap
|
13031 |
|
|
&& crtl->drap_reg
|
13032 |
|
|
&& crtl->args.internal_arg_pointer == rtl
|
13033 |
|
|
&& REGNO (crtl->drap_reg) < FIRST_PSEUDO_REGISTER)
|
13034 |
|
|
{
|
13035 |
|
|
/* If RTL is internal_arg_pointer, which has been optimized
|
13036 |
|
|
out, use DRAP instead. */
|
13037 |
|
|
mem_loc_result = based_loc_descr (crtl->drap_reg, 0,
|
13038 |
|
|
VAR_INIT_STATUS_INITIALIZED);
|
13039 |
|
|
}
|
13040 |
|
|
break;
|
13041 |
|
|
|
13042 |
|
|
case SIGN_EXTEND:
|
13043 |
|
|
case ZERO_EXTEND:
|
13044 |
|
|
op0 = mem_loc_descriptor (XEXP (rtl, 0), mode,
|
13045 |
|
|
VAR_INIT_STATUS_INITIALIZED);
|
13046 |
|
|
if (op0 == 0)
|
13047 |
|
|
break;
|
13048 |
|
|
else
|
13049 |
|
|
{
|
13050 |
|
|
int shift = DWARF2_ADDR_SIZE
|
13051 |
|
|
- GET_MODE_SIZE (GET_MODE (XEXP (rtl, 0)));
|
13052 |
|
|
shift *= BITS_PER_UNIT;
|
13053 |
|
|
if (GET_CODE (rtl) == SIGN_EXTEND)
|
13054 |
|
|
op = DW_OP_shra;
|
13055 |
|
|
else
|
13056 |
|
|
op = DW_OP_shr;
|
13057 |
|
|
mem_loc_result = op0;
|
13058 |
|
|
add_loc_descr (&mem_loc_result, int_loc_descriptor (shift));
|
13059 |
|
|
add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_shl, 0, 0));
|
13060 |
|
|
add_loc_descr (&mem_loc_result, int_loc_descriptor (shift));
|
13061 |
|
|
add_loc_descr (&mem_loc_result, new_loc_descr (op, 0, 0));
|
13062 |
|
|
}
|
13063 |
|
|
break;
|
13064 |
|
|
|
13065 |
|
|
case MEM:
|
13066 |
|
|
mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl),
|
13067 |
|
|
VAR_INIT_STATUS_INITIALIZED);
|
13068 |
|
|
if (mem_loc_result == NULL)
|
13069 |
|
|
mem_loc_result = tls_mem_loc_descriptor (rtl);
|
13070 |
|
|
if (mem_loc_result != 0)
|
13071 |
|
|
{
|
13072 |
|
|
if (GET_MODE_SIZE (GET_MODE (rtl)) > DWARF2_ADDR_SIZE)
|
13073 |
|
|
{
|
13074 |
|
|
expansion_failed (NULL_TREE, rtl, "DWARF address size mismatch");
|
13075 |
|
|
return 0;
|
13076 |
|
|
}
|
13077 |
|
|
else if (GET_MODE_SIZE (GET_MODE (rtl)) == DWARF2_ADDR_SIZE)
|
13078 |
|
|
add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0));
|
13079 |
|
|
else
|
13080 |
|
|
add_loc_descr (&mem_loc_result,
|
13081 |
|
|
new_loc_descr (DW_OP_deref_size,
|
13082 |
|
|
GET_MODE_SIZE (GET_MODE (rtl)), 0));
|
13083 |
|
|
}
|
13084 |
|
|
else
|
13085 |
|
|
{
|
13086 |
|
|
rtx new_rtl = avoid_constant_pool_reference (rtl);
|
13087 |
|
|
if (new_rtl != rtl)
|
13088 |
|
|
return mem_loc_descriptor (new_rtl, mode, initialized);
|
13089 |
|
|
}
|
13090 |
|
|
break;
|
13091 |
|
|
|
13092 |
|
|
case LO_SUM:
|
13093 |
|
|
rtl = XEXP (rtl, 1);
|
13094 |
|
|
|
13095 |
|
|
/* ... fall through ... */
|
13096 |
|
|
|
13097 |
|
|
case LABEL_REF:
|
13098 |
|
|
/* Some ports can transform a symbol ref into a label ref, because
|
13099 |
|
|
the symbol ref is too far away and has to be dumped into a constant
|
13100 |
|
|
pool. */
|
13101 |
|
|
case CONST:
|
13102 |
|
|
case SYMBOL_REF:
|
13103 |
|
|
if (GET_CODE (rtl) == SYMBOL_REF
|
13104 |
|
|
&& SYMBOL_REF_TLS_MODEL (rtl) != TLS_MODEL_NONE)
|
13105 |
|
|
{
|
13106 |
|
|
dw_loc_descr_ref temp;
|
13107 |
|
|
|
13108 |
|
|
/* If this is not defined, we have no way to emit the data. */
|
13109 |
|
|
if (!targetm.have_tls || !targetm.asm_out.output_dwarf_dtprel)
|
13110 |
|
|
break;
|
13111 |
|
|
|
13112 |
|
|
temp = new_loc_descr (DW_OP_addr, 0, 0);
|
13113 |
|
|
temp->dw_loc_oprnd1.val_class = dw_val_class_addr;
|
13114 |
|
|
temp->dw_loc_oprnd1.v.val_addr = rtl;
|
13115 |
|
|
temp->dtprel = true;
|
13116 |
|
|
|
13117 |
|
|
mem_loc_result = new_loc_descr (DW_OP_GNU_push_tls_address, 0, 0);
|
13118 |
|
|
add_loc_descr (&mem_loc_result, temp);
|
13119 |
|
|
|
13120 |
|
|
break;
|
13121 |
|
|
}
|
13122 |
|
|
|
13123 |
|
|
if (!const_ok_for_output (rtl))
|
13124 |
|
|
break;
|
13125 |
|
|
|
13126 |
|
|
symref:
|
13127 |
|
|
mem_loc_result = new_loc_descr (DW_OP_addr, 0, 0);
|
13128 |
|
|
mem_loc_result->dw_loc_oprnd1.val_class = dw_val_class_addr;
|
13129 |
|
|
mem_loc_result->dw_loc_oprnd1.v.val_addr = rtl;
|
13130 |
|
|
VEC_safe_push (rtx, gc, used_rtx_array, rtl);
|
13131 |
|
|
break;
|
13132 |
|
|
|
13133 |
|
|
case CONCAT:
|
13134 |
|
|
case CONCATN:
|
13135 |
|
|
case VAR_LOCATION:
|
13136 |
|
|
expansion_failed (NULL_TREE, rtl,
|
13137 |
|
|
"CONCAT/CONCATN/VAR_LOCATION is handled only by loc_descriptor");
|
13138 |
|
|
return 0;
|
13139 |
|
|
|
13140 |
|
|
case PRE_MODIFY:
|
13141 |
|
|
/* Extract the PLUS expression nested inside and fall into
|
13142 |
|
|
PLUS code below. */
|
13143 |
|
|
rtl = XEXP (rtl, 1);
|
13144 |
|
|
goto plus;
|
13145 |
|
|
|
13146 |
|
|
case PRE_INC:
|
13147 |
|
|
case PRE_DEC:
|
13148 |
|
|
/* Turn these into a PLUS expression and fall into the PLUS code
|
13149 |
|
|
below. */
|
13150 |
|
|
rtl = gen_rtx_PLUS (word_mode, XEXP (rtl, 0),
|
13151 |
|
|
GEN_INT (GET_CODE (rtl) == PRE_INC
|
13152 |
|
|
? GET_MODE_UNIT_SIZE (mode)
|
13153 |
|
|
: -GET_MODE_UNIT_SIZE (mode)));
|
13154 |
|
|
|
13155 |
|
|
/* ... fall through ... */
|
13156 |
|
|
|
13157 |
|
|
case PLUS:
|
13158 |
|
|
plus:
|
13159 |
|
|
if (is_based_loc (rtl))
|
13160 |
|
|
mem_loc_result = based_loc_descr (XEXP (rtl, 0),
|
13161 |
|
|
INTVAL (XEXP (rtl, 1)),
|
13162 |
|
|
VAR_INIT_STATUS_INITIALIZED);
|
13163 |
|
|
else
|
13164 |
|
|
{
|
13165 |
|
|
mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode,
|
13166 |
|
|
VAR_INIT_STATUS_INITIALIZED);
|
13167 |
|
|
if (mem_loc_result == 0)
|
13168 |
|
|
break;
|
13169 |
|
|
|
13170 |
|
|
if (CONST_INT_P (XEXP (rtl, 1)))
|
13171 |
|
|
loc_descr_plus_const (&mem_loc_result, INTVAL (XEXP (rtl, 1)));
|
13172 |
|
|
else
|
13173 |
|
|
{
|
13174 |
|
|
dw_loc_descr_ref mem_loc_result2
|
13175 |
|
|
= mem_loc_descriptor (XEXP (rtl, 1), mode,
|
13176 |
|
|
VAR_INIT_STATUS_INITIALIZED);
|
13177 |
|
|
if (mem_loc_result2 == 0)
|
13178 |
|
|
break;
|
13179 |
|
|
add_loc_descr (&mem_loc_result, mem_loc_result2);
|
13180 |
|
|
add_loc_descr (&mem_loc_result,
|
13181 |
|
|
new_loc_descr (DW_OP_plus, 0, 0));
|
13182 |
|
|
}
|
13183 |
|
|
}
|
13184 |
|
|
break;
|
13185 |
|
|
|
13186 |
|
|
/* If a pseudo-reg is optimized away, it is possible for it to
|
13187 |
|
|
be replaced with a MEM containing a multiply or shift. */
|
13188 |
|
|
case MINUS:
|
13189 |
|
|
op = DW_OP_minus;
|
13190 |
|
|
goto do_binop;
|
13191 |
|
|
|
13192 |
|
|
case MULT:
|
13193 |
|
|
op = DW_OP_mul;
|
13194 |
|
|
goto do_binop;
|
13195 |
|
|
|
13196 |
|
|
case DIV:
|
13197 |
|
|
op = DW_OP_div;
|
13198 |
|
|
goto do_binop;
|
13199 |
|
|
|
13200 |
|
|
case UMOD:
|
13201 |
|
|
op = DW_OP_mod;
|
13202 |
|
|
goto do_binop;
|
13203 |
|
|
|
13204 |
|
|
case ASHIFT:
|
13205 |
|
|
op = DW_OP_shl;
|
13206 |
|
|
goto do_binop;
|
13207 |
|
|
|
13208 |
|
|
case ASHIFTRT:
|
13209 |
|
|
op = DW_OP_shra;
|
13210 |
|
|
goto do_binop;
|
13211 |
|
|
|
13212 |
|
|
case LSHIFTRT:
|
13213 |
|
|
op = DW_OP_shr;
|
13214 |
|
|
goto do_binop;
|
13215 |
|
|
|
13216 |
|
|
case AND:
|
13217 |
|
|
op = DW_OP_and;
|
13218 |
|
|
goto do_binop;
|
13219 |
|
|
|
13220 |
|
|
case IOR:
|
13221 |
|
|
op = DW_OP_or;
|
13222 |
|
|
goto do_binop;
|
13223 |
|
|
|
13224 |
|
|
case XOR:
|
13225 |
|
|
op = DW_OP_xor;
|
13226 |
|
|
goto do_binop;
|
13227 |
|
|
|
13228 |
|
|
do_binop:
|
13229 |
|
|
op0 = mem_loc_descriptor (XEXP (rtl, 0), mode,
|
13230 |
|
|
VAR_INIT_STATUS_INITIALIZED);
|
13231 |
|
|
op1 = mem_loc_descriptor (XEXP (rtl, 1), mode,
|
13232 |
|
|
VAR_INIT_STATUS_INITIALIZED);
|
13233 |
|
|
|
13234 |
|
|
if (op0 == 0 || op1 == 0)
|
13235 |
|
|
break;
|
13236 |
|
|
|
13237 |
|
|
mem_loc_result = op0;
|
13238 |
|
|
add_loc_descr (&mem_loc_result, op1);
|
13239 |
|
|
add_loc_descr (&mem_loc_result, new_loc_descr (op, 0, 0));
|
13240 |
|
|
break;
|
13241 |
|
|
|
13242 |
|
|
case MOD:
|
13243 |
|
|
op0 = mem_loc_descriptor (XEXP (rtl, 0), mode,
|
13244 |
|
|
VAR_INIT_STATUS_INITIALIZED);
|
13245 |
|
|
op1 = mem_loc_descriptor (XEXP (rtl, 1), mode,
|
13246 |
|
|
VAR_INIT_STATUS_INITIALIZED);
|
13247 |
|
|
|
13248 |
|
|
if (op0 == 0 || op1 == 0)
|
13249 |
|
|
break;
|
13250 |
|
|
|
13251 |
|
|
mem_loc_result = op0;
|
13252 |
|
|
add_loc_descr (&mem_loc_result, op1);
|
13253 |
|
|
add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_over, 0, 0));
|
13254 |
|
|
add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_over, 0, 0));
|
13255 |
|
|
add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_div, 0, 0));
|
13256 |
|
|
add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_mul, 0, 0));
|
13257 |
|
|
add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_minus, 0, 0));
|
13258 |
|
|
break;
|
13259 |
|
|
|
13260 |
|
|
case NOT:
|
13261 |
|
|
op = DW_OP_not;
|
13262 |
|
|
goto do_unop;
|
13263 |
|
|
|
13264 |
|
|
case ABS:
|
13265 |
|
|
op = DW_OP_abs;
|
13266 |
|
|
goto do_unop;
|
13267 |
|
|
|
13268 |
|
|
case NEG:
|
13269 |
|
|
op = DW_OP_neg;
|
13270 |
|
|
goto do_unop;
|
13271 |
|
|
|
13272 |
|
|
do_unop:
|
13273 |
|
|
op0 = mem_loc_descriptor (XEXP (rtl, 0), mode,
|
13274 |
|
|
VAR_INIT_STATUS_INITIALIZED);
|
13275 |
|
|
|
13276 |
|
|
if (op0 == 0)
|
13277 |
|
|
break;
|
13278 |
|
|
|
13279 |
|
|
mem_loc_result = op0;
|
13280 |
|
|
add_loc_descr (&mem_loc_result, new_loc_descr (op, 0, 0));
|
13281 |
|
|
break;
|
13282 |
|
|
|
13283 |
|
|
case CONST_INT:
|
13284 |
|
|
mem_loc_result = int_loc_descriptor (INTVAL (rtl));
|
13285 |
|
|
break;
|
13286 |
|
|
|
13287 |
|
|
case EQ:
|
13288 |
|
|
op = DW_OP_eq;
|
13289 |
|
|
goto do_scompare;
|
13290 |
|
|
|
13291 |
|
|
case GE:
|
13292 |
|
|
op = DW_OP_ge;
|
13293 |
|
|
goto do_scompare;
|
13294 |
|
|
|
13295 |
|
|
case GT:
|
13296 |
|
|
op = DW_OP_gt;
|
13297 |
|
|
goto do_scompare;
|
13298 |
|
|
|
13299 |
|
|
case LE:
|
13300 |
|
|
op = DW_OP_le;
|
13301 |
|
|
goto do_scompare;
|
13302 |
|
|
|
13303 |
|
|
case LT:
|
13304 |
|
|
op = DW_OP_lt;
|
13305 |
|
|
goto do_scompare;
|
13306 |
|
|
|
13307 |
|
|
case NE:
|
13308 |
|
|
op = DW_OP_ne;
|
13309 |
|
|
goto do_scompare;
|
13310 |
|
|
|
13311 |
|
|
do_scompare:
|
13312 |
|
|
if (GET_MODE_SIZE (GET_MODE (XEXP (rtl, 0))) > DWARF2_ADDR_SIZE
|
13313 |
|
|
|| GET_MODE_SIZE (GET_MODE (XEXP (rtl, 1))) > DWARF2_ADDR_SIZE)
|
13314 |
|
|
break;
|
13315 |
|
|
else
|
13316 |
|
|
{
|
13317 |
|
|
enum machine_mode op_mode = GET_MODE (XEXP (rtl, 0));
|
13318 |
|
|
|
13319 |
|
|
if (op_mode == VOIDmode)
|
13320 |
|
|
op_mode = GET_MODE (XEXP (rtl, 1));
|
13321 |
|
|
if (op_mode != VOIDmode && GET_MODE_CLASS (op_mode) != MODE_INT)
|
13322 |
|
|
break;
|
13323 |
|
|
|
13324 |
|
|
op0 = mem_loc_descriptor (XEXP (rtl, 0), mode,
|
13325 |
|
|
VAR_INIT_STATUS_INITIALIZED);
|
13326 |
|
|
op1 = mem_loc_descriptor (XEXP (rtl, 1), mode,
|
13327 |
|
|
VAR_INIT_STATUS_INITIALIZED);
|
13328 |
|
|
|
13329 |
|
|
if (op0 == 0 || op1 == 0)
|
13330 |
|
|
break;
|
13331 |
|
|
|
13332 |
|
|
if (op_mode != VOIDmode
|
13333 |
|
|
&& GET_MODE_SIZE (op_mode) < DWARF2_ADDR_SIZE)
|
13334 |
|
|
{
|
13335 |
|
|
int shift = DWARF2_ADDR_SIZE - GET_MODE_SIZE (op_mode);
|
13336 |
|
|
shift *= BITS_PER_UNIT;
|
13337 |
|
|
/* For eq/ne, if the operands are known to be zero-extended,
|
13338 |
|
|
there is no need to do the fancy shifting up. */
|
13339 |
|
|
if (op == DW_OP_eq || op == DW_OP_ne)
|
13340 |
|
|
{
|
13341 |
|
|
dw_loc_descr_ref last0, last1;
|
13342 |
|
|
for (last0 = op0;
|
13343 |
|
|
last0->dw_loc_next != NULL;
|
13344 |
|
|
last0 = last0->dw_loc_next)
|
13345 |
|
|
;
|
13346 |
|
|
for (last1 = op1;
|
13347 |
|
|
last1->dw_loc_next != NULL;
|
13348 |
|
|
last1 = last1->dw_loc_next)
|
13349 |
|
|
;
|
13350 |
|
|
/* deref_size zero extends, and for constants we can check
|
13351 |
|
|
whether they are zero extended or not. */
|
13352 |
|
|
if (((last0->dw_loc_opc == DW_OP_deref_size
|
13353 |
|
|
&& last0->dw_loc_oprnd1.v.val_int
|
13354 |
|
|
<= GET_MODE_SIZE (op_mode))
|
13355 |
|
|
|| (CONST_INT_P (XEXP (rtl, 0))
|
13356 |
|
|
&& (unsigned HOST_WIDE_INT) INTVAL (XEXP (rtl, 0))
|
13357 |
|
|
== (INTVAL (XEXP (rtl, 0))
|
13358 |
|
|
& GET_MODE_MASK (op_mode))))
|
13359 |
|
|
&& ((last1->dw_loc_opc == DW_OP_deref_size
|
13360 |
|
|
&& last1->dw_loc_oprnd1.v.val_int
|
13361 |
|
|
<= GET_MODE_SIZE (op_mode))
|
13362 |
|
|
|| (CONST_INT_P (XEXP (rtl, 1))
|
13363 |
|
|
&& (unsigned HOST_WIDE_INT)
|
13364 |
|
|
INTVAL (XEXP (rtl, 1))
|
13365 |
|
|
== (INTVAL (XEXP (rtl, 1))
|
13366 |
|
|
& GET_MODE_MASK (op_mode)))))
|
13367 |
|
|
goto do_compare;
|
13368 |
|
|
}
|
13369 |
|
|
add_loc_descr (&op0, int_loc_descriptor (shift));
|
13370 |
|
|
add_loc_descr (&op0, new_loc_descr (DW_OP_shl, 0, 0));
|
13371 |
|
|
if (CONST_INT_P (XEXP (rtl, 1)))
|
13372 |
|
|
op1 = int_loc_descriptor (INTVAL (XEXP (rtl, 1)) << shift);
|
13373 |
|
|
else
|
13374 |
|
|
{
|
13375 |
|
|
add_loc_descr (&op1, int_loc_descriptor (shift));
|
13376 |
|
|
add_loc_descr (&op1, new_loc_descr (DW_OP_shl, 0, 0));
|
13377 |
|
|
}
|
13378 |
|
|
}
|
13379 |
|
|
}
|
13380 |
|
|
|
13381 |
|
|
do_compare:
|
13382 |
|
|
mem_loc_result = op0;
|
13383 |
|
|
add_loc_descr (&mem_loc_result, op1);
|
13384 |
|
|
add_loc_descr (&mem_loc_result, new_loc_descr (op, 0, 0));
|
13385 |
|
|
if (STORE_FLAG_VALUE != 1)
|
13386 |
|
|
{
|
13387 |
|
|
add_loc_descr (&mem_loc_result,
|
13388 |
|
|
int_loc_descriptor (STORE_FLAG_VALUE));
|
13389 |
|
|
add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_mul, 0, 0));
|
13390 |
|
|
}
|
13391 |
|
|
break;
|
13392 |
|
|
|
13393 |
|
|
case GEU:
|
13394 |
|
|
op = DW_OP_ge;
|
13395 |
|
|
goto do_ucompare;
|
13396 |
|
|
|
13397 |
|
|
case GTU:
|
13398 |
|
|
op = DW_OP_gt;
|
13399 |
|
|
goto do_ucompare;
|
13400 |
|
|
|
13401 |
|
|
case LEU:
|
13402 |
|
|
op = DW_OP_le;
|
13403 |
|
|
goto do_ucompare;
|
13404 |
|
|
|
13405 |
|
|
case LTU:
|
13406 |
|
|
op = DW_OP_lt;
|
13407 |
|
|
goto do_ucompare;
|
13408 |
|
|
|
13409 |
|
|
do_ucompare:
|
13410 |
|
|
if (GET_MODE_SIZE (GET_MODE (XEXP (rtl, 0))) > DWARF2_ADDR_SIZE
|
13411 |
|
|
|| GET_MODE_SIZE (GET_MODE (XEXP (rtl, 1))) > DWARF2_ADDR_SIZE)
|
13412 |
|
|
break;
|
13413 |
|
|
else
|
13414 |
|
|
{
|
13415 |
|
|
enum machine_mode op_mode = GET_MODE (XEXP (rtl, 0));
|
13416 |
|
|
|
13417 |
|
|
if (op_mode == VOIDmode)
|
13418 |
|
|
op_mode = GET_MODE (XEXP (rtl, 1));
|
13419 |
|
|
if (op_mode != VOIDmode && GET_MODE_CLASS (op_mode) != MODE_INT)
|
13420 |
|
|
break;
|
13421 |
|
|
|
13422 |
|
|
op0 = mem_loc_descriptor (XEXP (rtl, 0), mode,
|
13423 |
|
|
VAR_INIT_STATUS_INITIALIZED);
|
13424 |
|
|
op1 = mem_loc_descriptor (XEXP (rtl, 1), mode,
|
13425 |
|
|
VAR_INIT_STATUS_INITIALIZED);
|
13426 |
|
|
|
13427 |
|
|
if (op0 == 0 || op1 == 0)
|
13428 |
|
|
break;
|
13429 |
|
|
|
13430 |
|
|
if (op_mode != VOIDmode
|
13431 |
|
|
&& GET_MODE_SIZE (op_mode) < DWARF2_ADDR_SIZE)
|
13432 |
|
|
{
|
13433 |
|
|
HOST_WIDE_INT mask = GET_MODE_MASK (op_mode);
|
13434 |
|
|
dw_loc_descr_ref last0, last1;
|
13435 |
|
|
for (last0 = op0;
|
13436 |
|
|
last0->dw_loc_next != NULL;
|
13437 |
|
|
last0 = last0->dw_loc_next)
|
13438 |
|
|
;
|
13439 |
|
|
for (last1 = op1;
|
13440 |
|
|
last1->dw_loc_next != NULL;
|
13441 |
|
|
last1 = last1->dw_loc_next)
|
13442 |
|
|
;
|
13443 |
|
|
if (CONST_INT_P (XEXP (rtl, 0)))
|
13444 |
|
|
op0 = int_loc_descriptor (INTVAL (XEXP (rtl, 0)) & mask);
|
13445 |
|
|
/* deref_size zero extends, so no need to mask it again. */
|
13446 |
|
|
else if (last0->dw_loc_opc != DW_OP_deref_size
|
13447 |
|
|
|| last0->dw_loc_oprnd1.v.val_int
|
13448 |
|
|
> GET_MODE_SIZE (op_mode))
|
13449 |
|
|
{
|
13450 |
|
|
add_loc_descr (&op0, int_loc_descriptor (mask));
|
13451 |
|
|
add_loc_descr (&op0, new_loc_descr (DW_OP_and, 0, 0));
|
13452 |
|
|
}
|
13453 |
|
|
if (CONST_INT_P (XEXP (rtl, 1)))
|
13454 |
|
|
op1 = int_loc_descriptor (INTVAL (XEXP (rtl, 1)) & mask);
|
13455 |
|
|
/* deref_size zero extends, so no need to mask it again. */
|
13456 |
|
|
else if (last1->dw_loc_opc != DW_OP_deref_size
|
13457 |
|
|
|| last1->dw_loc_oprnd1.v.val_int
|
13458 |
|
|
> GET_MODE_SIZE (op_mode))
|
13459 |
|
|
{
|
13460 |
|
|
add_loc_descr (&op1, int_loc_descriptor (mask));
|
13461 |
|
|
add_loc_descr (&op1, new_loc_descr (DW_OP_and, 0, 0));
|
13462 |
|
|
}
|
13463 |
|
|
}
|
13464 |
|
|
else
|
13465 |
|
|
{
|
13466 |
|
|
HOST_WIDE_INT bias = 1;
|
13467 |
|
|
bias <<= (DWARF2_ADDR_SIZE * BITS_PER_UNIT - 1);
|
13468 |
|
|
add_loc_descr (&op0, new_loc_descr (DW_OP_plus_uconst, bias, 0));
|
13469 |
|
|
if (CONST_INT_P (XEXP (rtl, 1)))
|
13470 |
|
|
op1 = int_loc_descriptor ((unsigned HOST_WIDE_INT) bias
|
13471 |
|
|
+ INTVAL (XEXP (rtl, 1)));
|
13472 |
|
|
else
|
13473 |
|
|
add_loc_descr (&op1, new_loc_descr (DW_OP_plus_uconst,
|
13474 |
|
|
bias, 0));
|
13475 |
|
|
}
|
13476 |
|
|
}
|
13477 |
|
|
goto do_compare;
|
13478 |
|
|
|
13479 |
|
|
case SMIN:
|
13480 |
|
|
case SMAX:
|
13481 |
|
|
case UMIN:
|
13482 |
|
|
case UMAX:
|
13483 |
|
|
if (GET_MODE_CLASS (GET_MODE (XEXP (rtl, 0))) != MODE_INT
|
13484 |
|
|
|| GET_MODE_SIZE (GET_MODE (XEXP (rtl, 0))) > DWARF2_ADDR_SIZE
|
13485 |
|
|
|| GET_MODE (XEXP (rtl, 0)) != GET_MODE (XEXP (rtl, 1)))
|
13486 |
|
|
break;
|
13487 |
|
|
|
13488 |
|
|
op0 = mem_loc_descriptor (XEXP (rtl, 0), mode,
|
13489 |
|
|
VAR_INIT_STATUS_INITIALIZED);
|
13490 |
|
|
op1 = mem_loc_descriptor (XEXP (rtl, 1), mode,
|
13491 |
|
|
VAR_INIT_STATUS_INITIALIZED);
|
13492 |
|
|
|
13493 |
|
|
if (op0 == 0 || op1 == 0)
|
13494 |
|
|
break;
|
13495 |
|
|
|
13496 |
|
|
add_loc_descr (&op0, new_loc_descr (DW_OP_dup, 0, 0));
|
13497 |
|
|
add_loc_descr (&op1, new_loc_descr (DW_OP_swap, 0, 0));
|
13498 |
|
|
add_loc_descr (&op1, new_loc_descr (DW_OP_over, 0, 0));
|
13499 |
|
|
if (GET_CODE (rtl) == UMIN || GET_CODE (rtl) == UMAX)
|
13500 |
|
|
{
|
13501 |
|
|
if (GET_MODE_SIZE (GET_MODE (XEXP (rtl, 0))) < DWARF2_ADDR_SIZE)
|
13502 |
|
|
{
|
13503 |
|
|
HOST_WIDE_INT mask = GET_MODE_MASK (GET_MODE (XEXP (rtl, 0)));
|
13504 |
|
|
add_loc_descr (&op0, int_loc_descriptor (mask));
|
13505 |
|
|
add_loc_descr (&op0, new_loc_descr (DW_OP_and, 0, 0));
|
13506 |
|
|
add_loc_descr (&op1, int_loc_descriptor (mask));
|
13507 |
|
|
add_loc_descr (&op1, new_loc_descr (DW_OP_and, 0, 0));
|
13508 |
|
|
}
|
13509 |
|
|
else
|
13510 |
|
|
{
|
13511 |
|
|
HOST_WIDE_INT bias = 1;
|
13512 |
|
|
bias <<= (DWARF2_ADDR_SIZE * BITS_PER_UNIT - 1);
|
13513 |
|
|
add_loc_descr (&op0, new_loc_descr (DW_OP_plus_uconst, bias, 0));
|
13514 |
|
|
add_loc_descr (&op1, new_loc_descr (DW_OP_plus_uconst, bias, 0));
|
13515 |
|
|
}
|
13516 |
|
|
}
|
13517 |
|
|
else if (GET_MODE_SIZE (GET_MODE (XEXP (rtl, 0))) < DWARF2_ADDR_SIZE)
|
13518 |
|
|
{
|
13519 |
|
|
int shift = DWARF2_ADDR_SIZE
|
13520 |
|
|
- GET_MODE_SIZE (GET_MODE (XEXP (rtl, 0)));
|
13521 |
|
|
shift *= BITS_PER_UNIT;
|
13522 |
|
|
add_loc_descr (&op0, int_loc_descriptor (shift));
|
13523 |
|
|
add_loc_descr (&op0, new_loc_descr (DW_OP_shl, 0, 0));
|
13524 |
|
|
add_loc_descr (&op1, int_loc_descriptor (shift));
|
13525 |
|
|
add_loc_descr (&op1, new_loc_descr (DW_OP_shl, 0, 0));
|
13526 |
|
|
}
|
13527 |
|
|
|
13528 |
|
|
if (GET_CODE (rtl) == SMIN || GET_CODE (rtl) == UMIN)
|
13529 |
|
|
op = DW_OP_lt;
|
13530 |
|
|
else
|
13531 |
|
|
op = DW_OP_gt;
|
13532 |
|
|
mem_loc_result = op0;
|
13533 |
|
|
add_loc_descr (&mem_loc_result, op1);
|
13534 |
|
|
add_loc_descr (&mem_loc_result, new_loc_descr (op, 0, 0));
|
13535 |
|
|
{
|
13536 |
|
|
dw_loc_descr_ref bra_node, drop_node;
|
13537 |
|
|
|
13538 |
|
|
bra_node = new_loc_descr (DW_OP_bra, 0, 0);
|
13539 |
|
|
add_loc_descr (&mem_loc_result, bra_node);
|
13540 |
|
|
add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_swap, 0, 0));
|
13541 |
|
|
drop_node = new_loc_descr (DW_OP_drop, 0, 0);
|
13542 |
|
|
add_loc_descr (&mem_loc_result, drop_node);
|
13543 |
|
|
bra_node->dw_loc_oprnd1.val_class = dw_val_class_loc;
|
13544 |
|
|
bra_node->dw_loc_oprnd1.v.val_loc = drop_node;
|
13545 |
|
|
}
|
13546 |
|
|
break;
|
13547 |
|
|
|
13548 |
|
|
case ZERO_EXTRACT:
|
13549 |
|
|
case SIGN_EXTRACT:
|
13550 |
|
|
if (CONST_INT_P (XEXP (rtl, 1))
|
13551 |
|
|
&& CONST_INT_P (XEXP (rtl, 2))
|
13552 |
|
|
&& ((unsigned) INTVAL (XEXP (rtl, 1))
|
13553 |
|
|
+ (unsigned) INTVAL (XEXP (rtl, 2))
|
13554 |
|
|
<= GET_MODE_BITSIZE (GET_MODE (rtl)))
|
13555 |
|
|
&& GET_MODE_BITSIZE (GET_MODE (rtl)) <= DWARF2_ADDR_SIZE
|
13556 |
|
|
&& GET_MODE_BITSIZE (GET_MODE (XEXP (rtl, 0))) <= DWARF2_ADDR_SIZE)
|
13557 |
|
|
{
|
13558 |
|
|
int shift, size;
|
13559 |
|
|
op0 = mem_loc_descriptor (XEXP (rtl, 0), mode,
|
13560 |
|
|
VAR_INIT_STATUS_INITIALIZED);
|
13561 |
|
|
if (op0 == 0)
|
13562 |
|
|
break;
|
13563 |
|
|
if (GET_CODE (rtl) == SIGN_EXTRACT)
|
13564 |
|
|
op = DW_OP_shra;
|
13565 |
|
|
else
|
13566 |
|
|
op = DW_OP_shr;
|
13567 |
|
|
mem_loc_result = op0;
|
13568 |
|
|
size = INTVAL (XEXP (rtl, 1));
|
13569 |
|
|
shift = INTVAL (XEXP (rtl, 2));
|
13570 |
|
|
if (BITS_BIG_ENDIAN)
|
13571 |
|
|
shift = GET_MODE_BITSIZE (GET_MODE (XEXP (rtl, 0)))
|
13572 |
|
|
- shift - size;
|
13573 |
|
|
if (shift + size != (int) DWARF2_ADDR_SIZE)
|
13574 |
|
|
{
|
13575 |
|
|
add_loc_descr (&mem_loc_result,
|
13576 |
|
|
int_loc_descriptor (DWARF2_ADDR_SIZE
|
13577 |
|
|
- shift - size));
|
13578 |
|
|
add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_shl, 0, 0));
|
13579 |
|
|
}
|
13580 |
|
|
if (size != (int) DWARF2_ADDR_SIZE)
|
13581 |
|
|
{
|
13582 |
|
|
add_loc_descr (&mem_loc_result,
|
13583 |
|
|
int_loc_descriptor (DWARF2_ADDR_SIZE - size));
|
13584 |
|
|
add_loc_descr (&mem_loc_result, new_loc_descr (op, 0, 0));
|
13585 |
|
|
}
|
13586 |
|
|
}
|
13587 |
|
|
break;
|
13588 |
|
|
|
13589 |
|
|
case COMPARE:
|
13590 |
|
|
case IF_THEN_ELSE:
|
13591 |
|
|
case ROTATE:
|
13592 |
|
|
case ROTATERT:
|
13593 |
|
|
case TRUNCATE:
|
13594 |
|
|
/* In theory, we could implement the above. */
|
13595 |
|
|
/* DWARF cannot represent the unsigned compare operations
|
13596 |
|
|
natively. */
|
13597 |
|
|
case SS_MULT:
|
13598 |
|
|
case US_MULT:
|
13599 |
|
|
case SS_DIV:
|
13600 |
|
|
case US_DIV:
|
13601 |
|
|
case SS_PLUS:
|
13602 |
|
|
case US_PLUS:
|
13603 |
|
|
case SS_MINUS:
|
13604 |
|
|
case US_MINUS:
|
13605 |
|
|
case SS_NEG:
|
13606 |
|
|
case US_NEG:
|
13607 |
|
|
case SS_ABS:
|
13608 |
|
|
case SS_ASHIFT:
|
13609 |
|
|
case US_ASHIFT:
|
13610 |
|
|
case SS_TRUNCATE:
|
13611 |
|
|
case US_TRUNCATE:
|
13612 |
|
|
case UDIV:
|
13613 |
|
|
case UNORDERED:
|
13614 |
|
|
case ORDERED:
|
13615 |
|
|
case UNEQ:
|
13616 |
|
|
case UNGE:
|
13617 |
|
|
case UNGT:
|
13618 |
|
|
case UNLE:
|
13619 |
|
|
case UNLT:
|
13620 |
|
|
case LTGT:
|
13621 |
|
|
case FLOAT_EXTEND:
|
13622 |
|
|
case FLOAT_TRUNCATE:
|
13623 |
|
|
case FLOAT:
|
13624 |
|
|
case UNSIGNED_FLOAT:
|
13625 |
|
|
case FIX:
|
13626 |
|
|
case UNSIGNED_FIX:
|
13627 |
|
|
case FRACT_CONVERT:
|
13628 |
|
|
case UNSIGNED_FRACT_CONVERT:
|
13629 |
|
|
case SAT_FRACT:
|
13630 |
|
|
case UNSIGNED_SAT_FRACT:
|
13631 |
|
|
case SQRT:
|
13632 |
|
|
case BSWAP:
|
13633 |
|
|
case FFS:
|
13634 |
|
|
case CLZ:
|
13635 |
|
|
case CTZ:
|
13636 |
|
|
case POPCOUNT:
|
13637 |
|
|
case PARITY:
|
13638 |
|
|
case ASM_OPERANDS:
|
13639 |
|
|
case VEC_MERGE:
|
13640 |
|
|
case VEC_SELECT:
|
13641 |
|
|
case VEC_CONCAT:
|
13642 |
|
|
case VEC_DUPLICATE:
|
13643 |
|
|
case UNSPEC:
|
13644 |
|
|
case HIGH:
|
13645 |
|
|
/* If delegitimize_address couldn't do anything with the UNSPEC, we
|
13646 |
|
|
can't express it in the debug info. This can happen e.g. with some
|
13647 |
|
|
TLS UNSPECs. */
|
13648 |
|
|
break;
|
13649 |
|
|
|
13650 |
|
|
case CONST_STRING:
|
13651 |
|
|
resolve_one_addr (&rtl, NULL);
|
13652 |
|
|
goto symref;
|
13653 |
|
|
|
13654 |
|
|
default:
|
13655 |
|
|
#ifdef ENABLE_CHECKING
|
13656 |
|
|
print_rtl (stderr, rtl);
|
13657 |
|
|
gcc_unreachable ();
|
13658 |
|
|
#else
|
13659 |
|
|
break;
|
13660 |
|
|
#endif
|
13661 |
|
|
}
|
13662 |
|
|
|
13663 |
|
|
if (mem_loc_result && initialized == VAR_INIT_STATUS_UNINITIALIZED)
|
13664 |
|
|
add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_GNU_uninit, 0, 0));
|
13665 |
|
|
|
13666 |
|
|
return mem_loc_result;
|
13667 |
|
|
}
|
13668 |
|
|
|
13669 |
|
|
/* Return a descriptor that describes the concatenation of two locations.
|
13670 |
|
|
This is typically a complex variable. */
|
13671 |
|
|
|
13672 |
|
|
static dw_loc_descr_ref
|
13673 |
|
|
concat_loc_descriptor (rtx x0, rtx x1, enum var_init_status initialized)
|
13674 |
|
|
{
|
13675 |
|
|
dw_loc_descr_ref cc_loc_result = NULL;
|
13676 |
|
|
dw_loc_descr_ref x0_ref
|
13677 |
|
|
= loc_descriptor (x0, VOIDmode, VAR_INIT_STATUS_INITIALIZED);
|
13678 |
|
|
dw_loc_descr_ref x1_ref
|
13679 |
|
|
= loc_descriptor (x1, VOIDmode, VAR_INIT_STATUS_INITIALIZED);
|
13680 |
|
|
|
13681 |
|
|
if (x0_ref == 0 || x1_ref == 0)
|
13682 |
|
|
return 0;
|
13683 |
|
|
|
13684 |
|
|
cc_loc_result = x0_ref;
|
13685 |
|
|
add_loc_descr_op_piece (&cc_loc_result, GET_MODE_SIZE (GET_MODE (x0)));
|
13686 |
|
|
|
13687 |
|
|
add_loc_descr (&cc_loc_result, x1_ref);
|
13688 |
|
|
add_loc_descr_op_piece (&cc_loc_result, GET_MODE_SIZE (GET_MODE (x1)));
|
13689 |
|
|
|
13690 |
|
|
if (initialized == VAR_INIT_STATUS_UNINITIALIZED)
|
13691 |
|
|
add_loc_descr (&cc_loc_result, new_loc_descr (DW_OP_GNU_uninit, 0, 0));
|
13692 |
|
|
|
13693 |
|
|
return cc_loc_result;
|
13694 |
|
|
}
|
13695 |
|
|
|
13696 |
|
|
/* Return a descriptor that describes the concatenation of N
|
13697 |
|
|
locations. */
|
13698 |
|
|
|
13699 |
|
|
static dw_loc_descr_ref
|
13700 |
|
|
concatn_loc_descriptor (rtx concatn, enum var_init_status initialized)
|
13701 |
|
|
{
|
13702 |
|
|
unsigned int i;
|
13703 |
|
|
dw_loc_descr_ref cc_loc_result = NULL;
|
13704 |
|
|
unsigned int n = XVECLEN (concatn, 0);
|
13705 |
|
|
|
13706 |
|
|
for (i = 0; i < n; ++i)
|
13707 |
|
|
{
|
13708 |
|
|
dw_loc_descr_ref ref;
|
13709 |
|
|
rtx x = XVECEXP (concatn, 0, i);
|
13710 |
|
|
|
13711 |
|
|
ref = loc_descriptor (x, VOIDmode, VAR_INIT_STATUS_INITIALIZED);
|
13712 |
|
|
if (ref == NULL)
|
13713 |
|
|
return NULL;
|
13714 |
|
|
|
13715 |
|
|
add_loc_descr (&cc_loc_result, ref);
|
13716 |
|
|
add_loc_descr_op_piece (&cc_loc_result, GET_MODE_SIZE (GET_MODE (x)));
|
13717 |
|
|
}
|
13718 |
|
|
|
13719 |
|
|
if (cc_loc_result && initialized == VAR_INIT_STATUS_UNINITIALIZED)
|
13720 |
|
|
add_loc_descr (&cc_loc_result, new_loc_descr (DW_OP_GNU_uninit, 0, 0));
|
13721 |
|
|
|
13722 |
|
|
return cc_loc_result;
|
13723 |
|
|
}
|
13724 |
|
|
|
13725 |
|
|
/* Output a proper Dwarf location descriptor for a variable or parameter
|
13726 |
|
|
which is either allocated in a register or in a memory location. For a
|
13727 |
|
|
register, we just generate an OP_REG and the register number. For a
|
13728 |
|
|
memory location we provide a Dwarf postfix expression describing how to
|
13729 |
|
|
generate the (dynamic) address of the object onto the address stack.
|
13730 |
|
|
|
13731 |
|
|
MODE is mode of the decl if this loc_descriptor is going to be used in
|
13732 |
|
|
.debug_loc section where DW_OP_stack_value and DW_OP_implicit_value are
|
13733 |
|
|
allowed, VOIDmode otherwise.
|
13734 |
|
|
|
13735 |
|
|
If we don't know how to describe it, return 0. */
|
13736 |
|
|
|
13737 |
|
|
static dw_loc_descr_ref
|
13738 |
|
|
loc_descriptor (rtx rtl, enum machine_mode mode,
|
13739 |
|
|
enum var_init_status initialized)
|
13740 |
|
|
{
|
13741 |
|
|
dw_loc_descr_ref loc_result = NULL;
|
13742 |
|
|
|
13743 |
|
|
switch (GET_CODE (rtl))
|
13744 |
|
|
{
|
13745 |
|
|
case SUBREG:
|
13746 |
|
|
/* The case of a subreg may arise when we have a local (register)
|
13747 |
|
|
variable or a formal (register) parameter which doesn't quite fill
|
13748 |
|
|
up an entire register. For now, just assume that it is
|
13749 |
|
|
legitimate to make the Dwarf info refer to the whole register which
|
13750 |
|
|
contains the given subreg. */
|
13751 |
|
|
loc_result = loc_descriptor (SUBREG_REG (rtl), mode, initialized);
|
13752 |
|
|
break;
|
13753 |
|
|
|
13754 |
|
|
case REG:
|
13755 |
|
|
loc_result = reg_loc_descriptor (rtl, initialized);
|
13756 |
|
|
break;
|
13757 |
|
|
|
13758 |
|
|
case SIGN_EXTEND:
|
13759 |
|
|
case ZERO_EXTEND:
|
13760 |
|
|
loc_result = loc_descriptor (XEXP (rtl, 0), mode, initialized);
|
13761 |
|
|
break;
|
13762 |
|
|
|
13763 |
|
|
case MEM:
|
13764 |
|
|
loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl),
|
13765 |
|
|
initialized);
|
13766 |
|
|
if (loc_result == NULL)
|
13767 |
|
|
loc_result = tls_mem_loc_descriptor (rtl);
|
13768 |
|
|
if (loc_result == NULL)
|
13769 |
|
|
{
|
13770 |
|
|
rtx new_rtl = avoid_constant_pool_reference (rtl);
|
13771 |
|
|
if (new_rtl != rtl)
|
13772 |
|
|
loc_result = loc_descriptor (new_rtl, mode, initialized);
|
13773 |
|
|
}
|
13774 |
|
|
break;
|
13775 |
|
|
|
13776 |
|
|
case CONCAT:
|
13777 |
|
|
loc_result = concat_loc_descriptor (XEXP (rtl, 0), XEXP (rtl, 1),
|
13778 |
|
|
initialized);
|
13779 |
|
|
break;
|
13780 |
|
|
|
13781 |
|
|
case CONCATN:
|
13782 |
|
|
loc_result = concatn_loc_descriptor (rtl, initialized);
|
13783 |
|
|
break;
|
13784 |
|
|
|
13785 |
|
|
case VAR_LOCATION:
|
13786 |
|
|
/* Single part. */
|
13787 |
|
|
if (GET_CODE (PAT_VAR_LOCATION_LOC (rtl)) != PARALLEL)
|
13788 |
|
|
{
|
13789 |
|
|
rtx loc = PAT_VAR_LOCATION_LOC (rtl);
|
13790 |
|
|
if (GET_CODE (loc) == EXPR_LIST)
|
13791 |
|
|
loc = XEXP (loc, 0);
|
13792 |
|
|
loc_result = loc_descriptor (loc, mode, initialized);
|
13793 |
|
|
break;
|
13794 |
|
|
}
|
13795 |
|
|
|
13796 |
|
|
rtl = XEXP (rtl, 1);
|
13797 |
|
|
/* FALLTHRU */
|
13798 |
|
|
|
13799 |
|
|
case PARALLEL:
|
13800 |
|
|
{
|
13801 |
|
|
rtvec par_elems = XVEC (rtl, 0);
|
13802 |
|
|
int num_elem = GET_NUM_ELEM (par_elems);
|
13803 |
|
|
enum machine_mode mode;
|
13804 |
|
|
int i;
|
13805 |
|
|
|
13806 |
|
|
/* Create the first one, so we have something to add to. */
|
13807 |
|
|
loc_result = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0),
|
13808 |
|
|
VOIDmode, initialized);
|
13809 |
|
|
if (loc_result == NULL)
|
13810 |
|
|
return NULL;
|
13811 |
|
|
mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0));
|
13812 |
|
|
add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode));
|
13813 |
|
|
for (i = 1; i < num_elem; i++)
|
13814 |
|
|
{
|
13815 |
|
|
dw_loc_descr_ref temp;
|
13816 |
|
|
|
13817 |
|
|
temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0),
|
13818 |
|
|
VOIDmode, initialized);
|
13819 |
|
|
if (temp == NULL)
|
13820 |
|
|
return NULL;
|
13821 |
|
|
add_loc_descr (&loc_result, temp);
|
13822 |
|
|
mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0));
|
13823 |
|
|
add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode));
|
13824 |
|
|
}
|
13825 |
|
|
}
|
13826 |
|
|
break;
|
13827 |
|
|
|
13828 |
|
|
case CONST_INT:
|
13829 |
|
|
if (mode != VOIDmode && mode != BLKmode)
|
13830 |
|
|
loc_result = address_of_int_loc_descriptor (GET_MODE_SIZE (mode),
|
13831 |
|
|
INTVAL (rtl));
|
13832 |
|
|
break;
|
13833 |
|
|
|
13834 |
|
|
case CONST_DOUBLE:
|
13835 |
|
|
if (mode == VOIDmode)
|
13836 |
|
|
mode = GET_MODE (rtl);
|
13837 |
|
|
|
13838 |
|
|
if (mode != VOIDmode && (dwarf_version >= 4 || !dwarf_strict))
|
13839 |
|
|
{
|
13840 |
|
|
gcc_assert (mode == GET_MODE (rtl) || VOIDmode == GET_MODE (rtl));
|
13841 |
|
|
|
13842 |
|
|
/* Note that a CONST_DOUBLE rtx could represent either an integer
|
13843 |
|
|
or a floating-point constant. A CONST_DOUBLE is used whenever
|
13844 |
|
|
the constant requires more than one word in order to be
|
13845 |
|
|
adequately represented. We output CONST_DOUBLEs as blocks. */
|
13846 |
|
|
loc_result = new_loc_descr (DW_OP_implicit_value,
|
13847 |
|
|
GET_MODE_SIZE (mode), 0);
|
13848 |
|
|
if (SCALAR_FLOAT_MODE_P (mode))
|
13849 |
|
|
{
|
13850 |
|
|
unsigned int length = GET_MODE_SIZE (mode);
|
13851 |
|
|
unsigned char *array = GGC_NEWVEC (unsigned char, length);
|
13852 |
|
|
|
13853 |
|
|
insert_float (rtl, array);
|
13854 |
|
|
loc_result->dw_loc_oprnd2.val_class = dw_val_class_vec;
|
13855 |
|
|
loc_result->dw_loc_oprnd2.v.val_vec.length = length / 4;
|
13856 |
|
|
loc_result->dw_loc_oprnd2.v.val_vec.elt_size = 4;
|
13857 |
|
|
loc_result->dw_loc_oprnd2.v.val_vec.array = array;
|
13858 |
|
|
}
|
13859 |
|
|
else
|
13860 |
|
|
{
|
13861 |
|
|
loc_result->dw_loc_oprnd2.val_class = dw_val_class_const_double;
|
13862 |
|
|
loc_result->dw_loc_oprnd2.v.val_double.high
|
13863 |
|
|
= CONST_DOUBLE_HIGH (rtl);
|
13864 |
|
|
loc_result->dw_loc_oprnd2.v.val_double.low
|
13865 |
|
|
= CONST_DOUBLE_LOW (rtl);
|
13866 |
|
|
}
|
13867 |
|
|
}
|
13868 |
|
|
break;
|
13869 |
|
|
|
13870 |
|
|
case CONST_VECTOR:
|
13871 |
|
|
if (mode == VOIDmode)
|
13872 |
|
|
mode = GET_MODE (rtl);
|
13873 |
|
|
|
13874 |
|
|
if (mode != VOIDmode && (dwarf_version >= 4 || !dwarf_strict))
|
13875 |
|
|
{
|
13876 |
|
|
unsigned int elt_size = GET_MODE_UNIT_SIZE (GET_MODE (rtl));
|
13877 |
|
|
unsigned int length = CONST_VECTOR_NUNITS (rtl);
|
13878 |
|
|
unsigned char *array = GGC_NEWVEC (unsigned char, length * elt_size);
|
13879 |
|
|
unsigned int i;
|
13880 |
|
|
unsigned char *p;
|
13881 |
|
|
|
13882 |
|
|
gcc_assert (mode == GET_MODE (rtl) || VOIDmode == GET_MODE (rtl));
|
13883 |
|
|
switch (GET_MODE_CLASS (mode))
|
13884 |
|
|
{
|
13885 |
|
|
case MODE_VECTOR_INT:
|
13886 |
|
|
for (i = 0, p = array; i < length; i++, p += elt_size)
|
13887 |
|
|
{
|
13888 |
|
|
rtx elt = CONST_VECTOR_ELT (rtl, i);
|
13889 |
|
|
HOST_WIDE_INT lo, hi;
|
13890 |
|
|
|
13891 |
|
|
switch (GET_CODE (elt))
|
13892 |
|
|
{
|
13893 |
|
|
case CONST_INT:
|
13894 |
|
|
lo = INTVAL (elt);
|
13895 |
|
|
hi = -(lo < 0);
|
13896 |
|
|
break;
|
13897 |
|
|
|
13898 |
|
|
case CONST_DOUBLE:
|
13899 |
|
|
lo = CONST_DOUBLE_LOW (elt);
|
13900 |
|
|
hi = CONST_DOUBLE_HIGH (elt);
|
13901 |
|
|
break;
|
13902 |
|
|
|
13903 |
|
|
default:
|
13904 |
|
|
gcc_unreachable ();
|
13905 |
|
|
}
|
13906 |
|
|
|
13907 |
|
|
if (elt_size <= sizeof (HOST_WIDE_INT))
|
13908 |
|
|
insert_int (lo, elt_size, p);
|
13909 |
|
|
else
|
13910 |
|
|
{
|
13911 |
|
|
unsigned char *p0 = p;
|
13912 |
|
|
unsigned char *p1 = p + sizeof (HOST_WIDE_INT);
|
13913 |
|
|
|
13914 |
|
|
gcc_assert (elt_size == 2 * sizeof (HOST_WIDE_INT));
|
13915 |
|
|
if (WORDS_BIG_ENDIAN)
|
13916 |
|
|
{
|
13917 |
|
|
p0 = p1;
|
13918 |
|
|
p1 = p;
|
13919 |
|
|
}
|
13920 |
|
|
insert_int (lo, sizeof (HOST_WIDE_INT), p0);
|
13921 |
|
|
insert_int (hi, sizeof (HOST_WIDE_INT), p1);
|
13922 |
|
|
}
|
13923 |
|
|
}
|
13924 |
|
|
break;
|
13925 |
|
|
|
13926 |
|
|
case MODE_VECTOR_FLOAT:
|
13927 |
|
|
for (i = 0, p = array; i < length; i++, p += elt_size)
|
13928 |
|
|
{
|
13929 |
|
|
rtx elt = CONST_VECTOR_ELT (rtl, i);
|
13930 |
|
|
insert_float (elt, p);
|
13931 |
|
|
}
|
13932 |
|
|
break;
|
13933 |
|
|
|
13934 |
|
|
default:
|
13935 |
|
|
gcc_unreachable ();
|
13936 |
|
|
}
|
13937 |
|
|
|
13938 |
|
|
loc_result = new_loc_descr (DW_OP_implicit_value,
|
13939 |
|
|
length * elt_size, 0);
|
13940 |
|
|
loc_result->dw_loc_oprnd2.val_class = dw_val_class_vec;
|
13941 |
|
|
loc_result->dw_loc_oprnd2.v.val_vec.length = length;
|
13942 |
|
|
loc_result->dw_loc_oprnd2.v.val_vec.elt_size = elt_size;
|
13943 |
|
|
loc_result->dw_loc_oprnd2.v.val_vec.array = array;
|
13944 |
|
|
}
|
13945 |
|
|
break;
|
13946 |
|
|
|
13947 |
|
|
case CONST:
|
13948 |
|
|
if (mode == VOIDmode
|
13949 |
|
|
|| GET_CODE (XEXP (rtl, 0)) == CONST_INT
|
13950 |
|
|
|| GET_CODE (XEXP (rtl, 0)) == CONST_DOUBLE
|
13951 |
|
|
|| GET_CODE (XEXP (rtl, 0)) == CONST_VECTOR)
|
13952 |
|
|
{
|
13953 |
|
|
loc_result = loc_descriptor (XEXP (rtl, 0), mode, initialized);
|
13954 |
|
|
break;
|
13955 |
|
|
}
|
13956 |
|
|
/* FALLTHROUGH */
|
13957 |
|
|
case SYMBOL_REF:
|
13958 |
|
|
if (!const_ok_for_output (rtl))
|
13959 |
|
|
break;
|
13960 |
|
|
case LABEL_REF:
|
13961 |
|
|
if (mode != VOIDmode && GET_MODE_SIZE (mode) == DWARF2_ADDR_SIZE
|
13962 |
|
|
&& (dwarf_version >= 4 || !dwarf_strict))
|
13963 |
|
|
{
|
13964 |
|
|
loc_result = new_loc_descr (DW_OP_addr, 0, 0);
|
13965 |
|
|
loc_result->dw_loc_oprnd1.val_class = dw_val_class_addr;
|
13966 |
|
|
loc_result->dw_loc_oprnd1.v.val_addr = rtl;
|
13967 |
|
|
add_loc_descr (&loc_result, new_loc_descr (DW_OP_stack_value, 0, 0));
|
13968 |
|
|
VEC_safe_push (rtx, gc, used_rtx_array, rtl);
|
13969 |
|
|
}
|
13970 |
|
|
break;
|
13971 |
|
|
|
13972 |
|
|
default:
|
13973 |
|
|
if (GET_MODE_CLASS (mode) == MODE_INT && GET_MODE (rtl) == mode
|
13974 |
|
|
&& GET_MODE_SIZE (GET_MODE (rtl)) <= DWARF2_ADDR_SIZE
|
13975 |
|
|
&& (dwarf_version >= 4 || !dwarf_strict))
|
13976 |
|
|
{
|
13977 |
|
|
/* Value expression. */
|
13978 |
|
|
loc_result = mem_loc_descriptor (rtl, VOIDmode, initialized);
|
13979 |
|
|
if (loc_result)
|
13980 |
|
|
add_loc_descr (&loc_result,
|
13981 |
|
|
new_loc_descr (DW_OP_stack_value, 0, 0));
|
13982 |
|
|
}
|
13983 |
|
|
break;
|
13984 |
|
|
}
|
13985 |
|
|
|
13986 |
|
|
return loc_result;
|
13987 |
|
|
}
|
13988 |
|
|
|
13989 |
|
|
/* We need to figure out what section we should use as the base for the
|
13990 |
|
|
address ranges where a given location is valid.
|
13991 |
|
|
1. If this particular DECL has a section associated with it, use that.
|
13992 |
|
|
2. If this function has a section associated with it, use that.
|
13993 |
|
|
3. Otherwise, use the text section.
|
13994 |
|
|
XXX: If you split a variable across multiple sections, we won't notice. */
|
13995 |
|
|
|
13996 |
|
|
static const char *
|
13997 |
|
|
secname_for_decl (const_tree decl)
|
13998 |
|
|
{
|
13999 |
|
|
const char *secname;
|
14000 |
|
|
|
14001 |
|
|
if (VAR_OR_FUNCTION_DECL_P (decl) && DECL_SECTION_NAME (decl))
|
14002 |
|
|
{
|
14003 |
|
|
tree sectree = DECL_SECTION_NAME (decl);
|
14004 |
|
|
secname = TREE_STRING_POINTER (sectree);
|
14005 |
|
|
}
|
14006 |
|
|
else if (current_function_decl && DECL_SECTION_NAME (current_function_decl))
|
14007 |
|
|
{
|
14008 |
|
|
tree sectree = DECL_SECTION_NAME (current_function_decl);
|
14009 |
|
|
secname = TREE_STRING_POINTER (sectree);
|
14010 |
|
|
}
|
14011 |
|
|
else if (cfun && in_cold_section_p)
|
14012 |
|
|
secname = crtl->subsections.cold_section_label;
|
14013 |
|
|
else
|
14014 |
|
|
secname = text_section_label;
|
14015 |
|
|
|
14016 |
|
|
return secname;
|
14017 |
|
|
}
|
14018 |
|
|
|
14019 |
|
|
/* Return true when DECL_BY_REFERENCE is defined and set for DECL. */
|
14020 |
|
|
|
14021 |
|
|
static bool
|
14022 |
|
|
decl_by_reference_p (tree decl)
|
14023 |
|
|
{
|
14024 |
|
|
return ((TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == RESULT_DECL
|
14025 |
|
|
|| TREE_CODE (decl) == VAR_DECL)
|
14026 |
|
|
&& DECL_BY_REFERENCE (decl));
|
14027 |
|
|
}
|
14028 |
|
|
|
14029 |
|
|
/* Helper function for dw_loc_list. Compute proper Dwarf location descriptor
|
14030 |
|
|
for VARLOC. */
|
14031 |
|
|
|
14032 |
|
|
static dw_loc_descr_ref
|
14033 |
|
|
dw_loc_list_1 (tree loc, rtx varloc, int want_address,
|
14034 |
|
|
enum var_init_status initialized)
|
14035 |
|
|
{
|
14036 |
|
|
int have_address = 0;
|
14037 |
|
|
dw_loc_descr_ref descr;
|
14038 |
|
|
enum machine_mode mode;
|
14039 |
|
|
|
14040 |
|
|
if (want_address != 2)
|
14041 |
|
|
{
|
14042 |
|
|
gcc_assert (GET_CODE (varloc) == VAR_LOCATION);
|
14043 |
|
|
/* Single part. */
|
14044 |
|
|
if (GET_CODE (PAT_VAR_LOCATION_LOC (varloc)) != PARALLEL)
|
14045 |
|
|
{
|
14046 |
|
|
varloc = PAT_VAR_LOCATION_LOC (varloc);
|
14047 |
|
|
if (GET_CODE (varloc) == EXPR_LIST)
|
14048 |
|
|
varloc = XEXP (varloc, 0);
|
14049 |
|
|
mode = GET_MODE (varloc);
|
14050 |
|
|
if (MEM_P (varloc))
|
14051 |
|
|
{
|
14052 |
|
|
rtx addr = XEXP (varloc, 0);
|
14053 |
|
|
descr = mem_loc_descriptor (addr, mode, initialized);
|
14054 |
|
|
if (descr)
|
14055 |
|
|
have_address = 1;
|
14056 |
|
|
else
|
14057 |
|
|
{
|
14058 |
|
|
rtx x = avoid_constant_pool_reference (varloc);
|
14059 |
|
|
if (x != varloc)
|
14060 |
|
|
descr = mem_loc_descriptor (x, mode, initialized);
|
14061 |
|
|
}
|
14062 |
|
|
}
|
14063 |
|
|
else
|
14064 |
|
|
descr = mem_loc_descriptor (varloc, mode, initialized);
|
14065 |
|
|
}
|
14066 |
|
|
else
|
14067 |
|
|
return 0;
|
14068 |
|
|
}
|
14069 |
|
|
else
|
14070 |
|
|
{
|
14071 |
|
|
descr = loc_descriptor (varloc, DECL_MODE (loc), initialized);
|
14072 |
|
|
have_address = 1;
|
14073 |
|
|
}
|
14074 |
|
|
|
14075 |
|
|
if (!descr)
|
14076 |
|
|
return 0;
|
14077 |
|
|
|
14078 |
|
|
if (want_address == 2 && !have_address
|
14079 |
|
|
&& (dwarf_version >= 4 || !dwarf_strict))
|
14080 |
|
|
{
|
14081 |
|
|
if (int_size_in_bytes (TREE_TYPE (loc)) > DWARF2_ADDR_SIZE)
|
14082 |
|
|
{
|
14083 |
|
|
expansion_failed (loc, NULL_RTX,
|
14084 |
|
|
"DWARF address size mismatch");
|
14085 |
|
|
return 0;
|
14086 |
|
|
}
|
14087 |
|
|
add_loc_descr (&descr, new_loc_descr (DW_OP_stack_value, 0, 0));
|
14088 |
|
|
have_address = 1;
|
14089 |
|
|
}
|
14090 |
|
|
/* Show if we can't fill the request for an address. */
|
14091 |
|
|
if (want_address && !have_address)
|
14092 |
|
|
{
|
14093 |
|
|
expansion_failed (loc, NULL_RTX,
|
14094 |
|
|
"Want address and only have value");
|
14095 |
|
|
return 0;
|
14096 |
|
|
}
|
14097 |
|
|
|
14098 |
|
|
/* If we've got an address and don't want one, dereference. */
|
14099 |
|
|
if (!want_address && have_address)
|
14100 |
|
|
{
|
14101 |
|
|
HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (loc));
|
14102 |
|
|
enum dwarf_location_atom op;
|
14103 |
|
|
|
14104 |
|
|
if (size > DWARF2_ADDR_SIZE || size == -1)
|
14105 |
|
|
{
|
14106 |
|
|
expansion_failed (loc, NULL_RTX,
|
14107 |
|
|
"DWARF address size mismatch");
|
14108 |
|
|
return 0;
|
14109 |
|
|
}
|
14110 |
|
|
else if (size == DWARF2_ADDR_SIZE)
|
14111 |
|
|
op = DW_OP_deref;
|
14112 |
|
|
else
|
14113 |
|
|
op = DW_OP_deref_size;
|
14114 |
|
|
|
14115 |
|
|
add_loc_descr (&descr, new_loc_descr (op, size, 0));
|
14116 |
|
|
}
|
14117 |
|
|
|
14118 |
|
|
return descr;
|
14119 |
|
|
}
|
14120 |
|
|
|
14121 |
|
|
/* Return the dwarf representation of the location list LOC_LIST of
|
14122 |
|
|
DECL. WANT_ADDRESS has the same meaning as in loc_list_from_tree
|
14123 |
|
|
function. */
|
14124 |
|
|
|
14125 |
|
|
static dw_loc_list_ref
|
14126 |
|
|
dw_loc_list (var_loc_list *loc_list, tree decl, int want_address)
|
14127 |
|
|
{
|
14128 |
|
|
const char *endname, *secname;
|
14129 |
|
|
rtx varloc;
|
14130 |
|
|
enum var_init_status initialized;
|
14131 |
|
|
struct var_loc_node *node;
|
14132 |
|
|
dw_loc_descr_ref descr;
|
14133 |
|
|
char label_id[MAX_ARTIFICIAL_LABEL_BYTES];
|
14134 |
|
|
dw_loc_list_ref list = NULL;
|
14135 |
|
|
dw_loc_list_ref *listp = &list;
|
14136 |
|
|
|
14137 |
|
|
/* Now that we know what section we are using for a base,
|
14138 |
|
|
actually construct the list of locations.
|
14139 |
|
|
The first location information is what is passed to the
|
14140 |
|
|
function that creates the location list, and the remaining
|
14141 |
|
|
locations just get added on to that list.
|
14142 |
|
|
Note that we only know the start address for a location
|
14143 |
|
|
(IE location changes), so to build the range, we use
|
14144 |
|
|
the range [current location start, next location start].
|
14145 |
|
|
This means we have to special case the last node, and generate
|
14146 |
|
|
a range of [last location start, end of function label]. */
|
14147 |
|
|
|
14148 |
|
|
secname = secname_for_decl (decl);
|
14149 |
|
|
|
14150 |
|
|
for (node = loc_list->first; node->next; node = node->next)
|
14151 |
|
|
if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX)
|
14152 |
|
|
{
|
14153 |
|
|
/* The variable has a location between NODE->LABEL and
|
14154 |
|
|
NODE->NEXT->LABEL. */
|
14155 |
|
|
initialized = NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
|
14156 |
|
|
varloc = NOTE_VAR_LOCATION (node->var_loc_note);
|
14157 |
|
|
descr = dw_loc_list_1 (decl, varloc, want_address, initialized);
|
14158 |
|
|
if (descr)
|
14159 |
|
|
{
|
14160 |
|
|
*listp = new_loc_list (descr, node->label, node->next->label,
|
14161 |
|
|
secname);
|
14162 |
|
|
listp = &(*listp)->dw_loc_next;
|
14163 |
|
|
}
|
14164 |
|
|
}
|
14165 |
|
|
|
14166 |
|
|
/* If the variable has a location at the last label
|
14167 |
|
|
it keeps its location until the end of function. */
|
14168 |
|
|
if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX)
|
14169 |
|
|
{
|
14170 |
|
|
initialized = NOTE_VAR_LOCATION_STATUS (node->var_loc_note);
|
14171 |
|
|
varloc = NOTE_VAR_LOCATION (node->var_loc_note);
|
14172 |
|
|
descr = dw_loc_list_1 (decl, varloc, want_address, initialized);
|
14173 |
|
|
if (descr)
|
14174 |
|
|
{
|
14175 |
|
|
if (!current_function_decl)
|
14176 |
|
|
endname = text_end_label;
|
14177 |
|
|
else
|
14178 |
|
|
{
|
14179 |
|
|
ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL,
|
14180 |
|
|
current_function_funcdef_no);
|
14181 |
|
|
endname = ggc_strdup (label_id);
|
14182 |
|
|
}
|
14183 |
|
|
|
14184 |
|
|
*listp = new_loc_list (descr, node->label, endname, secname);
|
14185 |
|
|
listp = &(*listp)->dw_loc_next;
|
14186 |
|
|
}
|
14187 |
|
|
}
|
14188 |
|
|
|
14189 |
|
|
/* Try to avoid the overhead of a location list emitting a location
|
14190 |
|
|
expression instead, but only if we didn't have more than one
|
14191 |
|
|
location entry in the first place. If some entries were not
|
14192 |
|
|
representable, we don't want to pretend a single entry that was
|
14193 |
|
|
applies to the entire scope in which the variable is
|
14194 |
|
|
available. */
|
14195 |
|
|
if (list && loc_list->first->next)
|
14196 |
|
|
gen_llsym (list);
|
14197 |
|
|
|
14198 |
|
|
return list;
|
14199 |
|
|
}
|
14200 |
|
|
|
14201 |
|
|
/* Return if the loc_list has only single element and thus can be represented
|
14202 |
|
|
as location description. */
|
14203 |
|
|
|
14204 |
|
|
static bool
|
14205 |
|
|
single_element_loc_list_p (dw_loc_list_ref list)
|
14206 |
|
|
{
|
14207 |
|
|
gcc_assert (!list->dw_loc_next || list->ll_symbol);
|
14208 |
|
|
return !list->ll_symbol;
|
14209 |
|
|
}
|
14210 |
|
|
|
14211 |
|
|
/* To each location in list LIST add loc descr REF. */
|
14212 |
|
|
|
14213 |
|
|
static void
|
14214 |
|
|
add_loc_descr_to_each (dw_loc_list_ref list, dw_loc_descr_ref ref)
|
14215 |
|
|
{
|
14216 |
|
|
dw_loc_descr_ref copy;
|
14217 |
|
|
add_loc_descr (&list->expr, ref);
|
14218 |
|
|
list = list->dw_loc_next;
|
14219 |
|
|
while (list)
|
14220 |
|
|
{
|
14221 |
|
|
copy = GGC_CNEW (dw_loc_descr_node);
|
14222 |
|
|
memcpy (copy, ref, sizeof (dw_loc_descr_node));
|
14223 |
|
|
add_loc_descr (&list->expr, copy);
|
14224 |
|
|
while (copy->dw_loc_next)
|
14225 |
|
|
{
|
14226 |
|
|
dw_loc_descr_ref new_copy = GGC_CNEW (dw_loc_descr_node);
|
14227 |
|
|
memcpy (new_copy, copy->dw_loc_next, sizeof (dw_loc_descr_node));
|
14228 |
|
|
copy->dw_loc_next = new_copy;
|
14229 |
|
|
copy = new_copy;
|
14230 |
|
|
}
|
14231 |
|
|
list = list->dw_loc_next;
|
14232 |
|
|
}
|
14233 |
|
|
}
|
14234 |
|
|
|
14235 |
|
|
/* Given two lists RET and LIST
|
14236 |
|
|
produce location list that is result of adding expression in LIST
|
14237 |
|
|
to expression in RET on each possition in program.
|
14238 |
|
|
Might be destructive on both RET and LIST.
|
14239 |
|
|
|
14240 |
|
|
TODO: We handle only simple cases of RET or LIST having at most one
|
14241 |
|
|
element. General case would inolve sorting the lists in program order
|
14242 |
|
|
and merging them that will need some additional work.
|
14243 |
|
|
Adding that will improve quality of debug info especially for SRA-ed
|
14244 |
|
|
structures. */
|
14245 |
|
|
|
14246 |
|
|
static void
|
14247 |
|
|
add_loc_list (dw_loc_list_ref *ret, dw_loc_list_ref list)
|
14248 |
|
|
{
|
14249 |
|
|
if (!list)
|
14250 |
|
|
return;
|
14251 |
|
|
if (!*ret)
|
14252 |
|
|
{
|
14253 |
|
|
*ret = list;
|
14254 |
|
|
return;
|
14255 |
|
|
}
|
14256 |
|
|
if (!list->dw_loc_next)
|
14257 |
|
|
{
|
14258 |
|
|
add_loc_descr_to_each (*ret, list->expr);
|
14259 |
|
|
return;
|
14260 |
|
|
}
|
14261 |
|
|
if (!(*ret)->dw_loc_next)
|
14262 |
|
|
{
|
14263 |
|
|
add_loc_descr_to_each (list, (*ret)->expr);
|
14264 |
|
|
*ret = list;
|
14265 |
|
|
return;
|
14266 |
|
|
}
|
14267 |
|
|
expansion_failed (NULL_TREE, NULL_RTX,
|
14268 |
|
|
"Don't know how to merge two non-trivial"
|
14269 |
|
|
" location lists.\n");
|
14270 |
|
|
*ret = NULL;
|
14271 |
|
|
return;
|
14272 |
|
|
}
|
14273 |
|
|
|
14274 |
|
|
/* LOC is constant expression. Try a luck, look it up in constant
|
14275 |
|
|
pool and return its loc_descr of its address. */
|
14276 |
|
|
|
14277 |
|
|
static dw_loc_descr_ref
|
14278 |
|
|
cst_pool_loc_descr (tree loc)
|
14279 |
|
|
{
|
14280 |
|
|
/* Get an RTL for this, if something has been emitted. */
|
14281 |
|
|
rtx rtl = lookup_constant_def (loc);
|
14282 |
|
|
enum machine_mode mode;
|
14283 |
|
|
|
14284 |
|
|
if (!rtl || !MEM_P (rtl))
|
14285 |
|
|
{
|
14286 |
|
|
gcc_assert (!rtl);
|
14287 |
|
|
return 0;
|
14288 |
|
|
}
|
14289 |
|
|
gcc_assert (GET_CODE (XEXP (rtl, 0)) == SYMBOL_REF);
|
14290 |
|
|
|
14291 |
|
|
/* TODO: We might get more coverage if we was actually delaying expansion
|
14292 |
|
|
of all expressions till end of compilation when constant pools are fully
|
14293 |
|
|
populated. */
|
14294 |
|
|
if (!TREE_ASM_WRITTEN (SYMBOL_REF_DECL (XEXP (rtl, 0))))
|
14295 |
|
|
{
|
14296 |
|
|
expansion_failed (loc, NULL_RTX,
|
14297 |
|
|
"CST value in contant pool but not marked.");
|
14298 |
|
|
return 0;
|
14299 |
|
|
}
|
14300 |
|
|
mode = GET_MODE (rtl);
|
14301 |
|
|
rtl = XEXP (rtl, 0);
|
14302 |
|
|
return mem_loc_descriptor (rtl, mode, VAR_INIT_STATUS_INITIALIZED);
|
14303 |
|
|
}
|
14304 |
|
|
|
14305 |
|
|
/* Return dw_loc_list representing address of addr_expr LOC
|
14306 |
|
|
by looking for innder INDIRECT_REF expression and turing it
|
14307 |
|
|
into simple arithmetics. */
|
14308 |
|
|
|
14309 |
|
|
static dw_loc_list_ref
|
14310 |
|
|
loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev)
|
14311 |
|
|
{
|
14312 |
|
|
tree obj, offset;
|
14313 |
|
|
HOST_WIDE_INT bitsize, bitpos, bytepos;
|
14314 |
|
|
enum machine_mode mode;
|
14315 |
|
|
int volatilep;
|
14316 |
|
|
int unsignedp = TYPE_UNSIGNED (TREE_TYPE (loc));
|
14317 |
|
|
dw_loc_list_ref list_ret = NULL, list_ret1 = NULL;
|
14318 |
|
|
|
14319 |
|
|
obj = get_inner_reference (TREE_OPERAND (loc, 0),
|
14320 |
|
|
&bitsize, &bitpos, &offset, &mode,
|
14321 |
|
|
&unsignedp, &volatilep, false);
|
14322 |
|
|
STRIP_NOPS (obj);
|
14323 |
|
|
if (bitpos % BITS_PER_UNIT)
|
14324 |
|
|
{
|
14325 |
|
|
expansion_failed (loc, NULL_RTX, "bitfield access");
|
14326 |
|
|
return 0;
|
14327 |
|
|
}
|
14328 |
|
|
if (!INDIRECT_REF_P (obj))
|
14329 |
|
|
{
|
14330 |
|
|
expansion_failed (obj,
|
14331 |
|
|
NULL_RTX, "no indirect ref in inner refrence");
|
14332 |
|
|
return 0;
|
14333 |
|
|
}
|
14334 |
|
|
if (!offset && !bitpos)
|
14335 |
|
|
list_ret = loc_list_from_tree (TREE_OPERAND (obj, 0), toplev ? 2 : 1);
|
14336 |
|
|
else if (toplev
|
14337 |
|
|
&& int_size_in_bytes (TREE_TYPE (loc)) <= DWARF2_ADDR_SIZE
|
14338 |
|
|
&& (dwarf_version >= 4 || !dwarf_strict))
|
14339 |
|
|
{
|
14340 |
|
|
list_ret = loc_list_from_tree (TREE_OPERAND (obj, 0), 0);
|
14341 |
|
|
if (!list_ret)
|
14342 |
|
|
return 0;
|
14343 |
|
|
if (offset)
|
14344 |
|
|
{
|
14345 |
|
|
/* Variable offset. */
|
14346 |
|
|
list_ret1 = loc_list_from_tree (offset, 0);
|
14347 |
|
|
if (list_ret1 == 0)
|
14348 |
|
|
return 0;
|
14349 |
|
|
add_loc_list (&list_ret, list_ret1);
|
14350 |
|
|
if (!list_ret)
|
14351 |
|
|
return 0;
|
14352 |
|
|
add_loc_descr_to_each (list_ret,
|
14353 |
|
|
new_loc_descr (DW_OP_plus, 0, 0));
|
14354 |
|
|
}
|
14355 |
|
|
bytepos = bitpos / BITS_PER_UNIT;
|
14356 |
|
|
if (bytepos > 0)
|
14357 |
|
|
add_loc_descr_to_each (list_ret,
|
14358 |
|
|
new_loc_descr (DW_OP_plus_uconst,
|
14359 |
|
|
bytepos, 0));
|
14360 |
|
|
else if (bytepos < 0)
|
14361 |
|
|
loc_list_plus_const (list_ret, bytepos);
|
14362 |
|
|
add_loc_descr_to_each (list_ret,
|
14363 |
|
|
new_loc_descr (DW_OP_stack_value, 0, 0));
|
14364 |
|
|
}
|
14365 |
|
|
return list_ret;
|
14366 |
|
|
}
|
14367 |
|
|
|
14368 |
|
|
|
14369 |
|
|
/* Generate Dwarf location list representing LOC.
|
14370 |
|
|
If WANT_ADDRESS is false, expression computing LOC will be computed
|
14371 |
|
|
If WANT_ADDRESS is 1, expression computing address of LOC will be returned
|
14372 |
|
|
if WANT_ADDRESS is 2, expression computing address useable in location
|
14373 |
|
|
will be returned (i.e. DW_OP_reg can be used
|
14374 |
|
|
to refer to register values). */
|
14375 |
|
|
|
14376 |
|
|
static dw_loc_list_ref
|
14377 |
|
|
loc_list_from_tree (tree loc, int want_address)
|
14378 |
|
|
{
|
14379 |
|
|
dw_loc_descr_ref ret = NULL, ret1 = NULL;
|
14380 |
|
|
dw_loc_list_ref list_ret = NULL, list_ret1 = NULL;
|
14381 |
|
|
int have_address = 0;
|
14382 |
|
|
enum dwarf_location_atom op;
|
14383 |
|
|
|
14384 |
|
|
/* ??? Most of the time we do not take proper care for sign/zero
|
14385 |
|
|
extending the values properly. Hopefully this won't be a real
|
14386 |
|
|
problem... */
|
14387 |
|
|
|
14388 |
|
|
switch (TREE_CODE (loc))
|
14389 |
|
|
{
|
14390 |
|
|
case ERROR_MARK:
|
14391 |
|
|
expansion_failed (loc, NULL_RTX, "ERROR_MARK");
|
14392 |
|
|
return 0;
|
14393 |
|
|
|
14394 |
|
|
case PLACEHOLDER_EXPR:
|
14395 |
|
|
/* This case involves extracting fields from an object to determine the
|
14396 |
|
|
position of other fields. We don't try to encode this here. The
|
14397 |
|
|
only user of this is Ada, which encodes the needed information using
|
14398 |
|
|
the names of types. */
|
14399 |
|
|
expansion_failed (loc, NULL_RTX, "PLACEHOLDER_EXPR");
|
14400 |
|
|
return 0;
|
14401 |
|
|
|
14402 |
|
|
case CALL_EXPR:
|
14403 |
|
|
expansion_failed (loc, NULL_RTX, "CALL_EXPR");
|
14404 |
|
|
/* There are no opcodes for these operations. */
|
14405 |
|
|
return 0;
|
14406 |
|
|
|
14407 |
|
|
case PREINCREMENT_EXPR:
|
14408 |
|
|
case PREDECREMENT_EXPR:
|
14409 |
|
|
case POSTINCREMENT_EXPR:
|
14410 |
|
|
case POSTDECREMENT_EXPR:
|
14411 |
|
|
expansion_failed (loc, NULL_RTX, "PRE/POST INDCREMENT/DECREMENT");
|
14412 |
|
|
/* There are no opcodes for these operations. */
|
14413 |
|
|
return 0;
|
14414 |
|
|
|
14415 |
|
|
case ADDR_EXPR:
|
14416 |
|
|
/* If we already want an address, see if there is INDIRECT_REF inside
|
14417 |
|
|
e.g. for &this->field. */
|
14418 |
|
|
if (want_address)
|
14419 |
|
|
{
|
14420 |
|
|
list_ret = loc_list_for_address_of_addr_expr_of_indirect_ref
|
14421 |
|
|
(loc, want_address == 2);
|
14422 |
|
|
if (list_ret)
|
14423 |
|
|
have_address = 1;
|
14424 |
|
|
else if (decl_address_ip_invariant_p (TREE_OPERAND (loc, 0))
|
14425 |
|
|
&& (ret = cst_pool_loc_descr (loc)))
|
14426 |
|
|
have_address = 1;
|
14427 |
|
|
}
|
14428 |
|
|
/* Otherwise, process the argument and look for the address. */
|
14429 |
|
|
if (!list_ret && !ret)
|
14430 |
|
|
list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 1);
|
14431 |
|
|
else
|
14432 |
|
|
{
|
14433 |
|
|
if (want_address)
|
14434 |
|
|
expansion_failed (loc, NULL_RTX, "need address of ADDR_EXPR");
|
14435 |
|
|
return NULL;
|
14436 |
|
|
}
|
14437 |
|
|
break;
|
14438 |
|
|
|
14439 |
|
|
case VAR_DECL:
|
14440 |
|
|
if (DECL_THREAD_LOCAL_P (loc))
|
14441 |
|
|
{
|
14442 |
|
|
rtx rtl;
|
14443 |
|
|
enum dwarf_location_atom first_op;
|
14444 |
|
|
enum dwarf_location_atom second_op;
|
14445 |
|
|
bool dtprel = false;
|
14446 |
|
|
|
14447 |
|
|
if (targetm.have_tls)
|
14448 |
|
|
{
|
14449 |
|
|
/* If this is not defined, we have no way to emit the
|
14450 |
|
|
data. */
|
14451 |
|
|
if (!targetm.asm_out.output_dwarf_dtprel)
|
14452 |
|
|
return 0;
|
14453 |
|
|
|
14454 |
|
|
/* The way DW_OP_GNU_push_tls_address is specified, we
|
14455 |
|
|
can only look up addresses of objects in the current
|
14456 |
|
|
module. */
|
14457 |
|
|
if (DECL_EXTERNAL (loc) && !targetm.binds_local_p (loc))
|
14458 |
|
|
return 0;
|
14459 |
|
|
first_op = DW_OP_addr;
|
14460 |
|
|
dtprel = true;
|
14461 |
|
|
second_op = DW_OP_GNU_push_tls_address;
|
14462 |
|
|
}
|
14463 |
|
|
else
|
14464 |
|
|
{
|
14465 |
|
|
if (!targetm.emutls.debug_form_tls_address
|
14466 |
|
|
|| !(dwarf_version >= 3 || !dwarf_strict))
|
14467 |
|
|
return 0;
|
14468 |
|
|
loc = emutls_decl (loc);
|
14469 |
|
|
first_op = DW_OP_addr;
|
14470 |
|
|
second_op = DW_OP_form_tls_address;
|
14471 |
|
|
}
|
14472 |
|
|
|
14473 |
|
|
rtl = rtl_for_decl_location (loc);
|
14474 |
|
|
if (rtl == NULL_RTX)
|
14475 |
|
|
return 0;
|
14476 |
|
|
|
14477 |
|
|
if (!MEM_P (rtl))
|
14478 |
|
|
return 0;
|
14479 |
|
|
rtl = XEXP (rtl, 0);
|
14480 |
|
|
if (! CONSTANT_P (rtl))
|
14481 |
|
|
return 0;
|
14482 |
|
|
|
14483 |
|
|
ret = new_loc_descr (first_op, 0, 0);
|
14484 |
|
|
ret->dw_loc_oprnd1.val_class = dw_val_class_addr;
|
14485 |
|
|
ret->dw_loc_oprnd1.v.val_addr = rtl;
|
14486 |
|
|
ret->dtprel = dtprel;
|
14487 |
|
|
|
14488 |
|
|
ret1 = new_loc_descr (second_op, 0, 0);
|
14489 |
|
|
add_loc_descr (&ret, ret1);
|
14490 |
|
|
|
14491 |
|
|
have_address = 1;
|
14492 |
|
|
break;
|
14493 |
|
|
}
|
14494 |
|
|
/* FALLTHRU */
|
14495 |
|
|
|
14496 |
|
|
case PARM_DECL:
|
14497 |
|
|
if (DECL_HAS_VALUE_EXPR_P (loc))
|
14498 |
|
|
return loc_list_from_tree (DECL_VALUE_EXPR (loc),
|
14499 |
|
|
want_address);
|
14500 |
|
|
/* FALLTHRU */
|
14501 |
|
|
|
14502 |
|
|
case RESULT_DECL:
|
14503 |
|
|
case FUNCTION_DECL:
|
14504 |
|
|
{
|
14505 |
|
|
rtx rtl;
|
14506 |
|
|
var_loc_list *loc_list = lookup_decl_loc (loc);
|
14507 |
|
|
|
14508 |
|
|
if (loc_list && loc_list->first)
|
14509 |
|
|
{
|
14510 |
|
|
list_ret = dw_loc_list (loc_list, loc, want_address);
|
14511 |
|
|
have_address = want_address != 0;
|
14512 |
|
|
break;
|
14513 |
|
|
}
|
14514 |
|
|
rtl = rtl_for_decl_location (loc);
|
14515 |
|
|
if (rtl == NULL_RTX)
|
14516 |
|
|
{
|
14517 |
|
|
expansion_failed (loc, NULL_RTX, "DECL has no RTL");
|
14518 |
|
|
return 0;
|
14519 |
|
|
}
|
14520 |
|
|
else if (CONST_INT_P (rtl))
|
14521 |
|
|
{
|
14522 |
|
|
HOST_WIDE_INT val = INTVAL (rtl);
|
14523 |
|
|
if (TYPE_UNSIGNED (TREE_TYPE (loc)))
|
14524 |
|
|
val &= GET_MODE_MASK (DECL_MODE (loc));
|
14525 |
|
|
ret = int_loc_descriptor (val);
|
14526 |
|
|
}
|
14527 |
|
|
else if (GET_CODE (rtl) == CONST_STRING)
|
14528 |
|
|
{
|
14529 |
|
|
expansion_failed (loc, NULL_RTX, "CONST_STRING");
|
14530 |
|
|
return 0;
|
14531 |
|
|
}
|
14532 |
|
|
else if (CONSTANT_P (rtl) && const_ok_for_output (rtl))
|
14533 |
|
|
{
|
14534 |
|
|
ret = new_loc_descr (DW_OP_addr, 0, 0);
|
14535 |
|
|
ret->dw_loc_oprnd1.val_class = dw_val_class_addr;
|
14536 |
|
|
ret->dw_loc_oprnd1.v.val_addr = rtl;
|
14537 |
|
|
}
|
14538 |
|
|
else
|
14539 |
|
|
{
|
14540 |
|
|
enum machine_mode mode;
|
14541 |
|
|
|
14542 |
|
|
/* Certain constructs can only be represented at top-level. */
|
14543 |
|
|
if (want_address == 2)
|
14544 |
|
|
{
|
14545 |
|
|
ret = loc_descriptor (rtl, VOIDmode,
|
14546 |
|
|
VAR_INIT_STATUS_INITIALIZED);
|
14547 |
|
|
have_address = 1;
|
14548 |
|
|
}
|
14549 |
|
|
else
|
14550 |
|
|
{
|
14551 |
|
|
mode = GET_MODE (rtl);
|
14552 |
|
|
if (MEM_P (rtl))
|
14553 |
|
|
{
|
14554 |
|
|
rtl = XEXP (rtl, 0);
|
14555 |
|
|
have_address = 1;
|
14556 |
|
|
}
|
14557 |
|
|
ret = mem_loc_descriptor (rtl, mode, VAR_INIT_STATUS_INITIALIZED);
|
14558 |
|
|
}
|
14559 |
|
|
if (!ret)
|
14560 |
|
|
expansion_failed (loc, rtl,
|
14561 |
|
|
"failed to produce loc descriptor for rtl");
|
14562 |
|
|
}
|
14563 |
|
|
}
|
14564 |
|
|
break;
|
14565 |
|
|
|
14566 |
|
|
case INDIRECT_REF:
|
14567 |
|
|
case ALIGN_INDIRECT_REF:
|
14568 |
|
|
case MISALIGNED_INDIRECT_REF:
|
14569 |
|
|
list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
|
14570 |
|
|
have_address = 1;
|
14571 |
|
|
break;
|
14572 |
|
|
|
14573 |
|
|
case COMPOUND_EXPR:
|
14574 |
|
|
return loc_list_from_tree (TREE_OPERAND (loc, 1), want_address);
|
14575 |
|
|
|
14576 |
|
|
CASE_CONVERT:
|
14577 |
|
|
case VIEW_CONVERT_EXPR:
|
14578 |
|
|
case SAVE_EXPR:
|
14579 |
|
|
case MODIFY_EXPR:
|
14580 |
|
|
return loc_list_from_tree (TREE_OPERAND (loc, 0), want_address);
|
14581 |
|
|
|
14582 |
|
|
case COMPONENT_REF:
|
14583 |
|
|
case BIT_FIELD_REF:
|
14584 |
|
|
case ARRAY_REF:
|
14585 |
|
|
case ARRAY_RANGE_REF:
|
14586 |
|
|
case REALPART_EXPR:
|
14587 |
|
|
case IMAGPART_EXPR:
|
14588 |
|
|
{
|
14589 |
|
|
tree obj, offset;
|
14590 |
|
|
HOST_WIDE_INT bitsize, bitpos, bytepos;
|
14591 |
|
|
enum machine_mode mode;
|
14592 |
|
|
int volatilep;
|
14593 |
|
|
int unsignedp = TYPE_UNSIGNED (TREE_TYPE (loc));
|
14594 |
|
|
|
14595 |
|
|
obj = get_inner_reference (loc, &bitsize, &bitpos, &offset, &mode,
|
14596 |
|
|
&unsignedp, &volatilep, false);
|
14597 |
|
|
|
14598 |
|
|
gcc_assert (obj != loc);
|
14599 |
|
|
|
14600 |
|
|
list_ret = loc_list_from_tree (obj,
|
14601 |
|
|
want_address == 2
|
14602 |
|
|
&& !bitpos && !offset ? 2 : 1);
|
14603 |
|
|
/* TODO: We can extract value of the small expression via shifting even
|
14604 |
|
|
for nonzero bitpos. */
|
14605 |
|
|
if (list_ret == 0)
|
14606 |
|
|
return 0;
|
14607 |
|
|
if (bitpos % BITS_PER_UNIT != 0 || bitsize % BITS_PER_UNIT != 0)
|
14608 |
|
|
{
|
14609 |
|
|
expansion_failed (loc, NULL_RTX,
|
14610 |
|
|
"bitfield access");
|
14611 |
|
|
return 0;
|
14612 |
|
|
}
|
14613 |
|
|
|
14614 |
|
|
if (offset != NULL_TREE)
|
14615 |
|
|
{
|
14616 |
|
|
/* Variable offset. */
|
14617 |
|
|
list_ret1 = loc_list_from_tree (offset, 0);
|
14618 |
|
|
if (list_ret1 == 0)
|
14619 |
|
|
return 0;
|
14620 |
|
|
add_loc_list (&list_ret, list_ret1);
|
14621 |
|
|
if (!list_ret)
|
14622 |
|
|
return 0;
|
14623 |
|
|
add_loc_descr_to_each (list_ret, new_loc_descr (DW_OP_plus, 0, 0));
|
14624 |
|
|
}
|
14625 |
|
|
|
14626 |
|
|
bytepos = bitpos / BITS_PER_UNIT;
|
14627 |
|
|
if (bytepos > 0)
|
14628 |
|
|
add_loc_descr_to_each (list_ret, new_loc_descr (DW_OP_plus_uconst, bytepos, 0));
|
14629 |
|
|
else if (bytepos < 0)
|
14630 |
|
|
loc_list_plus_const (list_ret, bytepos);
|
14631 |
|
|
|
14632 |
|
|
have_address = 1;
|
14633 |
|
|
break;
|
14634 |
|
|
}
|
14635 |
|
|
|
14636 |
|
|
case INTEGER_CST:
|
14637 |
|
|
if ((want_address || !host_integerp (loc, 0))
|
14638 |
|
|
&& (ret = cst_pool_loc_descr (loc)))
|
14639 |
|
|
have_address = 1;
|
14640 |
|
|
else if (want_address == 2
|
14641 |
|
|
&& host_integerp (loc, 0)
|
14642 |
|
|
&& (ret = address_of_int_loc_descriptor
|
14643 |
|
|
(int_size_in_bytes (TREE_TYPE (loc)),
|
14644 |
|
|
tree_low_cst (loc, 0))))
|
14645 |
|
|
have_address = 1;
|
14646 |
|
|
else if (host_integerp (loc, 0))
|
14647 |
|
|
ret = int_loc_descriptor (tree_low_cst (loc, 0));
|
14648 |
|
|
else
|
14649 |
|
|
{
|
14650 |
|
|
expansion_failed (loc, NULL_RTX,
|
14651 |
|
|
"Integer operand is not host integer");
|
14652 |
|
|
return 0;
|
14653 |
|
|
}
|
14654 |
|
|
break;
|
14655 |
|
|
|
14656 |
|
|
case CONSTRUCTOR:
|
14657 |
|
|
case REAL_CST:
|
14658 |
|
|
case STRING_CST:
|
14659 |
|
|
case COMPLEX_CST:
|
14660 |
|
|
if ((ret = cst_pool_loc_descr (loc)))
|
14661 |
|
|
have_address = 1;
|
14662 |
|
|
else
|
14663 |
|
|
/* We can construct small constants here using int_loc_descriptor. */
|
14664 |
|
|
expansion_failed (loc, NULL_RTX,
|
14665 |
|
|
"constructor or constant not in constant pool");
|
14666 |
|
|
break;
|
14667 |
|
|
|
14668 |
|
|
case TRUTH_AND_EXPR:
|
14669 |
|
|
case TRUTH_ANDIF_EXPR:
|
14670 |
|
|
case BIT_AND_EXPR:
|
14671 |
|
|
op = DW_OP_and;
|
14672 |
|
|
goto do_binop;
|
14673 |
|
|
|
14674 |
|
|
case TRUTH_XOR_EXPR:
|
14675 |
|
|
case BIT_XOR_EXPR:
|
14676 |
|
|
op = DW_OP_xor;
|
14677 |
|
|
goto do_binop;
|
14678 |
|
|
|
14679 |
|
|
case TRUTH_OR_EXPR:
|
14680 |
|
|
case TRUTH_ORIF_EXPR:
|
14681 |
|
|
case BIT_IOR_EXPR:
|
14682 |
|
|
op = DW_OP_or;
|
14683 |
|
|
goto do_binop;
|
14684 |
|
|
|
14685 |
|
|
case FLOOR_DIV_EXPR:
|
14686 |
|
|
case CEIL_DIV_EXPR:
|
14687 |
|
|
case ROUND_DIV_EXPR:
|
14688 |
|
|
case TRUNC_DIV_EXPR:
|
14689 |
|
|
if (TYPE_UNSIGNED (TREE_TYPE (loc)))
|
14690 |
|
|
return 0;
|
14691 |
|
|
op = DW_OP_div;
|
14692 |
|
|
goto do_binop;
|
14693 |
|
|
|
14694 |
|
|
case MINUS_EXPR:
|
14695 |
|
|
op = DW_OP_minus;
|
14696 |
|
|
goto do_binop;
|
14697 |
|
|
|
14698 |
|
|
case FLOOR_MOD_EXPR:
|
14699 |
|
|
case CEIL_MOD_EXPR:
|
14700 |
|
|
case ROUND_MOD_EXPR:
|
14701 |
|
|
case TRUNC_MOD_EXPR:
|
14702 |
|
|
if (TYPE_UNSIGNED (TREE_TYPE (loc)))
|
14703 |
|
|
{
|
14704 |
|
|
op = DW_OP_mod;
|
14705 |
|
|
goto do_binop;
|
14706 |
|
|
}
|
14707 |
|
|
list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
|
14708 |
|
|
list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0);
|
14709 |
|
|
if (list_ret == 0 || list_ret1 == 0)
|
14710 |
|
|
return 0;
|
14711 |
|
|
|
14712 |
|
|
add_loc_list (&list_ret, list_ret1);
|
14713 |
|
|
if (list_ret == 0)
|
14714 |
|
|
return 0;
|
14715 |
|
|
add_loc_descr_to_each (list_ret, new_loc_descr (DW_OP_over, 0, 0));
|
14716 |
|
|
add_loc_descr_to_each (list_ret, new_loc_descr (DW_OP_over, 0, 0));
|
14717 |
|
|
add_loc_descr_to_each (list_ret, new_loc_descr (DW_OP_div, 0, 0));
|
14718 |
|
|
add_loc_descr_to_each (list_ret, new_loc_descr (DW_OP_mul, 0, 0));
|
14719 |
|
|
add_loc_descr_to_each (list_ret, new_loc_descr (DW_OP_minus, 0, 0));
|
14720 |
|
|
break;
|
14721 |
|
|
|
14722 |
|
|
case MULT_EXPR:
|
14723 |
|
|
op = DW_OP_mul;
|
14724 |
|
|
goto do_binop;
|
14725 |
|
|
|
14726 |
|
|
case LSHIFT_EXPR:
|
14727 |
|
|
op = DW_OP_shl;
|
14728 |
|
|
goto do_binop;
|
14729 |
|
|
|
14730 |
|
|
case RSHIFT_EXPR:
|
14731 |
|
|
op = (TYPE_UNSIGNED (TREE_TYPE (loc)) ? DW_OP_shr : DW_OP_shra);
|
14732 |
|
|
goto do_binop;
|
14733 |
|
|
|
14734 |
|
|
case POINTER_PLUS_EXPR:
|
14735 |
|
|
case PLUS_EXPR:
|
14736 |
|
|
if (TREE_CODE (TREE_OPERAND (loc, 1)) == INTEGER_CST
|
14737 |
|
|
&& host_integerp (TREE_OPERAND (loc, 1), 0))
|
14738 |
|
|
{
|
14739 |
|
|
list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
|
14740 |
|
|
if (list_ret == 0)
|
14741 |
|
|
return 0;
|
14742 |
|
|
|
14743 |
|
|
loc_list_plus_const (list_ret, tree_low_cst (TREE_OPERAND (loc, 1), 0));
|
14744 |
|
|
break;
|
14745 |
|
|
}
|
14746 |
|
|
|
14747 |
|
|
op = DW_OP_plus;
|
14748 |
|
|
goto do_binop;
|
14749 |
|
|
|
14750 |
|
|
case LE_EXPR:
|
14751 |
|
|
if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
|
14752 |
|
|
return 0;
|
14753 |
|
|
|
14754 |
|
|
op = DW_OP_le;
|
14755 |
|
|
goto do_binop;
|
14756 |
|
|
|
14757 |
|
|
case GE_EXPR:
|
14758 |
|
|
if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
|
14759 |
|
|
return 0;
|
14760 |
|
|
|
14761 |
|
|
op = DW_OP_ge;
|
14762 |
|
|
goto do_binop;
|
14763 |
|
|
|
14764 |
|
|
case LT_EXPR:
|
14765 |
|
|
if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
|
14766 |
|
|
return 0;
|
14767 |
|
|
|
14768 |
|
|
op = DW_OP_lt;
|
14769 |
|
|
goto do_binop;
|
14770 |
|
|
|
14771 |
|
|
case GT_EXPR:
|
14772 |
|
|
if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0))))
|
14773 |
|
|
return 0;
|
14774 |
|
|
|
14775 |
|
|
op = DW_OP_gt;
|
14776 |
|
|
goto do_binop;
|
14777 |
|
|
|
14778 |
|
|
case EQ_EXPR:
|
14779 |
|
|
op = DW_OP_eq;
|
14780 |
|
|
goto do_binop;
|
14781 |
|
|
|
14782 |
|
|
case NE_EXPR:
|
14783 |
|
|
op = DW_OP_ne;
|
14784 |
|
|
goto do_binop;
|
14785 |
|
|
|
14786 |
|
|
do_binop:
|
14787 |
|
|
list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
|
14788 |
|
|
list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0);
|
14789 |
|
|
if (list_ret == 0 || list_ret1 == 0)
|
14790 |
|
|
return 0;
|
14791 |
|
|
|
14792 |
|
|
add_loc_list (&list_ret, list_ret1);
|
14793 |
|
|
if (list_ret == 0)
|
14794 |
|
|
return 0;
|
14795 |
|
|
add_loc_descr_to_each (list_ret, new_loc_descr (op, 0, 0));
|
14796 |
|
|
break;
|
14797 |
|
|
|
14798 |
|
|
case TRUTH_NOT_EXPR:
|
14799 |
|
|
case BIT_NOT_EXPR:
|
14800 |
|
|
op = DW_OP_not;
|
14801 |
|
|
goto do_unop;
|
14802 |
|
|
|
14803 |
|
|
case ABS_EXPR:
|
14804 |
|
|
op = DW_OP_abs;
|
14805 |
|
|
goto do_unop;
|
14806 |
|
|
|
14807 |
|
|
case NEGATE_EXPR:
|
14808 |
|
|
op = DW_OP_neg;
|
14809 |
|
|
goto do_unop;
|
14810 |
|
|
|
14811 |
|
|
do_unop:
|
14812 |
|
|
list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
|
14813 |
|
|
if (list_ret == 0)
|
14814 |
|
|
return 0;
|
14815 |
|
|
|
14816 |
|
|
add_loc_descr_to_each (list_ret, new_loc_descr (op, 0, 0));
|
14817 |
|
|
break;
|
14818 |
|
|
|
14819 |
|
|
case MIN_EXPR:
|
14820 |
|
|
case MAX_EXPR:
|
14821 |
|
|
{
|
14822 |
|
|
const enum tree_code code =
|
14823 |
|
|
TREE_CODE (loc) == MIN_EXPR ? GT_EXPR : LT_EXPR;
|
14824 |
|
|
|
14825 |
|
|
loc = build3 (COND_EXPR, TREE_TYPE (loc),
|
14826 |
|
|
build2 (code, integer_type_node,
|
14827 |
|
|
TREE_OPERAND (loc, 0), TREE_OPERAND (loc, 1)),
|
14828 |
|
|
TREE_OPERAND (loc, 1), TREE_OPERAND (loc, 0));
|
14829 |
|
|
}
|
14830 |
|
|
|
14831 |
|
|
/* ... fall through ... */
|
14832 |
|
|
|
14833 |
|
|
case COND_EXPR:
|
14834 |
|
|
{
|
14835 |
|
|
dw_loc_descr_ref lhs
|
14836 |
|
|
= loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0);
|
14837 |
|
|
dw_loc_list_ref rhs
|
14838 |
|
|
= loc_list_from_tree (TREE_OPERAND (loc, 2), 0);
|
14839 |
|
|
dw_loc_descr_ref bra_node, jump_node, tmp;
|
14840 |
|
|
|
14841 |
|
|
list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
|
14842 |
|
|
if (list_ret == 0 || lhs == 0 || rhs == 0)
|
14843 |
|
|
return 0;
|
14844 |
|
|
|
14845 |
|
|
bra_node = new_loc_descr (DW_OP_bra, 0, 0);
|
14846 |
|
|
add_loc_descr_to_each (list_ret, bra_node);
|
14847 |
|
|
|
14848 |
|
|
add_loc_list (&list_ret, rhs);
|
14849 |
|
|
jump_node = new_loc_descr (DW_OP_skip, 0, 0);
|
14850 |
|
|
add_loc_descr_to_each (list_ret, jump_node);
|
14851 |
|
|
|
14852 |
|
|
add_loc_descr_to_each (list_ret, lhs);
|
14853 |
|
|
bra_node->dw_loc_oprnd1.val_class = dw_val_class_loc;
|
14854 |
|
|
bra_node->dw_loc_oprnd1.v.val_loc = lhs;
|
14855 |
|
|
|
14856 |
|
|
/* ??? Need a node to point the skip at. Use a nop. */
|
14857 |
|
|
tmp = new_loc_descr (DW_OP_nop, 0, 0);
|
14858 |
|
|
add_loc_descr_to_each (list_ret, tmp);
|
14859 |
|
|
jump_node->dw_loc_oprnd1.val_class = dw_val_class_loc;
|
14860 |
|
|
jump_node->dw_loc_oprnd1.v.val_loc = tmp;
|
14861 |
|
|
}
|
14862 |
|
|
break;
|
14863 |
|
|
|
14864 |
|
|
case FIX_TRUNC_EXPR:
|
14865 |
|
|
return 0;
|
14866 |
|
|
|
14867 |
|
|
default:
|
14868 |
|
|
/* Leave front-end specific codes as simply unknown. This comes
|
14869 |
|
|
up, for instance, with the C STMT_EXPR. */
|
14870 |
|
|
if ((unsigned int) TREE_CODE (loc)
|
14871 |
|
|
>= (unsigned int) LAST_AND_UNUSED_TREE_CODE)
|
14872 |
|
|
{
|
14873 |
|
|
expansion_failed (loc, NULL_RTX,
|
14874 |
|
|
"language specific tree node");
|
14875 |
|
|
return 0;
|
14876 |
|
|
}
|
14877 |
|
|
|
14878 |
|
|
#ifdef ENABLE_CHECKING
|
14879 |
|
|
/* Otherwise this is a generic code; we should just lists all of
|
14880 |
|
|
these explicitly. We forgot one. */
|
14881 |
|
|
gcc_unreachable ();
|
14882 |
|
|
#else
|
14883 |
|
|
/* In a release build, we want to degrade gracefully: better to
|
14884 |
|
|
generate incomplete debugging information than to crash. */
|
14885 |
|
|
return NULL;
|
14886 |
|
|
#endif
|
14887 |
|
|
}
|
14888 |
|
|
|
14889 |
|
|
if (!ret && !list_ret)
|
14890 |
|
|
return 0;
|
14891 |
|
|
|
14892 |
|
|
if (want_address == 2 && !have_address
|
14893 |
|
|
&& (dwarf_version >= 4 || !dwarf_strict))
|
14894 |
|
|
{
|
14895 |
|
|
if (int_size_in_bytes (TREE_TYPE (loc)) > DWARF2_ADDR_SIZE)
|
14896 |
|
|
{
|
14897 |
|
|
expansion_failed (loc, NULL_RTX,
|
14898 |
|
|
"DWARF address size mismatch");
|
14899 |
|
|
return 0;
|
14900 |
|
|
}
|
14901 |
|
|
if (ret)
|
14902 |
|
|
add_loc_descr (&ret, new_loc_descr (DW_OP_stack_value, 0, 0));
|
14903 |
|
|
else
|
14904 |
|
|
add_loc_descr_to_each (list_ret,
|
14905 |
|
|
new_loc_descr (DW_OP_stack_value, 0, 0));
|
14906 |
|
|
have_address = 1;
|
14907 |
|
|
}
|
14908 |
|
|
/* Show if we can't fill the request for an address. */
|
14909 |
|
|
if (want_address && !have_address)
|
14910 |
|
|
{
|
14911 |
|
|
expansion_failed (loc, NULL_RTX,
|
14912 |
|
|
"Want address and only have value");
|
14913 |
|
|
return 0;
|
14914 |
|
|
}
|
14915 |
|
|
|
14916 |
|
|
gcc_assert (!ret || !list_ret);
|
14917 |
|
|
|
14918 |
|
|
/* If we've got an address and don't want one, dereference. */
|
14919 |
|
|
if (!want_address && have_address)
|
14920 |
|
|
{
|
14921 |
|
|
HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (loc));
|
14922 |
|
|
|
14923 |
|
|
if (size > DWARF2_ADDR_SIZE || size == -1)
|
14924 |
|
|
{
|
14925 |
|
|
expansion_failed (loc, NULL_RTX,
|
14926 |
|
|
"DWARF address size mismatch");
|
14927 |
|
|
return 0;
|
14928 |
|
|
}
|
14929 |
|
|
else if (size == DWARF2_ADDR_SIZE)
|
14930 |
|
|
op = DW_OP_deref;
|
14931 |
|
|
else
|
14932 |
|
|
op = DW_OP_deref_size;
|
14933 |
|
|
|
14934 |
|
|
if (ret)
|
14935 |
|
|
add_loc_descr (&ret, new_loc_descr (op, size, 0));
|
14936 |
|
|
else
|
14937 |
|
|
add_loc_descr_to_each (list_ret, new_loc_descr (op, size, 0));
|
14938 |
|
|
}
|
14939 |
|
|
if (ret)
|
14940 |
|
|
list_ret = new_loc_list (ret, NULL, NULL, NULL);
|
14941 |
|
|
|
14942 |
|
|
return list_ret;
|
14943 |
|
|
}
|
14944 |
|
|
|
14945 |
|
|
/* Same as above but return only single location expression. */
|
14946 |
|
|
static dw_loc_descr_ref
|
14947 |
|
|
loc_descriptor_from_tree (tree loc, int want_address)
|
14948 |
|
|
{
|
14949 |
|
|
dw_loc_list_ref ret = loc_list_from_tree (loc, want_address);
|
14950 |
|
|
if (!ret)
|
14951 |
|
|
return NULL;
|
14952 |
|
|
if (ret->dw_loc_next)
|
14953 |
|
|
{
|
14954 |
|
|
expansion_failed (loc, NULL_RTX,
|
14955 |
|
|
"Location list where only loc descriptor needed");
|
14956 |
|
|
return NULL;
|
14957 |
|
|
}
|
14958 |
|
|
return ret->expr;
|
14959 |
|
|
}
|
14960 |
|
|
|
14961 |
|
|
/* Given a value, round it up to the lowest multiple of `boundary'
|
14962 |
|
|
which is not less than the value itself. */
|
14963 |
|
|
|
14964 |
|
|
static inline HOST_WIDE_INT
|
14965 |
|
|
ceiling (HOST_WIDE_INT value, unsigned int boundary)
|
14966 |
|
|
{
|
14967 |
|
|
return (((value + boundary - 1) / boundary) * boundary);
|
14968 |
|
|
}
|
14969 |
|
|
|
14970 |
|
|
/* Given a pointer to what is assumed to be a FIELD_DECL node, return a
|
14971 |
|
|
pointer to the declared type for the relevant field variable, or return
|
14972 |
|
|
`integer_type_node' if the given node turns out to be an
|
14973 |
|
|
ERROR_MARK node. */
|
14974 |
|
|
|
14975 |
|
|
static inline tree
|
14976 |
|
|
field_type (const_tree decl)
|
14977 |
|
|
{
|
14978 |
|
|
tree type;
|
14979 |
|
|
|
14980 |
|
|
if (TREE_CODE (decl) == ERROR_MARK)
|
14981 |
|
|
return integer_type_node;
|
14982 |
|
|
|
14983 |
|
|
type = DECL_BIT_FIELD_TYPE (decl);
|
14984 |
|
|
if (type == NULL_TREE)
|
14985 |
|
|
type = TREE_TYPE (decl);
|
14986 |
|
|
|
14987 |
|
|
return type;
|
14988 |
|
|
}
|
14989 |
|
|
|
14990 |
|
|
/* Given a pointer to a tree node, return the alignment in bits for
|
14991 |
|
|
it, or else return BITS_PER_WORD if the node actually turns out to
|
14992 |
|
|
be an ERROR_MARK node. */
|
14993 |
|
|
|
14994 |
|
|
static inline unsigned
|
14995 |
|
|
simple_type_align_in_bits (const_tree type)
|
14996 |
|
|
{
|
14997 |
|
|
return (TREE_CODE (type) != ERROR_MARK) ? TYPE_ALIGN (type) : BITS_PER_WORD;
|
14998 |
|
|
}
|
14999 |
|
|
|
15000 |
|
|
static inline unsigned
|
15001 |
|
|
simple_decl_align_in_bits (const_tree decl)
|
15002 |
|
|
{
|
15003 |
|
|
return (TREE_CODE (decl) != ERROR_MARK) ? DECL_ALIGN (decl) : BITS_PER_WORD;
|
15004 |
|
|
}
|
15005 |
|
|
|
15006 |
|
|
/* Return the result of rounding T up to ALIGN. */
|
15007 |
|
|
|
15008 |
|
|
static inline HOST_WIDE_INT
|
15009 |
|
|
round_up_to_align (HOST_WIDE_INT t, unsigned int align)
|
15010 |
|
|
{
|
15011 |
|
|
/* We must be careful if T is negative because HOST_WIDE_INT can be
|
15012 |
|
|
either "above" or "below" unsigned int as per the C promotion
|
15013 |
|
|
rules, depending on the host, thus making the signedness of the
|
15014 |
|
|
direct multiplication and division unpredictable. */
|
15015 |
|
|
unsigned HOST_WIDE_INT u = (unsigned HOST_WIDE_INT) t;
|
15016 |
|
|
|
15017 |
|
|
u += align - 1;
|
15018 |
|
|
u /= align;
|
15019 |
|
|
u *= align;
|
15020 |
|
|
|
15021 |
|
|
return (HOST_WIDE_INT) u;
|
15022 |
|
|
}
|
15023 |
|
|
|
15024 |
|
|
/* Given a pointer to a FIELD_DECL, compute and return the byte offset of the
|
15025 |
|
|
lowest addressed byte of the "containing object" for the given FIELD_DECL,
|
15026 |
|
|
or return 0 if we are unable to determine what that offset is, either
|
15027 |
|
|
because the argument turns out to be a pointer to an ERROR_MARK node, or
|
15028 |
|
|
because the offset is actually variable. (We can't handle the latter case
|
15029 |
|
|
just yet). */
|
15030 |
|
|
|
15031 |
|
|
static HOST_WIDE_INT
|
15032 |
|
|
field_byte_offset (const_tree decl)
|
15033 |
|
|
{
|
15034 |
|
|
HOST_WIDE_INT object_offset_in_bits;
|
15035 |
|
|
HOST_WIDE_INT bitpos_int;
|
15036 |
|
|
|
15037 |
|
|
if (TREE_CODE (decl) == ERROR_MARK)
|
15038 |
|
|
return 0;
|
15039 |
|
|
|
15040 |
|
|
gcc_assert (TREE_CODE (decl) == FIELD_DECL);
|
15041 |
|
|
|
15042 |
|
|
/* We cannot yet cope with fields whose positions are variable, so
|
15043 |
|
|
for now, when we see such things, we simply return 0. Someday, we may
|
15044 |
|
|
be able to handle such cases, but it will be damn difficult. */
|
15045 |
|
|
if (! host_integerp (bit_position (decl), 0))
|
15046 |
|
|
return 0;
|
15047 |
|
|
|
15048 |
|
|
bitpos_int = int_bit_position (decl);
|
15049 |
|
|
|
15050 |
|
|
#ifdef PCC_BITFIELD_TYPE_MATTERS
|
15051 |
|
|
if (PCC_BITFIELD_TYPE_MATTERS)
|
15052 |
|
|
{
|
15053 |
|
|
tree type;
|
15054 |
|
|
tree field_size_tree;
|
15055 |
|
|
HOST_WIDE_INT deepest_bitpos;
|
15056 |
|
|
unsigned HOST_WIDE_INT field_size_in_bits;
|
15057 |
|
|
unsigned int type_align_in_bits;
|
15058 |
|
|
unsigned int decl_align_in_bits;
|
15059 |
|
|
unsigned HOST_WIDE_INT type_size_in_bits;
|
15060 |
|
|
|
15061 |
|
|
type = field_type (decl);
|
15062 |
|
|
type_size_in_bits = simple_type_size_in_bits (type);
|
15063 |
|
|
type_align_in_bits = simple_type_align_in_bits (type);
|
15064 |
|
|
|
15065 |
|
|
field_size_tree = DECL_SIZE (decl);
|
15066 |
|
|
|
15067 |
|
|
/* The size could be unspecified if there was an error, or for
|
15068 |
|
|
a flexible array member. */
|
15069 |
|
|
if (!field_size_tree)
|
15070 |
|
|
field_size_tree = bitsize_zero_node;
|
15071 |
|
|
|
15072 |
|
|
/* If the size of the field is not constant, use the type size. */
|
15073 |
|
|
if (host_integerp (field_size_tree, 1))
|
15074 |
|
|
field_size_in_bits = tree_low_cst (field_size_tree, 1);
|
15075 |
|
|
else
|
15076 |
|
|
field_size_in_bits = type_size_in_bits;
|
15077 |
|
|
|
15078 |
|
|
decl_align_in_bits = simple_decl_align_in_bits (decl);
|
15079 |
|
|
|
15080 |
|
|
/* The GCC front-end doesn't make any attempt to keep track of the
|
15081 |
|
|
starting bit offset (relative to the start of the containing
|
15082 |
|
|
structure type) of the hypothetical "containing object" for a
|
15083 |
|
|
bit-field. Thus, when computing the byte offset value for the
|
15084 |
|
|
start of the "containing object" of a bit-field, we must deduce
|
15085 |
|
|
this information on our own. This can be rather tricky to do in
|
15086 |
|
|
some cases. For example, handling the following structure type
|
15087 |
|
|
definition when compiling for an i386/i486 target (which only
|
15088 |
|
|
aligns long long's to 32-bit boundaries) can be very tricky:
|
15089 |
|
|
|
15090 |
|
|
struct S { int field1; long long field2:31; };
|
15091 |
|
|
|
15092 |
|
|
Fortunately, there is a simple rule-of-thumb which can be used
|
15093 |
|
|
in such cases. When compiling for an i386/i486, GCC will
|
15094 |
|
|
allocate 8 bytes for the structure shown above. It decides to
|
15095 |
|
|
do this based upon one simple rule for bit-field allocation.
|
15096 |
|
|
GCC allocates each "containing object" for each bit-field at
|
15097 |
|
|
the first (i.e. lowest addressed) legitimate alignment boundary
|
15098 |
|
|
(based upon the required minimum alignment for the declared
|
15099 |
|
|
type of the field) which it can possibly use, subject to the
|
15100 |
|
|
condition that there is still enough available space remaining
|
15101 |
|
|
in the containing object (when allocated at the selected point)
|
15102 |
|
|
to fully accommodate all of the bits of the bit-field itself.
|
15103 |
|
|
|
15104 |
|
|
This simple rule makes it obvious why GCC allocates 8 bytes for
|
15105 |
|
|
each object of the structure type shown above. When looking
|
15106 |
|
|
for a place to allocate the "containing object" for `field2',
|
15107 |
|
|
the compiler simply tries to allocate a 64-bit "containing
|
15108 |
|
|
object" at each successive 32-bit boundary (starting at zero)
|
15109 |
|
|
until it finds a place to allocate that 64- bit field such that
|
15110 |
|
|
at least 31 contiguous (and previously unallocated) bits remain
|
15111 |
|
|
within that selected 64 bit field. (As it turns out, for the
|
15112 |
|
|
example above, the compiler finds it is OK to allocate the
|
15113 |
|
|
"containing object" 64-bit field at bit-offset zero within the
|
15114 |
|
|
structure type.)
|
15115 |
|
|
|
15116 |
|
|
Here we attempt to work backwards from the limited set of facts
|
15117 |
|
|
we're given, and we try to deduce from those facts, where GCC
|
15118 |
|
|
must have believed that the containing object started (within
|
15119 |
|
|
the structure type). The value we deduce is then used (by the
|
15120 |
|
|
callers of this routine) to generate DW_AT_location and
|
15121 |
|
|
DW_AT_bit_offset attributes for fields (both bit-fields and, in
|
15122 |
|
|
the case of DW_AT_location, regular fields as well). */
|
15123 |
|
|
|
15124 |
|
|
/* Figure out the bit-distance from the start of the structure to
|
15125 |
|
|
the "deepest" bit of the bit-field. */
|
15126 |
|
|
deepest_bitpos = bitpos_int + field_size_in_bits;
|
15127 |
|
|
|
15128 |
|
|
/* This is the tricky part. Use some fancy footwork to deduce
|
15129 |
|
|
where the lowest addressed bit of the containing object must
|
15130 |
|
|
be. */
|
15131 |
|
|
object_offset_in_bits = deepest_bitpos - type_size_in_bits;
|
15132 |
|
|
|
15133 |
|
|
/* Round up to type_align by default. This works best for
|
15134 |
|
|
bitfields. */
|
15135 |
|
|
object_offset_in_bits
|
15136 |
|
|
= round_up_to_align (object_offset_in_bits, type_align_in_bits);
|
15137 |
|
|
|
15138 |
|
|
if (object_offset_in_bits > bitpos_int)
|
15139 |
|
|
{
|
15140 |
|
|
object_offset_in_bits = deepest_bitpos - type_size_in_bits;
|
15141 |
|
|
|
15142 |
|
|
/* Round up to decl_align instead. */
|
15143 |
|
|
object_offset_in_bits
|
15144 |
|
|
= round_up_to_align (object_offset_in_bits, decl_align_in_bits);
|
15145 |
|
|
}
|
15146 |
|
|
}
|
15147 |
|
|
else
|
15148 |
|
|
#endif
|
15149 |
|
|
object_offset_in_bits = bitpos_int;
|
15150 |
|
|
|
15151 |
|
|
return object_offset_in_bits / BITS_PER_UNIT;
|
15152 |
|
|
}
|
15153 |
|
|
|
15154 |
|
|
/* The following routines define various Dwarf attributes and any data
|
15155 |
|
|
associated with them. */
|
15156 |
|
|
|
15157 |
|
|
/* Add a location description attribute value to a DIE.
|
15158 |
|
|
|
15159 |
|
|
This emits location attributes suitable for whole variables and
|
15160 |
|
|
whole parameters. Note that the location attributes for struct fields are
|
15161 |
|
|
generated by the routine `data_member_location_attribute' below. */
|
15162 |
|
|
|
15163 |
|
|
static inline void
|
15164 |
|
|
add_AT_location_description (dw_die_ref die, enum dwarf_attribute attr_kind,
|
15165 |
|
|
dw_loc_list_ref descr)
|
15166 |
|
|
{
|
15167 |
|
|
if (descr == 0)
|
15168 |
|
|
return;
|
15169 |
|
|
if (single_element_loc_list_p (descr))
|
15170 |
|
|
add_AT_loc (die, attr_kind, descr->expr);
|
15171 |
|
|
else
|
15172 |
|
|
add_AT_loc_list (die, attr_kind, descr);
|
15173 |
|
|
}
|
15174 |
|
|
|
15175 |
|
|
/* Attach the specialized form of location attribute used for data members of
|
15176 |
|
|
struct and union types. In the special case of a FIELD_DECL node which
|
15177 |
|
|
represents a bit-field, the "offset" part of this special location
|
15178 |
|
|
descriptor must indicate the distance in bytes from the lowest-addressed
|
15179 |
|
|
byte of the containing struct or union type to the lowest-addressed byte of
|
15180 |
|
|
the "containing object" for the bit-field. (See the `field_byte_offset'
|
15181 |
|
|
function above).
|
15182 |
|
|
|
15183 |
|
|
For any given bit-field, the "containing object" is a hypothetical object
|
15184 |
|
|
(of some integral or enum type) within which the given bit-field lives. The
|
15185 |
|
|
type of this hypothetical "containing object" is always the same as the
|
15186 |
|
|
declared type of the individual bit-field itself (for GCC anyway... the
|
15187 |
|
|
DWARF spec doesn't actually mandate this). Note that it is the size (in
|
15188 |
|
|
bytes) of the hypothetical "containing object" which will be given in the
|
15189 |
|
|
DW_AT_byte_size attribute for this bit-field. (See the
|
15190 |
|
|
`byte_size_attribute' function below.) It is also used when calculating the
|
15191 |
|
|
value of the DW_AT_bit_offset attribute. (See the `bit_offset_attribute'
|
15192 |
|
|
function below.) */
|
15193 |
|
|
|
15194 |
|
|
static void
|
15195 |
|
|
add_data_member_location_attribute (dw_die_ref die, tree decl)
|
15196 |
|
|
{
|
15197 |
|
|
HOST_WIDE_INT offset;
|
15198 |
|
|
dw_loc_descr_ref loc_descr = 0;
|
15199 |
|
|
|
15200 |
|
|
if (TREE_CODE (decl) == TREE_BINFO)
|
15201 |
|
|
{
|
15202 |
|
|
/* We're working on the TAG_inheritance for a base class. */
|
15203 |
|
|
if (BINFO_VIRTUAL_P (decl) && is_cxx ())
|
15204 |
|
|
{
|
15205 |
|
|
/* For C++ virtual bases we can't just use BINFO_OFFSET, as they
|
15206 |
|
|
aren't at a fixed offset from all (sub)objects of the same
|
15207 |
|
|
type. We need to extract the appropriate offset from our
|
15208 |
|
|
vtable. The following dwarf expression means
|
15209 |
|
|
|
15210 |
|
|
BaseAddr = ObAddr + *((*ObAddr) - Offset)
|
15211 |
|
|
|
15212 |
|
|
This is specific to the V3 ABI, of course. */
|
15213 |
|
|
|
15214 |
|
|
dw_loc_descr_ref tmp;
|
15215 |
|
|
|
15216 |
|
|
/* Make a copy of the object address. */
|
15217 |
|
|
tmp = new_loc_descr (DW_OP_dup, 0, 0);
|
15218 |
|
|
add_loc_descr (&loc_descr, tmp);
|
15219 |
|
|
|
15220 |
|
|
/* Extract the vtable address. */
|
15221 |
|
|
tmp = new_loc_descr (DW_OP_deref, 0, 0);
|
15222 |
|
|
add_loc_descr (&loc_descr, tmp);
|
15223 |
|
|
|
15224 |
|
|
/* Calculate the address of the offset. */
|
15225 |
|
|
offset = tree_low_cst (BINFO_VPTR_FIELD (decl), 0);
|
15226 |
|
|
gcc_assert (offset < 0);
|
15227 |
|
|
|
15228 |
|
|
tmp = int_loc_descriptor (-offset);
|
15229 |
|
|
add_loc_descr (&loc_descr, tmp);
|
15230 |
|
|
tmp = new_loc_descr (DW_OP_minus, 0, 0);
|
15231 |
|
|
add_loc_descr (&loc_descr, tmp);
|
15232 |
|
|
|
15233 |
|
|
/* Extract the offset. */
|
15234 |
|
|
tmp = new_loc_descr (DW_OP_deref, 0, 0);
|
15235 |
|
|
add_loc_descr (&loc_descr, tmp);
|
15236 |
|
|
|
15237 |
|
|
/* Add it to the object address. */
|
15238 |
|
|
tmp = new_loc_descr (DW_OP_plus, 0, 0);
|
15239 |
|
|
add_loc_descr (&loc_descr, tmp);
|
15240 |
|
|
}
|
15241 |
|
|
else
|
15242 |
|
|
offset = tree_low_cst (BINFO_OFFSET (decl), 0);
|
15243 |
|
|
}
|
15244 |
|
|
else
|
15245 |
|
|
offset = field_byte_offset (decl);
|
15246 |
|
|
|
15247 |
|
|
if (! loc_descr)
|
15248 |
|
|
{
|
15249 |
|
|
if (dwarf_version > 2)
|
15250 |
|
|
{
|
15251 |
|
|
/* Don't need to output a location expression, just the constant. */
|
15252 |
|
|
add_AT_int (die, DW_AT_data_member_location, offset);
|
15253 |
|
|
return;
|
15254 |
|
|
}
|
15255 |
|
|
else
|
15256 |
|
|
{
|
15257 |
|
|
enum dwarf_location_atom op;
|
15258 |
|
|
|
15259 |
|
|
/* The DWARF2 standard says that we should assume that the structure
|
15260 |
|
|
address is already on the stack, so we can specify a structure
|
15261 |
|
|
field address by using DW_OP_plus_uconst. */
|
15262 |
|
|
|
15263 |
|
|
#ifdef MIPS_DEBUGGING_INFO
|
15264 |
|
|
/* ??? The SGI dwarf reader does not handle the DW_OP_plus_uconst
|
15265 |
|
|
operator correctly. It works only if we leave the offset on the
|
15266 |
|
|
stack. */
|
15267 |
|
|
op = DW_OP_constu;
|
15268 |
|
|
#else
|
15269 |
|
|
op = DW_OP_plus_uconst;
|
15270 |
|
|
#endif
|
15271 |
|
|
|
15272 |
|
|
loc_descr = new_loc_descr (op, offset, 0);
|
15273 |
|
|
}
|
15274 |
|
|
}
|
15275 |
|
|
|
15276 |
|
|
add_AT_loc (die, DW_AT_data_member_location, loc_descr);
|
15277 |
|
|
}
|
15278 |
|
|
|
15279 |
|
|
/* Writes integer values to dw_vec_const array. */
|
15280 |
|
|
|
15281 |
|
|
static void
|
15282 |
|
|
insert_int (HOST_WIDE_INT val, unsigned int size, unsigned char *dest)
|
15283 |
|
|
{
|
15284 |
|
|
while (size != 0)
|
15285 |
|
|
{
|
15286 |
|
|
*dest++ = val & 0xff;
|
15287 |
|
|
val >>= 8;
|
15288 |
|
|
--size;
|
15289 |
|
|
}
|
15290 |
|
|
}
|
15291 |
|
|
|
15292 |
|
|
/* Reads integers from dw_vec_const array. Inverse of insert_int. */
|
15293 |
|
|
|
15294 |
|
|
static HOST_WIDE_INT
|
15295 |
|
|
extract_int (const unsigned char *src, unsigned int size)
|
15296 |
|
|
{
|
15297 |
|
|
HOST_WIDE_INT val = 0;
|
15298 |
|
|
|
15299 |
|
|
src += size;
|
15300 |
|
|
while (size != 0)
|
15301 |
|
|
{
|
15302 |
|
|
val <<= 8;
|
15303 |
|
|
val |= *--src & 0xff;
|
15304 |
|
|
--size;
|
15305 |
|
|
}
|
15306 |
|
|
return val;
|
15307 |
|
|
}
|
15308 |
|
|
|
15309 |
|
|
/* Writes floating point values to dw_vec_const array. */
|
15310 |
|
|
|
15311 |
|
|
static void
|
15312 |
|
|
insert_float (const_rtx rtl, unsigned char *array)
|
15313 |
|
|
{
|
15314 |
|
|
REAL_VALUE_TYPE rv;
|
15315 |
|
|
long val[4];
|
15316 |
|
|
int i;
|
15317 |
|
|
|
15318 |
|
|
REAL_VALUE_FROM_CONST_DOUBLE (rv, rtl);
|
15319 |
|
|
real_to_target (val, &rv, GET_MODE (rtl));
|
15320 |
|
|
|
15321 |
|
|
/* real_to_target puts 32-bit pieces in each long. Pack them. */
|
15322 |
|
|
for (i = 0; i < GET_MODE_SIZE (GET_MODE (rtl)) / 4; i++)
|
15323 |
|
|
{
|
15324 |
|
|
insert_int (val[i], 4, array);
|
15325 |
|
|
array += 4;
|
15326 |
|
|
}
|
15327 |
|
|
}
|
15328 |
|
|
|
15329 |
|
|
/* Attach a DW_AT_const_value attribute for a variable or a parameter which
|
15330 |
|
|
does not have a "location" either in memory or in a register. These
|
15331 |
|
|
things can arise in GNU C when a constant is passed as an actual parameter
|
15332 |
|
|
to an inlined function. They can also arise in C++ where declared
|
15333 |
|
|
constants do not necessarily get memory "homes". */
|
15334 |
|
|
|
15335 |
|
|
static bool
|
15336 |
|
|
add_const_value_attribute (dw_die_ref die, rtx rtl)
|
15337 |
|
|
{
|
15338 |
|
|
switch (GET_CODE (rtl))
|
15339 |
|
|
{
|
15340 |
|
|
case CONST_INT:
|
15341 |
|
|
{
|
15342 |
|
|
HOST_WIDE_INT val = INTVAL (rtl);
|
15343 |
|
|
|
15344 |
|
|
if (val < 0)
|
15345 |
|
|
add_AT_int (die, DW_AT_const_value, val);
|
15346 |
|
|
else
|
15347 |
|
|
add_AT_unsigned (die, DW_AT_const_value, (unsigned HOST_WIDE_INT) val);
|
15348 |
|
|
}
|
15349 |
|
|
return true;
|
15350 |
|
|
|
15351 |
|
|
case CONST_DOUBLE:
|
15352 |
|
|
/* Note that a CONST_DOUBLE rtx could represent either an integer or a
|
15353 |
|
|
floating-point constant. A CONST_DOUBLE is used whenever the
|
15354 |
|
|
constant requires more than one word in order to be adequately
|
15355 |
|
|
represented. */
|
15356 |
|
|
{
|
15357 |
|
|
enum machine_mode mode = GET_MODE (rtl);
|
15358 |
|
|
|
15359 |
|
|
if (SCALAR_FLOAT_MODE_P (mode))
|
15360 |
|
|
{
|
15361 |
|
|
unsigned int length = GET_MODE_SIZE (mode);
|
15362 |
|
|
unsigned char *array = GGC_NEWVEC (unsigned char, length);
|
15363 |
|
|
|
15364 |
|
|
insert_float (rtl, array);
|
15365 |
|
|
add_AT_vec (die, DW_AT_const_value, length / 4, 4, array);
|
15366 |
|
|
}
|
15367 |
|
|
else
|
15368 |
|
|
add_AT_double (die, DW_AT_const_value,
|
15369 |
|
|
CONST_DOUBLE_HIGH (rtl), CONST_DOUBLE_LOW (rtl));
|
15370 |
|
|
}
|
15371 |
|
|
return true;
|
15372 |
|
|
|
15373 |
|
|
case CONST_VECTOR:
|
15374 |
|
|
{
|
15375 |
|
|
enum machine_mode mode = GET_MODE (rtl);
|
15376 |
|
|
unsigned int elt_size = GET_MODE_UNIT_SIZE (mode);
|
15377 |
|
|
unsigned int length = CONST_VECTOR_NUNITS (rtl);
|
15378 |
|
|
unsigned char *array = GGC_NEWVEC (unsigned char, length * elt_size);
|
15379 |
|
|
unsigned int i;
|
15380 |
|
|
unsigned char *p;
|
15381 |
|
|
|
15382 |
|
|
switch (GET_MODE_CLASS (mode))
|
15383 |
|
|
{
|
15384 |
|
|
case MODE_VECTOR_INT:
|
15385 |
|
|
for (i = 0, p = array; i < length; i++, p += elt_size)
|
15386 |
|
|
{
|
15387 |
|
|
rtx elt = CONST_VECTOR_ELT (rtl, i);
|
15388 |
|
|
HOST_WIDE_INT lo, hi;
|
15389 |
|
|
|
15390 |
|
|
switch (GET_CODE (elt))
|
15391 |
|
|
{
|
15392 |
|
|
case CONST_INT:
|
15393 |
|
|
lo = INTVAL (elt);
|
15394 |
|
|
hi = -(lo < 0);
|
15395 |
|
|
break;
|
15396 |
|
|
|
15397 |
|
|
case CONST_DOUBLE:
|
15398 |
|
|
lo = CONST_DOUBLE_LOW (elt);
|
15399 |
|
|
hi = CONST_DOUBLE_HIGH (elt);
|
15400 |
|
|
break;
|
15401 |
|
|
|
15402 |
|
|
default:
|
15403 |
|
|
gcc_unreachable ();
|
15404 |
|
|
}
|
15405 |
|
|
|
15406 |
|
|
if (elt_size <= sizeof (HOST_WIDE_INT))
|
15407 |
|
|
insert_int (lo, elt_size, p);
|
15408 |
|
|
else
|
15409 |
|
|
{
|
15410 |
|
|
unsigned char *p0 = p;
|
15411 |
|
|
unsigned char *p1 = p + sizeof (HOST_WIDE_INT);
|
15412 |
|
|
|
15413 |
|
|
gcc_assert (elt_size == 2 * sizeof (HOST_WIDE_INT));
|
15414 |
|
|
if (WORDS_BIG_ENDIAN)
|
15415 |
|
|
{
|
15416 |
|
|
p0 = p1;
|
15417 |
|
|
p1 = p;
|
15418 |
|
|
}
|
15419 |
|
|
insert_int (lo, sizeof (HOST_WIDE_INT), p0);
|
15420 |
|
|
insert_int (hi, sizeof (HOST_WIDE_INT), p1);
|
15421 |
|
|
}
|
15422 |
|
|
}
|
15423 |
|
|
break;
|
15424 |
|
|
|
15425 |
|
|
case MODE_VECTOR_FLOAT:
|
15426 |
|
|
for (i = 0, p = array; i < length; i++, p += elt_size)
|
15427 |
|
|
{
|
15428 |
|
|
rtx elt = CONST_VECTOR_ELT (rtl, i);
|
15429 |
|
|
insert_float (elt, p);
|
15430 |
|
|
}
|
15431 |
|
|
break;
|
15432 |
|
|
|
15433 |
|
|
default:
|
15434 |
|
|
gcc_unreachable ();
|
15435 |
|
|
}
|
15436 |
|
|
|
15437 |
|
|
add_AT_vec (die, DW_AT_const_value, length, elt_size, array);
|
15438 |
|
|
}
|
15439 |
|
|
return true;
|
15440 |
|
|
|
15441 |
|
|
case CONST_STRING:
|
15442 |
|
|
if (dwarf_version >= 4 || !dwarf_strict)
|
15443 |
|
|
{
|
15444 |
|
|
dw_loc_descr_ref loc_result;
|
15445 |
|
|
resolve_one_addr (&rtl, NULL);
|
15446 |
|
|
rtl_addr:
|
15447 |
|
|
loc_result = new_loc_descr (DW_OP_addr, 0, 0);
|
15448 |
|
|
loc_result->dw_loc_oprnd1.val_class = dw_val_class_addr;
|
15449 |
|
|
loc_result->dw_loc_oprnd1.v.val_addr = rtl;
|
15450 |
|
|
add_loc_descr (&loc_result, new_loc_descr (DW_OP_stack_value, 0, 0));
|
15451 |
|
|
add_AT_loc (die, DW_AT_location, loc_result);
|
15452 |
|
|
VEC_safe_push (rtx, gc, used_rtx_array, rtl);
|
15453 |
|
|
return true;
|
15454 |
|
|
}
|
15455 |
|
|
return false;
|
15456 |
|
|
|
15457 |
|
|
case CONST:
|
15458 |
|
|
if (CONSTANT_P (XEXP (rtl, 0)))
|
15459 |
|
|
return add_const_value_attribute (die, XEXP (rtl, 0));
|
15460 |
|
|
/* FALLTHROUGH */
|
15461 |
|
|
case SYMBOL_REF:
|
15462 |
|
|
if (!const_ok_for_output (rtl))
|
15463 |
|
|
return false;
|
15464 |
|
|
case LABEL_REF:
|
15465 |
|
|
if (dwarf_version >= 4 || !dwarf_strict)
|
15466 |
|
|
goto rtl_addr;
|
15467 |
|
|
return false;
|
15468 |
|
|
|
15469 |
|
|
case PLUS:
|
15470 |
|
|
/* In cases where an inlined instance of an inline function is passed
|
15471 |
|
|
the address of an `auto' variable (which is local to the caller) we
|
15472 |
|
|
can get a situation where the DECL_RTL of the artificial local
|
15473 |
|
|
variable (for the inlining) which acts as a stand-in for the
|
15474 |
|
|
corresponding formal parameter (of the inline function) will look
|
15475 |
|
|
like (plus:SI (reg:SI FRAME_PTR) (const_int ...)). This is not
|
15476 |
|
|
exactly a compile-time constant expression, but it isn't the address
|
15477 |
|
|
of the (artificial) local variable either. Rather, it represents the
|
15478 |
|
|
*value* which the artificial local variable always has during its
|
15479 |
|
|
lifetime. We currently have no way to represent such quasi-constant
|
15480 |
|
|
values in Dwarf, so for now we just punt and generate nothing. */
|
15481 |
|
|
return false;
|
15482 |
|
|
|
15483 |
|
|
case HIGH:
|
15484 |
|
|
case CONST_FIXED:
|
15485 |
|
|
return false;
|
15486 |
|
|
|
15487 |
|
|
case MEM:
|
15488 |
|
|
if (GET_CODE (XEXP (rtl, 0)) == CONST_STRING
|
15489 |
|
|
&& MEM_READONLY_P (rtl)
|
15490 |
|
|
&& GET_MODE (rtl) == BLKmode)
|
15491 |
|
|
{
|
15492 |
|
|
add_AT_string (die, DW_AT_const_value, XSTR (XEXP (rtl, 0), 0));
|
15493 |
|
|
return true;
|
15494 |
|
|
}
|
15495 |
|
|
return false;
|
15496 |
|
|
|
15497 |
|
|
default:
|
15498 |
|
|
/* No other kinds of rtx should be possible here. */
|
15499 |
|
|
gcc_unreachable ();
|
15500 |
|
|
}
|
15501 |
|
|
return false;
|
15502 |
|
|
}
|
15503 |
|
|
|
15504 |
|
|
/* Determine whether the evaluation of EXPR references any variables
|
15505 |
|
|
or functions which aren't otherwise used (and therefore may not be
|
15506 |
|
|
output). */
|
15507 |
|
|
static tree
|
15508 |
|
|
reference_to_unused (tree * tp, int * walk_subtrees,
|
15509 |
|
|
void * data ATTRIBUTE_UNUSED)
|
15510 |
|
|
{
|
15511 |
|
|
if (! EXPR_P (*tp) && ! CONSTANT_CLASS_P (*tp))
|
15512 |
|
|
*walk_subtrees = 0;
|
15513 |
|
|
|
15514 |
|
|
if (DECL_P (*tp) && ! TREE_PUBLIC (*tp) && ! TREE_USED (*tp)
|
15515 |
|
|
&& ! TREE_ASM_WRITTEN (*tp))
|
15516 |
|
|
return *tp;
|
15517 |
|
|
/* ??? The C++ FE emits debug information for using decls, so
|
15518 |
|
|
putting gcc_unreachable here falls over. See PR31899. For now
|
15519 |
|
|
be conservative. */
|
15520 |
|
|
else if (!cgraph_global_info_ready
|
15521 |
|
|
&& (TREE_CODE (*tp) == VAR_DECL || TREE_CODE (*tp) == FUNCTION_DECL))
|
15522 |
|
|
return *tp;
|
15523 |
|
|
else if (TREE_CODE (*tp) == VAR_DECL)
|
15524 |
|
|
{
|
15525 |
|
|
struct varpool_node *node = varpool_node (*tp);
|
15526 |
|
|
if (!node->needed)
|
15527 |
|
|
return *tp;
|
15528 |
|
|
}
|
15529 |
|
|
else if (TREE_CODE (*tp) == FUNCTION_DECL
|
15530 |
|
|
&& (!DECL_EXTERNAL (*tp) || DECL_DECLARED_INLINE_P (*tp)))
|
15531 |
|
|
{
|
15532 |
|
|
/* The call graph machinery must have finished analyzing,
|
15533 |
|
|
optimizing and gimplifying the CU by now.
|
15534 |
|
|
So if *TP has no call graph node associated
|
15535 |
|
|
to it, it means *TP will not be emitted. */
|
15536 |
|
|
if (!cgraph_get_node (*tp))
|
15537 |
|
|
return *tp;
|
15538 |
|
|
}
|
15539 |
|
|
else if (TREE_CODE (*tp) == STRING_CST && !TREE_ASM_WRITTEN (*tp))
|
15540 |
|
|
return *tp;
|
15541 |
|
|
|
15542 |
|
|
return NULL_TREE;
|
15543 |
|
|
}
|
15544 |
|
|
|
15545 |
|
|
/* Generate an RTL constant from a decl initializer INIT with decl type TYPE,
|
15546 |
|
|
for use in a later add_const_value_attribute call. */
|
15547 |
|
|
|
15548 |
|
|
static rtx
|
15549 |
|
|
rtl_for_decl_init (tree init, tree type)
|
15550 |
|
|
{
|
15551 |
|
|
rtx rtl = NULL_RTX;
|
15552 |
|
|
|
15553 |
|
|
/* If a variable is initialized with a string constant without embedded
|
15554 |
|
|
zeros, build CONST_STRING. */
|
15555 |
|
|
if (TREE_CODE (init) == STRING_CST && TREE_CODE (type) == ARRAY_TYPE)
|
15556 |
|
|
{
|
15557 |
|
|
tree enttype = TREE_TYPE (type);
|
15558 |
|
|
tree domain = TYPE_DOMAIN (type);
|
15559 |
|
|
enum machine_mode mode = TYPE_MODE (enttype);
|
15560 |
|
|
|
15561 |
|
|
if (GET_MODE_CLASS (mode) == MODE_INT && GET_MODE_SIZE (mode) == 1
|
15562 |
|
|
&& domain
|
15563 |
|
|
&& integer_zerop (TYPE_MIN_VALUE (domain))
|
15564 |
|
|
&& compare_tree_int (TYPE_MAX_VALUE (domain),
|
15565 |
|
|
TREE_STRING_LENGTH (init) - 1) == 0
|
15566 |
|
|
&& ((size_t) TREE_STRING_LENGTH (init)
|
15567 |
|
|
== strlen (TREE_STRING_POINTER (init)) + 1))
|
15568 |
|
|
{
|
15569 |
|
|
rtl = gen_rtx_CONST_STRING (VOIDmode,
|
15570 |
|
|
ggc_strdup (TREE_STRING_POINTER (init)));
|
15571 |
|
|
rtl = gen_rtx_MEM (BLKmode, rtl);
|
15572 |
|
|
MEM_READONLY_P (rtl) = 1;
|
15573 |
|
|
}
|
15574 |
|
|
}
|
15575 |
|
|
/* Other aggregates, and complex values, could be represented using
|
15576 |
|
|
CONCAT: FIXME! */
|
15577 |
|
|
else if (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == COMPLEX_TYPE)
|
15578 |
|
|
;
|
15579 |
|
|
/* Vectors only work if their mode is supported by the target.
|
15580 |
|
|
FIXME: generic vectors ought to work too. */
|
15581 |
|
|
else if (TREE_CODE (type) == VECTOR_TYPE && TYPE_MODE (type) == BLKmode)
|
15582 |
|
|
;
|
15583 |
|
|
/* If the initializer is something that we know will expand into an
|
15584 |
|
|
immediate RTL constant, expand it now. We must be careful not to
|
15585 |
|
|
reference variables which won't be output. */
|
15586 |
|
|
else if (initializer_constant_valid_p (init, type)
|
15587 |
|
|
&& ! walk_tree (&init, reference_to_unused, NULL, NULL))
|
15588 |
|
|
{
|
15589 |
|
|
/* Convert vector CONSTRUCTOR initializers to VECTOR_CST if
|
15590 |
|
|
possible. */
|
15591 |
|
|
if (TREE_CODE (type) == VECTOR_TYPE)
|
15592 |
|
|
switch (TREE_CODE (init))
|
15593 |
|
|
{
|
15594 |
|
|
case VECTOR_CST:
|
15595 |
|
|
break;
|
15596 |
|
|
case CONSTRUCTOR:
|
15597 |
|
|
if (TREE_CONSTANT (init))
|
15598 |
|
|
{
|
15599 |
|
|
VEC(constructor_elt,gc) *elts = CONSTRUCTOR_ELTS (init);
|
15600 |
|
|
bool constant_p = true;
|
15601 |
|
|
tree value;
|
15602 |
|
|
unsigned HOST_WIDE_INT ix;
|
15603 |
|
|
|
15604 |
|
|
/* Even when ctor is constant, it might contain non-*_CST
|
15605 |
|
|
elements (e.g. { 1.0/0.0 - 1.0/0.0, 0.0 }) and those don't
|
15606 |
|
|
belong into VECTOR_CST nodes. */
|
15607 |
|
|
FOR_EACH_CONSTRUCTOR_VALUE (elts, ix, value)
|
15608 |
|
|
if (!CONSTANT_CLASS_P (value))
|
15609 |
|
|
{
|
15610 |
|
|
constant_p = false;
|
15611 |
|
|
break;
|
15612 |
|
|
}
|
15613 |
|
|
|
15614 |
|
|
if (constant_p)
|
15615 |
|
|
{
|
15616 |
|
|
init = build_vector_from_ctor (type, elts);
|
15617 |
|
|
break;
|
15618 |
|
|
}
|
15619 |
|
|
}
|
15620 |
|
|
/* FALLTHRU */
|
15621 |
|
|
|
15622 |
|
|
default:
|
15623 |
|
|
return NULL;
|
15624 |
|
|
}
|
15625 |
|
|
|
15626 |
|
|
rtl = expand_expr (init, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
|
15627 |
|
|
|
15628 |
|
|
/* If expand_expr returns a MEM, it wasn't immediate. */
|
15629 |
|
|
gcc_assert (!rtl || !MEM_P (rtl));
|
15630 |
|
|
}
|
15631 |
|
|
|
15632 |
|
|
return rtl;
|
15633 |
|
|
}
|
15634 |
|
|
|
15635 |
|
|
/* Generate RTL for the variable DECL to represent its location. */
|
15636 |
|
|
|
15637 |
|
|
static rtx
|
15638 |
|
|
rtl_for_decl_location (tree decl)
|
15639 |
|
|
{
|
15640 |
|
|
rtx rtl;
|
15641 |
|
|
|
15642 |
|
|
/* Here we have to decide where we are going to say the parameter "lives"
|
15643 |
|
|
(as far as the debugger is concerned). We only have a couple of
|
15644 |
|
|
choices. GCC provides us with DECL_RTL and with DECL_INCOMING_RTL.
|
15645 |
|
|
|
15646 |
|
|
DECL_RTL normally indicates where the parameter lives during most of the
|
15647 |
|
|
activation of the function. If optimization is enabled however, this
|
15648 |
|
|
could be either NULL or else a pseudo-reg. Both of those cases indicate
|
15649 |
|
|
that the parameter doesn't really live anywhere (as far as the code
|
15650 |
|
|
generation parts of GCC are concerned) during most of the function's
|
15651 |
|
|
activation. That will happen (for example) if the parameter is never
|
15652 |
|
|
referenced within the function.
|
15653 |
|
|
|
15654 |
|
|
We could just generate a location descriptor here for all non-NULL
|
15655 |
|
|
non-pseudo values of DECL_RTL and ignore all of the rest, but we can be
|
15656 |
|
|
a little nicer than that if we also consider DECL_INCOMING_RTL in cases
|
15657 |
|
|
where DECL_RTL is NULL or is a pseudo-reg.
|
15658 |
|
|
|
15659 |
|
|
Note however that we can only get away with using DECL_INCOMING_RTL as
|
15660 |
|
|
a backup substitute for DECL_RTL in certain limited cases. In cases
|
15661 |
|
|
where DECL_ARG_TYPE (decl) indicates the same type as TREE_TYPE (decl),
|
15662 |
|
|
we can be sure that the parameter was passed using the same type as it is
|
15663 |
|
|
declared to have within the function, and that its DECL_INCOMING_RTL
|
15664 |
|
|
points us to a place where a value of that type is passed.
|
15665 |
|
|
|
15666 |
|
|
In cases where DECL_ARG_TYPE (decl) and TREE_TYPE (decl) are different,
|
15667 |
|
|
we cannot (in general) use DECL_INCOMING_RTL as a substitute for DECL_RTL
|
15668 |
|
|
because in these cases DECL_INCOMING_RTL points us to a value of some
|
15669 |
|
|
type which is *different* from the type of the parameter itself. Thus,
|
15670 |
|
|
if we tried to use DECL_INCOMING_RTL to generate a location attribute in
|
15671 |
|
|
such cases, the debugger would end up (for example) trying to fetch a
|
15672 |
|
|
`float' from a place which actually contains the first part of a
|
15673 |
|
|
`double'. That would lead to really incorrect and confusing
|
15674 |
|
|
output at debug-time.
|
15675 |
|
|
|
15676 |
|
|
So, in general, we *do not* use DECL_INCOMING_RTL as a backup for DECL_RTL
|
15677 |
|
|
in cases where DECL_ARG_TYPE (decl) != TREE_TYPE (decl). There
|
15678 |
|
|
are a couple of exceptions however. On little-endian machines we can
|
15679 |
|
|
get away with using DECL_INCOMING_RTL even when DECL_ARG_TYPE (decl) is
|
15680 |
|
|
not the same as TREE_TYPE (decl), but only when DECL_ARG_TYPE (decl) is
|
15681 |
|
|
an integral type that is smaller than TREE_TYPE (decl). These cases arise
|
15682 |
|
|
when (on a little-endian machine) a non-prototyped function has a
|
15683 |
|
|
parameter declared to be of type `short' or `char'. In such cases,
|
15684 |
|
|
TREE_TYPE (decl) will be `short' or `char', DECL_ARG_TYPE (decl) will
|
15685 |
|
|
be `int', and DECL_INCOMING_RTL will point to the lowest-order byte of the
|
15686 |
|
|
passed `int' value. If the debugger then uses that address to fetch
|
15687 |
|
|
a `short' or a `char' (on a little-endian machine) the result will be
|
15688 |
|
|
the correct data, so we allow for such exceptional cases below.
|
15689 |
|
|
|
15690 |
|
|
Note that our goal here is to describe the place where the given formal
|
15691 |
|
|
parameter lives during most of the function's activation (i.e. between the
|
15692 |
|
|
end of the prologue and the start of the epilogue). We'll do that as best
|
15693 |
|
|
as we can. Note however that if the given formal parameter is modified
|
15694 |
|
|
sometime during the execution of the function, then a stack backtrace (at
|
15695 |
|
|
debug-time) will show the function as having been called with the *new*
|
15696 |
|
|
value rather than the value which was originally passed in. This happens
|
15697 |
|
|
rarely enough that it is not a major problem, but it *is* a problem, and
|
15698 |
|
|
I'd like to fix it.
|
15699 |
|
|
|
15700 |
|
|
A future version of dwarf2out.c may generate two additional attributes for
|
15701 |
|
|
any given DW_TAG_formal_parameter DIE which will describe the "passed
|
15702 |
|
|
type" and the "passed location" for the given formal parameter in addition
|
15703 |
|
|
to the attributes we now generate to indicate the "declared type" and the
|
15704 |
|
|
"active location" for each parameter. This additional set of attributes
|
15705 |
|
|
could be used by debuggers for stack backtraces. Separately, note that
|
15706 |
|
|
sometimes DECL_RTL can be NULL and DECL_INCOMING_RTL can be NULL also.
|
15707 |
|
|
This happens (for example) for inlined-instances of inline function formal
|
15708 |
|
|
parameters which are never referenced. This really shouldn't be
|
15709 |
|
|
happening. All PARM_DECL nodes should get valid non-NULL
|
15710 |
|
|
DECL_INCOMING_RTL values. FIXME. */
|
15711 |
|
|
|
15712 |
|
|
/* Use DECL_RTL as the "location" unless we find something better. */
|
15713 |
|
|
rtl = DECL_RTL_IF_SET (decl);
|
15714 |
|
|
|
15715 |
|
|
/* When generating abstract instances, ignore everything except
|
15716 |
|
|
constants, symbols living in memory, and symbols living in
|
15717 |
|
|
fixed registers. */
|
15718 |
|
|
if (! reload_completed)
|
15719 |
|
|
{
|
15720 |
|
|
if (rtl
|
15721 |
|
|
&& (CONSTANT_P (rtl)
|
15722 |
|
|
|| (MEM_P (rtl)
|
15723 |
|
|
&& CONSTANT_P (XEXP (rtl, 0)))
|
15724 |
|
|
|| (REG_P (rtl)
|
15725 |
|
|
&& TREE_CODE (decl) == VAR_DECL
|
15726 |
|
|
&& TREE_STATIC (decl))))
|
15727 |
|
|
{
|
15728 |
|
|
rtl = targetm.delegitimize_address (rtl);
|
15729 |
|
|
return rtl;
|
15730 |
|
|
}
|
15731 |
|
|
rtl = NULL_RTX;
|
15732 |
|
|
}
|
15733 |
|
|
else if (TREE_CODE (decl) == PARM_DECL)
|
15734 |
|
|
{
|
15735 |
|
|
if (rtl == NULL_RTX || is_pseudo_reg (rtl))
|
15736 |
|
|
{
|
15737 |
|
|
tree declared_type = TREE_TYPE (decl);
|
15738 |
|
|
tree passed_type = DECL_ARG_TYPE (decl);
|
15739 |
|
|
enum machine_mode dmode = TYPE_MODE (declared_type);
|
15740 |
|
|
enum machine_mode pmode = TYPE_MODE (passed_type);
|
15741 |
|
|
|
15742 |
|
|
/* This decl represents a formal parameter which was optimized out.
|
15743 |
|
|
Note that DECL_INCOMING_RTL may be NULL in here, but we handle
|
15744 |
|
|
all cases where (rtl == NULL_RTX) just below. */
|
15745 |
|
|
if (dmode == pmode)
|
15746 |
|
|
rtl = DECL_INCOMING_RTL (decl);
|
15747 |
|
|
else if (SCALAR_INT_MODE_P (dmode)
|
15748 |
|
|
&& GET_MODE_SIZE (dmode) <= GET_MODE_SIZE (pmode)
|
15749 |
|
|
&& DECL_INCOMING_RTL (decl))
|
15750 |
|
|
{
|
15751 |
|
|
rtx inc = DECL_INCOMING_RTL (decl);
|
15752 |
|
|
if (REG_P (inc))
|
15753 |
|
|
rtl = inc;
|
15754 |
|
|
else if (MEM_P (inc))
|
15755 |
|
|
{
|
15756 |
|
|
if (BYTES_BIG_ENDIAN)
|
15757 |
|
|
rtl = adjust_address_nv (inc, dmode,
|
15758 |
|
|
GET_MODE_SIZE (pmode)
|
15759 |
|
|
- GET_MODE_SIZE (dmode));
|
15760 |
|
|
else
|
15761 |
|
|
rtl = inc;
|
15762 |
|
|
}
|
15763 |
|
|
}
|
15764 |
|
|
}
|
15765 |
|
|
|
15766 |
|
|
/* If the parm was passed in registers, but lives on the stack, then
|
15767 |
|
|
make a big endian correction if the mode of the type of the
|
15768 |
|
|
parameter is not the same as the mode of the rtl. */
|
15769 |
|
|
/* ??? This is the same series of checks that are made in dbxout.c before
|
15770 |
|
|
we reach the big endian correction code there. It isn't clear if all
|
15771 |
|
|
of these checks are necessary here, but keeping them all is the safe
|
15772 |
|
|
thing to do. */
|
15773 |
|
|
else if (MEM_P (rtl)
|
15774 |
|
|
&& XEXP (rtl, 0) != const0_rtx
|
15775 |
|
|
&& ! CONSTANT_P (XEXP (rtl, 0))
|
15776 |
|
|
/* Not passed in memory. */
|
15777 |
|
|
&& !MEM_P (DECL_INCOMING_RTL (decl))
|
15778 |
|
|
/* Not passed by invisible reference. */
|
15779 |
|
|
&& (!REG_P (XEXP (rtl, 0))
|
15780 |
|
|
|| REGNO (XEXP (rtl, 0)) == HARD_FRAME_POINTER_REGNUM
|
15781 |
|
|
|| REGNO (XEXP (rtl, 0)) == STACK_POINTER_REGNUM
|
15782 |
|
|
#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
|
15783 |
|
|
|| REGNO (XEXP (rtl, 0)) == ARG_POINTER_REGNUM
|
15784 |
|
|
#endif
|
15785 |
|
|
)
|
15786 |
|
|
/* Big endian correction check. */
|
15787 |
|
|
&& BYTES_BIG_ENDIAN
|
15788 |
|
|
&& TYPE_MODE (TREE_TYPE (decl)) != GET_MODE (rtl)
|
15789 |
|
|
&& (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (decl)))
|
15790 |
|
|
< UNITS_PER_WORD))
|
15791 |
|
|
{
|
15792 |
|
|
int offset = (UNITS_PER_WORD
|
15793 |
|
|
- GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (decl))));
|
15794 |
|
|
|
15795 |
|
|
rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (decl)),
|
15796 |
|
|
plus_constant (XEXP (rtl, 0), offset));
|
15797 |
|
|
}
|
15798 |
|
|
}
|
15799 |
|
|
else if (TREE_CODE (decl) == VAR_DECL
|
15800 |
|
|
&& rtl
|
15801 |
|
|
&& MEM_P (rtl)
|
15802 |
|
|
&& GET_MODE (rtl) != TYPE_MODE (TREE_TYPE (decl))
|
15803 |
|
|
&& BYTES_BIG_ENDIAN)
|
15804 |
|
|
{
|
15805 |
|
|
int rsize = GET_MODE_SIZE (GET_MODE (rtl));
|
15806 |
|
|
int dsize = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (decl)));
|
15807 |
|
|
|
15808 |
|
|
/* If a variable is declared "register" yet is smaller than
|
15809 |
|
|
a register, then if we store the variable to memory, it
|
15810 |
|
|
looks like we're storing a register-sized value, when in
|
15811 |
|
|
fact we are not. We need to adjust the offset of the
|
15812 |
|
|
storage location to reflect the actual value's bytes,
|
15813 |
|
|
else gdb will not be able to display it. */
|
15814 |
|
|
if (rsize > dsize)
|
15815 |
|
|
rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (decl)),
|
15816 |
|
|
plus_constant (XEXP (rtl, 0), rsize-dsize));
|
15817 |
|
|
}
|
15818 |
|
|
|
15819 |
|
|
/* A variable with no DECL_RTL but a DECL_INITIAL is a compile-time constant,
|
15820 |
|
|
and will have been substituted directly into all expressions that use it.
|
15821 |
|
|
C does not have such a concept, but C++ and other languages do. */
|
15822 |
|
|
if (!rtl && TREE_CODE (decl) == VAR_DECL && DECL_INITIAL (decl))
|
15823 |
|
|
rtl = rtl_for_decl_init (DECL_INITIAL (decl), TREE_TYPE (decl));
|
15824 |
|
|
|
15825 |
|
|
if (rtl)
|
15826 |
|
|
rtl = targetm.delegitimize_address (rtl);
|
15827 |
|
|
|
15828 |
|
|
/* If we don't look past the constant pool, we risk emitting a
|
15829 |
|
|
reference to a constant pool entry that isn't referenced from
|
15830 |
|
|
code, and thus is not emitted. */
|
15831 |
|
|
if (rtl)
|
15832 |
|
|
rtl = avoid_constant_pool_reference (rtl);
|
15833 |
|
|
|
15834 |
|
|
/* Try harder to get a rtl. If this symbol ends up not being emitted
|
15835 |
|
|
in the current CU, resolve_addr will remove the expression referencing
|
15836 |
|
|
it. */
|
15837 |
|
|
if (rtl == NULL_RTX
|
15838 |
|
|
&& TREE_CODE (decl) == VAR_DECL
|
15839 |
|
|
&& !DECL_EXTERNAL (decl)
|
15840 |
|
|
&& TREE_STATIC (decl)
|
15841 |
|
|
&& DECL_NAME (decl)
|
15842 |
|
|
&& !DECL_HARD_REGISTER (decl)
|
15843 |
|
|
&& DECL_MODE (decl) != VOIDmode)
|
15844 |
|
|
{
|
15845 |
|
|
rtl = make_decl_rtl_for_debug (decl);
|
15846 |
|
|
if (!MEM_P (rtl)
|
15847 |
|
|
|| GET_CODE (XEXP (rtl, 0)) != SYMBOL_REF
|
15848 |
|
|
|| SYMBOL_REF_DECL (XEXP (rtl, 0)) != decl)
|
15849 |
|
|
rtl = NULL_RTX;
|
15850 |
|
|
}
|
15851 |
|
|
|
15852 |
|
|
return rtl;
|
15853 |
|
|
}
|
15854 |
|
|
|
15855 |
|
|
/* Check whether decl is a Fortran COMMON symbol. If not, NULL_TREE is
|
15856 |
|
|
returned. If so, the decl for the COMMON block is returned, and the
|
15857 |
|
|
value is the offset into the common block for the symbol. */
|
15858 |
|
|
|
15859 |
|
|
static tree
|
15860 |
|
|
fortran_common (tree decl, HOST_WIDE_INT *value)
|
15861 |
|
|
{
|
15862 |
|
|
tree val_expr, cvar;
|
15863 |
|
|
enum machine_mode mode;
|
15864 |
|
|
HOST_WIDE_INT bitsize, bitpos;
|
15865 |
|
|
tree offset;
|
15866 |
|
|
int volatilep = 0, unsignedp = 0;
|
15867 |
|
|
|
15868 |
|
|
/* If the decl isn't a VAR_DECL, or if it isn't static, or if
|
15869 |
|
|
it does not have a value (the offset into the common area), or if it
|
15870 |
|
|
is thread local (as opposed to global) then it isn't common, and shouldn't
|
15871 |
|
|
be handled as such. */
|
15872 |
|
|
if (TREE_CODE (decl) != VAR_DECL
|
15873 |
|
|
|| !TREE_STATIC (decl)
|
15874 |
|
|
|| !DECL_HAS_VALUE_EXPR_P (decl)
|
15875 |
|
|
|| !is_fortran ())
|
15876 |
|
|
return NULL_TREE;
|
15877 |
|
|
|
15878 |
|
|
val_expr = DECL_VALUE_EXPR (decl);
|
15879 |
|
|
if (TREE_CODE (val_expr) != COMPONENT_REF)
|
15880 |
|
|
return NULL_TREE;
|
15881 |
|
|
|
15882 |
|
|
cvar = get_inner_reference (val_expr, &bitsize, &bitpos, &offset,
|
15883 |
|
|
&mode, &unsignedp, &volatilep, true);
|
15884 |
|
|
|
15885 |
|
|
if (cvar == NULL_TREE
|
15886 |
|
|
|| TREE_CODE (cvar) != VAR_DECL
|
15887 |
|
|
|| DECL_ARTIFICIAL (cvar)
|
15888 |
|
|
|| !TREE_PUBLIC (cvar))
|
15889 |
|
|
return NULL_TREE;
|
15890 |
|
|
|
15891 |
|
|
*value = 0;
|
15892 |
|
|
if (offset != NULL)
|
15893 |
|
|
{
|
15894 |
|
|
if (!host_integerp (offset, 0))
|
15895 |
|
|
return NULL_TREE;
|
15896 |
|
|
*value = tree_low_cst (offset, 0);
|
15897 |
|
|
}
|
15898 |
|
|
if (bitpos != 0)
|
15899 |
|
|
*value += bitpos / BITS_PER_UNIT;
|
15900 |
|
|
|
15901 |
|
|
return cvar;
|
15902 |
|
|
}
|
15903 |
|
|
|
15904 |
|
|
/* Generate *either* a DW_AT_location attribute or else a DW_AT_const_value
|
15905 |
|
|
data attribute for a variable or a parameter. We generate the
|
15906 |
|
|
DW_AT_const_value attribute only in those cases where the given variable
|
15907 |
|
|
or parameter does not have a true "location" either in memory or in a
|
15908 |
|
|
register. This can happen (for example) when a constant is passed as an
|
15909 |
|
|
actual argument in a call to an inline function. (It's possible that
|
15910 |
|
|
these things can crop up in other ways also.) Note that one type of
|
15911 |
|
|
constant value which can be passed into an inlined function is a constant
|
15912 |
|
|
pointer. This can happen for example if an actual argument in an inlined
|
15913 |
|
|
function call evaluates to a compile-time constant address. */
|
15914 |
|
|
|
15915 |
|
|
static bool
|
15916 |
|
|
add_location_or_const_value_attribute (dw_die_ref die, tree decl,
|
15917 |
|
|
enum dwarf_attribute attr)
|
15918 |
|
|
{
|
15919 |
|
|
rtx rtl;
|
15920 |
|
|
dw_loc_list_ref list;
|
15921 |
|
|
var_loc_list *loc_list;
|
15922 |
|
|
|
15923 |
|
|
if (TREE_CODE (decl) == ERROR_MARK)
|
15924 |
|
|
return false;
|
15925 |
|
|
|
15926 |
|
|
gcc_assert (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL
|
15927 |
|
|
|| TREE_CODE (decl) == RESULT_DECL);
|
15928 |
|
|
|
15929 |
|
|
/* Try to get some constant RTL for this decl, and use that as the value of
|
15930 |
|
|
the location. */
|
15931 |
|
|
|
15932 |
|
|
rtl = rtl_for_decl_location (decl);
|
15933 |
|
|
if (rtl && (CONSTANT_P (rtl) || GET_CODE (rtl) == CONST_STRING)
|
15934 |
|
|
&& add_const_value_attribute (die, rtl))
|
15935 |
|
|
return true;
|
15936 |
|
|
|
15937 |
|
|
/* See if we have single element location list that is equivalent to
|
15938 |
|
|
a constant value. That way we are better to use add_const_value_attribute
|
15939 |
|
|
rather than expanding constant value equivalent. */
|
15940 |
|
|
loc_list = lookup_decl_loc (decl);
|
15941 |
|
|
if (loc_list
|
15942 |
|
|
&& loc_list->first
|
15943 |
|
|
&& loc_list->first == loc_list->last
|
15944 |
|
|
&& NOTE_VAR_LOCATION (loc_list->first->var_loc_note)
|
15945 |
|
|
&& NOTE_VAR_LOCATION_LOC (loc_list->first->var_loc_note))
|
15946 |
|
|
{
|
15947 |
|
|
struct var_loc_node *node;
|
15948 |
|
|
|
15949 |
|
|
node = loc_list->first;
|
15950 |
|
|
rtl = NOTE_VAR_LOCATION_LOC (node->var_loc_note);
|
15951 |
|
|
if (GET_CODE (rtl) == EXPR_LIST)
|
15952 |
|
|
rtl = XEXP (rtl, 0);
|
15953 |
|
|
if ((CONSTANT_P (rtl) || GET_CODE (rtl) == CONST_STRING)
|
15954 |
|
|
&& add_const_value_attribute (die, rtl))
|
15955 |
|
|
return true;
|
15956 |
|
|
}
|
15957 |
|
|
list = loc_list_from_tree (decl, decl_by_reference_p (decl) ? 0 : 2);
|
15958 |
|
|
if (list)
|
15959 |
|
|
{
|
15960 |
|
|
add_AT_location_description (die, attr, list);
|
15961 |
|
|
return true;
|
15962 |
|
|
}
|
15963 |
|
|
/* None of that worked, so it must not really have a location;
|
15964 |
|
|
try adding a constant value attribute from the DECL_INITIAL. */
|
15965 |
|
|
return tree_add_const_value_attribute_for_decl (die, decl);
|
15966 |
|
|
}
|
15967 |
|
|
|
15968 |
|
|
/* Add VARIABLE and DIE into deferred locations list. */
|
15969 |
|
|
|
15970 |
|
|
static void
|
15971 |
|
|
defer_location (tree variable, dw_die_ref die)
|
15972 |
|
|
{
|
15973 |
|
|
deferred_locations entry;
|
15974 |
|
|
entry.variable = variable;
|
15975 |
|
|
entry.die = die;
|
15976 |
|
|
VEC_safe_push (deferred_locations, gc, deferred_locations_list, &entry);
|
15977 |
|
|
}
|
15978 |
|
|
|
15979 |
|
|
/* Helper function for tree_add_const_value_attribute. Natively encode
|
15980 |
|
|
initializer INIT into an array. Return true if successful. */
|
15981 |
|
|
|
15982 |
|
|
static bool
|
15983 |
|
|
native_encode_initializer (tree init, unsigned char *array, int size)
|
15984 |
|
|
{
|
15985 |
|
|
tree type;
|
15986 |
|
|
|
15987 |
|
|
if (init == NULL_TREE)
|
15988 |
|
|
return false;
|
15989 |
|
|
|
15990 |
|
|
STRIP_NOPS (init);
|
15991 |
|
|
switch (TREE_CODE (init))
|
15992 |
|
|
{
|
15993 |
|
|
case STRING_CST:
|
15994 |
|
|
type = TREE_TYPE (init);
|
15995 |
|
|
if (TREE_CODE (type) == ARRAY_TYPE)
|
15996 |
|
|
{
|
15997 |
|
|
tree enttype = TREE_TYPE (type);
|
15998 |
|
|
enum machine_mode mode = TYPE_MODE (enttype);
|
15999 |
|
|
|
16000 |
|
|
if (GET_MODE_CLASS (mode) != MODE_INT || GET_MODE_SIZE (mode) != 1)
|
16001 |
|
|
return false;
|
16002 |
|
|
if (int_size_in_bytes (type) != size)
|
16003 |
|
|
return false;
|
16004 |
|
|
if (size > TREE_STRING_LENGTH (init))
|
16005 |
|
|
{
|
16006 |
|
|
memcpy (array, TREE_STRING_POINTER (init),
|
16007 |
|
|
TREE_STRING_LENGTH (init));
|
16008 |
|
|
memset (array + TREE_STRING_LENGTH (init),
|
16009 |
|
|
'\0', size - TREE_STRING_LENGTH (init));
|
16010 |
|
|
}
|
16011 |
|
|
else
|
16012 |
|
|
memcpy (array, TREE_STRING_POINTER (init), size);
|
16013 |
|
|
return true;
|
16014 |
|
|
}
|
16015 |
|
|
return false;
|
16016 |
|
|
case CONSTRUCTOR:
|
16017 |
|
|
type = TREE_TYPE (init);
|
16018 |
|
|
if (int_size_in_bytes (type) != size)
|
16019 |
|
|
return false;
|
16020 |
|
|
if (TREE_CODE (type) == ARRAY_TYPE)
|
16021 |
|
|
{
|
16022 |
|
|
HOST_WIDE_INT min_index;
|
16023 |
|
|
unsigned HOST_WIDE_INT cnt;
|
16024 |
|
|
int curpos = 0, fieldsize;
|
16025 |
|
|
constructor_elt *ce;
|
16026 |
|
|
|
16027 |
|
|
if (TYPE_DOMAIN (type) == NULL_TREE
|
16028 |
|
|
|| !host_integerp (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), 0))
|
16029 |
|
|
return false;
|
16030 |
|
|
|
16031 |
|
|
fieldsize = int_size_in_bytes (TREE_TYPE (type));
|
16032 |
|
|
if (fieldsize <= 0)
|
16033 |
|
|
return false;
|
16034 |
|
|
|
16035 |
|
|
min_index = tree_low_cst (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), 0);
|
16036 |
|
|
memset (array, '\0', size);
|
16037 |
|
|
for (cnt = 0;
|
16038 |
|
|
VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (init), cnt, ce);
|
16039 |
|
|
cnt++)
|
16040 |
|
|
{
|
16041 |
|
|
tree val = ce->value;
|
16042 |
|
|
tree index = ce->index;
|
16043 |
|
|
int pos = curpos;
|
16044 |
|
|
if (index && TREE_CODE (index) == RANGE_EXPR)
|
16045 |
|
|
pos = (tree_low_cst (TREE_OPERAND (index, 0), 0) - min_index)
|
16046 |
|
|
* fieldsize;
|
16047 |
|
|
else if (index)
|
16048 |
|
|
pos = (tree_low_cst (index, 0) - min_index) * fieldsize;
|
16049 |
|
|
|
16050 |
|
|
if (val)
|
16051 |
|
|
{
|
16052 |
|
|
STRIP_NOPS (val);
|
16053 |
|
|
if (!native_encode_initializer (val, array + pos, fieldsize))
|
16054 |
|
|
return false;
|
16055 |
|
|
}
|
16056 |
|
|
curpos = pos + fieldsize;
|
16057 |
|
|
if (index && TREE_CODE (index) == RANGE_EXPR)
|
16058 |
|
|
{
|
16059 |
|
|
int count = tree_low_cst (TREE_OPERAND (index, 1), 0)
|
16060 |
|
|
- tree_low_cst (TREE_OPERAND (index, 0), 0);
|
16061 |
|
|
while (count > 0)
|
16062 |
|
|
{
|
16063 |
|
|
if (val)
|
16064 |
|
|
memcpy (array + curpos, array + pos, fieldsize);
|
16065 |
|
|
curpos += fieldsize;
|
16066 |
|
|
}
|
16067 |
|
|
}
|
16068 |
|
|
gcc_assert (curpos <= size);
|
16069 |
|
|
}
|
16070 |
|
|
return true;
|
16071 |
|
|
}
|
16072 |
|
|
else if (TREE_CODE (type) == RECORD_TYPE
|
16073 |
|
|
|| TREE_CODE (type) == UNION_TYPE)
|
16074 |
|
|
{
|
16075 |
|
|
tree field = NULL_TREE;
|
16076 |
|
|
unsigned HOST_WIDE_INT cnt;
|
16077 |
|
|
constructor_elt *ce;
|
16078 |
|
|
|
16079 |
|
|
if (int_size_in_bytes (type) != size)
|
16080 |
|
|
return false;
|
16081 |
|
|
|
16082 |
|
|
if (TREE_CODE (type) == RECORD_TYPE)
|
16083 |
|
|
field = TYPE_FIELDS (type);
|
16084 |
|
|
|
16085 |
|
|
for (cnt = 0;
|
16086 |
|
|
VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (init), cnt, ce);
|
16087 |
|
|
cnt++, field = field ? TREE_CHAIN (field) : 0)
|
16088 |
|
|
{
|
16089 |
|
|
tree val = ce->value;
|
16090 |
|
|
int pos, fieldsize;
|
16091 |
|
|
|
16092 |
|
|
if (ce->index != 0)
|
16093 |
|
|
field = ce->index;
|
16094 |
|
|
|
16095 |
|
|
if (val)
|
16096 |
|
|
STRIP_NOPS (val);
|
16097 |
|
|
|
16098 |
|
|
if (field == NULL_TREE || DECL_BIT_FIELD (field))
|
16099 |
|
|
return false;
|
16100 |
|
|
|
16101 |
|
|
if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
|
16102 |
|
|
&& TYPE_DOMAIN (TREE_TYPE (field))
|
16103 |
|
|
&& ! TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (field))))
|
16104 |
|
|
return false;
|
16105 |
|
|
else if (DECL_SIZE_UNIT (field) == NULL_TREE
|
16106 |
|
|
|| !host_integerp (DECL_SIZE_UNIT (field), 0))
|
16107 |
|
|
return false;
|
16108 |
|
|
fieldsize = tree_low_cst (DECL_SIZE_UNIT (field), 0);
|
16109 |
|
|
pos = int_byte_position (field);
|
16110 |
|
|
gcc_assert (pos + fieldsize <= size);
|
16111 |
|
|
if (val
|
16112 |
|
|
&& !native_encode_initializer (val, array + pos, fieldsize))
|
16113 |
|
|
return false;
|
16114 |
|
|
}
|
16115 |
|
|
return true;
|
16116 |
|
|
}
|
16117 |
|
|
return false;
|
16118 |
|
|
case VIEW_CONVERT_EXPR:
|
16119 |
|
|
case NON_LVALUE_EXPR:
|
16120 |
|
|
return native_encode_initializer (TREE_OPERAND (init, 0), array, size);
|
16121 |
|
|
default:
|
16122 |
|
|
return native_encode_expr (init, array, size) == size;
|
16123 |
|
|
}
|
16124 |
|
|
}
|
16125 |
|
|
|
16126 |
|
|
/* Attach a DW_AT_const_value attribute to DIE. The value of the
|
16127 |
|
|
attribute is the const value T. */
|
16128 |
|
|
|
16129 |
|
|
static bool
|
16130 |
|
|
tree_add_const_value_attribute (dw_die_ref die, tree t)
|
16131 |
|
|
{
|
16132 |
|
|
tree init;
|
16133 |
|
|
tree type = TREE_TYPE (t);
|
16134 |
|
|
rtx rtl;
|
16135 |
|
|
|
16136 |
|
|
if (!t || !TREE_TYPE (t) || TREE_TYPE (t) == error_mark_node)
|
16137 |
|
|
return false;
|
16138 |
|
|
|
16139 |
|
|
init = t;
|
16140 |
|
|
gcc_assert (!DECL_P (init));
|
16141 |
|
|
|
16142 |
|
|
rtl = rtl_for_decl_init (init, type);
|
16143 |
|
|
if (rtl)
|
16144 |
|
|
return add_const_value_attribute (die, rtl);
|
16145 |
|
|
/* If the host and target are sane, try harder. */
|
16146 |
|
|
else if (CHAR_BIT == 8 && BITS_PER_UNIT == 8
|
16147 |
|
|
&& initializer_constant_valid_p (init, type))
|
16148 |
|
|
{
|
16149 |
|
|
HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (init));
|
16150 |
|
|
if (size > 0 && (int) size == size)
|
16151 |
|
|
{
|
16152 |
|
|
unsigned char *array = GGC_CNEWVEC (unsigned char, size);
|
16153 |
|
|
|
16154 |
|
|
if (native_encode_initializer (init, array, size))
|
16155 |
|
|
{
|
16156 |
|
|
add_AT_vec (die, DW_AT_const_value, size, 1, array);
|
16157 |
|
|
return true;
|
16158 |
|
|
}
|
16159 |
|
|
}
|
16160 |
|
|
}
|
16161 |
|
|
return false;
|
16162 |
|
|
}
|
16163 |
|
|
|
16164 |
|
|
/* Attach a DW_AT_const_value attribute to VAR_DIE. The value of the
|
16165 |
|
|
attribute is the const value of T, where T is an integral constant
|
16166 |
|
|
variable with static storage duration
|
16167 |
|
|
(so it can't be a PARM_DECL or a RESULT_DECL). */
|
16168 |
|
|
|
16169 |
|
|
static bool
|
16170 |
|
|
tree_add_const_value_attribute_for_decl (dw_die_ref var_die, tree decl)
|
16171 |
|
|
{
|
16172 |
|
|
|
16173 |
|
|
if (!decl
|
16174 |
|
|
|| (TREE_CODE (decl) != VAR_DECL
|
16175 |
|
|
&& TREE_CODE (decl) != CONST_DECL))
|
16176 |
|
|
return false;
|
16177 |
|
|
|
16178 |
|
|
if (TREE_READONLY (decl)
|
16179 |
|
|
&& ! TREE_THIS_VOLATILE (decl)
|
16180 |
|
|
&& DECL_INITIAL (decl))
|
16181 |
|
|
/* OK */;
|
16182 |
|
|
else
|
16183 |
|
|
return false;
|
16184 |
|
|
|
16185 |
|
|
/* Don't add DW_AT_const_value if abstract origin already has one. */
|
16186 |
|
|
if (get_AT (var_die, DW_AT_const_value))
|
16187 |
|
|
return false;
|
16188 |
|
|
|
16189 |
|
|
return tree_add_const_value_attribute (var_die, DECL_INITIAL (decl));
|
16190 |
|
|
}
|
16191 |
|
|
|
16192 |
|
|
/* Convert the CFI instructions for the current function into a
|
16193 |
|
|
location list. This is used for DW_AT_frame_base when we targeting
|
16194 |
|
|
a dwarf2 consumer that does not support the dwarf3
|
16195 |
|
|
DW_OP_call_frame_cfa. OFFSET is a constant to be added to all CFA
|
16196 |
|
|
expressions. */
|
16197 |
|
|
|
16198 |
|
|
static dw_loc_list_ref
|
16199 |
|
|
convert_cfa_to_fb_loc_list (HOST_WIDE_INT offset)
|
16200 |
|
|
{
|
16201 |
|
|
dw_fde_ref fde;
|
16202 |
|
|
dw_loc_list_ref list, *list_tail;
|
16203 |
|
|
dw_cfi_ref cfi;
|
16204 |
|
|
dw_cfa_location last_cfa, next_cfa;
|
16205 |
|
|
const char *start_label, *last_label, *section;
|
16206 |
|
|
dw_cfa_location remember;
|
16207 |
|
|
|
16208 |
|
|
fde = current_fde ();
|
16209 |
|
|
gcc_assert (fde != NULL);
|
16210 |
|
|
|
16211 |
|
|
section = secname_for_decl (current_function_decl);
|
16212 |
|
|
list_tail = &list;
|
16213 |
|
|
list = NULL;
|
16214 |
|
|
|
16215 |
|
|
memset (&next_cfa, 0, sizeof (next_cfa));
|
16216 |
|
|
next_cfa.reg = INVALID_REGNUM;
|
16217 |
|
|
remember = next_cfa;
|
16218 |
|
|
|
16219 |
|
|
start_label = fde->dw_fde_begin;
|
16220 |
|
|
|
16221 |
|
|
/* ??? Bald assumption that the CIE opcode list does not contain
|
16222 |
|
|
advance opcodes. */
|
16223 |
|
|
for (cfi = cie_cfi_head; cfi; cfi = cfi->dw_cfi_next)
|
16224 |
|
|
lookup_cfa_1 (cfi, &next_cfa, &remember);
|
16225 |
|
|
|
16226 |
|
|
last_cfa = next_cfa;
|
16227 |
|
|
last_label = start_label;
|
16228 |
|
|
|
16229 |
|
|
for (cfi = fde->dw_fde_cfi; cfi; cfi = cfi->dw_cfi_next)
|
16230 |
|
|
switch (cfi->dw_cfi_opc)
|
16231 |
|
|
{
|
16232 |
|
|
case DW_CFA_set_loc:
|
16233 |
|
|
case DW_CFA_advance_loc1:
|
16234 |
|
|
case DW_CFA_advance_loc2:
|
16235 |
|
|
case DW_CFA_advance_loc4:
|
16236 |
|
|
if (!cfa_equal_p (&last_cfa, &next_cfa))
|
16237 |
|
|
{
|
16238 |
|
|
*list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset),
|
16239 |
|
|
start_label, last_label, section);
|
16240 |
|
|
|
16241 |
|
|
list_tail = &(*list_tail)->dw_loc_next;
|
16242 |
|
|
last_cfa = next_cfa;
|
16243 |
|
|
start_label = last_label;
|
16244 |
|
|
}
|
16245 |
|
|
last_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
|
16246 |
|
|
break;
|
16247 |
|
|
|
16248 |
|
|
case DW_CFA_advance_loc:
|
16249 |
|
|
/* The encoding is complex enough that we should never emit this. */
|
16250 |
|
|
gcc_unreachable ();
|
16251 |
|
|
|
16252 |
|
|
default:
|
16253 |
|
|
lookup_cfa_1 (cfi, &next_cfa, &remember);
|
16254 |
|
|
break;
|
16255 |
|
|
}
|
16256 |
|
|
|
16257 |
|
|
if (!cfa_equal_p (&last_cfa, &next_cfa))
|
16258 |
|
|
{
|
16259 |
|
|
*list_tail = new_loc_list (build_cfa_loc (&last_cfa, offset),
|
16260 |
|
|
start_label, last_label, section);
|
16261 |
|
|
list_tail = &(*list_tail)->dw_loc_next;
|
16262 |
|
|
start_label = last_label;
|
16263 |
|
|
}
|
16264 |
|
|
|
16265 |
|
|
*list_tail = new_loc_list (build_cfa_loc (&next_cfa, offset),
|
16266 |
|
|
start_label, fde->dw_fde_end, section);
|
16267 |
|
|
|
16268 |
|
|
if (list && list->dw_loc_next)
|
16269 |
|
|
gen_llsym (list);
|
16270 |
|
|
|
16271 |
|
|
return list;
|
16272 |
|
|
}
|
16273 |
|
|
|
16274 |
|
|
/* Compute a displacement from the "steady-state frame pointer" to the
|
16275 |
|
|
frame base (often the same as the CFA), and store it in
|
16276 |
|
|
frame_pointer_fb_offset. OFFSET is added to the displacement
|
16277 |
|
|
before the latter is negated. */
|
16278 |
|
|
|
16279 |
|
|
static void
|
16280 |
|
|
compute_frame_pointer_to_fb_displacement (HOST_WIDE_INT offset)
|
16281 |
|
|
{
|
16282 |
|
|
rtx reg, elim;
|
16283 |
|
|
|
16284 |
|
|
#ifdef FRAME_POINTER_CFA_OFFSET
|
16285 |
|
|
reg = frame_pointer_rtx;
|
16286 |
|
|
offset += FRAME_POINTER_CFA_OFFSET (current_function_decl);
|
16287 |
|
|
#else
|
16288 |
|
|
reg = arg_pointer_rtx;
|
16289 |
|
|
offset += ARG_POINTER_CFA_OFFSET (current_function_decl);
|
16290 |
|
|
#endif
|
16291 |
|
|
|
16292 |
|
|
elim = eliminate_regs (reg, VOIDmode, NULL_RTX);
|
16293 |
|
|
if (GET_CODE (elim) == PLUS)
|
16294 |
|
|
{
|
16295 |
|
|
offset += INTVAL (XEXP (elim, 1));
|
16296 |
|
|
elim = XEXP (elim, 0);
|
16297 |
|
|
}
|
16298 |
|
|
|
16299 |
|
|
gcc_assert ((SUPPORTS_STACK_ALIGNMENT
|
16300 |
|
|
&& (elim == hard_frame_pointer_rtx
|
16301 |
|
|
|| elim == stack_pointer_rtx))
|
16302 |
|
|
|| elim == (frame_pointer_needed
|
16303 |
|
|
? hard_frame_pointer_rtx
|
16304 |
|
|
: stack_pointer_rtx));
|
16305 |
|
|
|
16306 |
|
|
frame_pointer_fb_offset = -offset;
|
16307 |
|
|
}
|
16308 |
|
|
|
16309 |
|
|
/* Generate a DW_AT_name attribute given some string value to be included as
|
16310 |
|
|
the value of the attribute. */
|
16311 |
|
|
|
16312 |
|
|
static void
|
16313 |
|
|
add_name_attribute (dw_die_ref die, const char *name_string)
|
16314 |
|
|
{
|
16315 |
|
|
if (name_string != NULL && *name_string != 0)
|
16316 |
|
|
{
|
16317 |
|
|
if (demangle_name_func)
|
16318 |
|
|
name_string = (*demangle_name_func) (name_string);
|
16319 |
|
|
|
16320 |
|
|
add_AT_string (die, DW_AT_name, name_string);
|
16321 |
|
|
}
|
16322 |
|
|
}
|
16323 |
|
|
|
16324 |
|
|
/* Generate a DW_AT_comp_dir attribute for DIE. */
|
16325 |
|
|
|
16326 |
|
|
static void
|
16327 |
|
|
add_comp_dir_attribute (dw_die_ref die)
|
16328 |
|
|
{
|
16329 |
|
|
const char *wd = get_src_pwd ();
|
16330 |
|
|
char *wd1;
|
16331 |
|
|
|
16332 |
|
|
if (wd == NULL)
|
16333 |
|
|
return;
|
16334 |
|
|
|
16335 |
|
|
if (DWARF2_DIR_SHOULD_END_WITH_SEPARATOR)
|
16336 |
|
|
{
|
16337 |
|
|
int wdlen;
|
16338 |
|
|
|
16339 |
|
|
wdlen = strlen (wd);
|
16340 |
|
|
wd1 = GGC_NEWVEC (char, wdlen + 2);
|
16341 |
|
|
strcpy (wd1, wd);
|
16342 |
|
|
wd1 [wdlen] = DIR_SEPARATOR;
|
16343 |
|
|
wd1 [wdlen + 1] = 0;
|
16344 |
|
|
wd = wd1;
|
16345 |
|
|
}
|
16346 |
|
|
|
16347 |
|
|
add_AT_string (die, DW_AT_comp_dir, remap_debug_filename (wd));
|
16348 |
|
|
}
|
16349 |
|
|
|
16350 |
|
|
/* Return the default for DW_AT_lower_bound, or -1 if there is not any
|
16351 |
|
|
default. */
|
16352 |
|
|
|
16353 |
|
|
static int
|
16354 |
|
|
lower_bound_default (void)
|
16355 |
|
|
{
|
16356 |
|
|
switch (get_AT_unsigned (comp_unit_die, DW_AT_language))
|
16357 |
|
|
{
|
16358 |
|
|
case DW_LANG_C:
|
16359 |
|
|
case DW_LANG_C89:
|
16360 |
|
|
case DW_LANG_C99:
|
16361 |
|
|
case DW_LANG_C_plus_plus:
|
16362 |
|
|
case DW_LANG_ObjC:
|
16363 |
|
|
case DW_LANG_ObjC_plus_plus:
|
16364 |
|
|
case DW_LANG_Java:
|
16365 |
|
|
return 0;
|
16366 |
|
|
case DW_LANG_Fortran77:
|
16367 |
|
|
case DW_LANG_Fortran90:
|
16368 |
|
|
case DW_LANG_Fortran95:
|
16369 |
|
|
return 1;
|
16370 |
|
|
case DW_LANG_UPC:
|
16371 |
|
|
case DW_LANG_D:
|
16372 |
|
|
return dwarf_version >= 4 ? 0 : -1;
|
16373 |
|
|
case DW_LANG_Ada95:
|
16374 |
|
|
case DW_LANG_Ada83:
|
16375 |
|
|
case DW_LANG_Cobol74:
|
16376 |
|
|
case DW_LANG_Cobol85:
|
16377 |
|
|
case DW_LANG_Pascal83:
|
16378 |
|
|
case DW_LANG_Modula2:
|
16379 |
|
|
case DW_LANG_PLI:
|
16380 |
|
|
return dwarf_version >= 4 ? 1 : -1;
|
16381 |
|
|
default:
|
16382 |
|
|
return -1;
|
16383 |
|
|
}
|
16384 |
|
|
}
|
16385 |
|
|
|
16386 |
|
|
/* Given a tree node describing an array bound (either lower or upper) output
|
16387 |
|
|
a representation for that bound. */
|
16388 |
|
|
|
16389 |
|
|
static void
|
16390 |
|
|
add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, tree bound)
|
16391 |
|
|
{
|
16392 |
|
|
int want_address = 2;
|
16393 |
|
|
|
16394 |
|
|
switch (TREE_CODE (bound))
|
16395 |
|
|
{
|
16396 |
|
|
case ERROR_MARK:
|
16397 |
|
|
return;
|
16398 |
|
|
|
16399 |
|
|
/* All fixed-bounds are represented by INTEGER_CST nodes. */
|
16400 |
|
|
case INTEGER_CST:
|
16401 |
|
|
{
|
16402 |
|
|
unsigned int prec = simple_type_size_in_bits (TREE_TYPE (bound));
|
16403 |
|
|
int dflt;
|
16404 |
|
|
|
16405 |
|
|
/* Use the default if possible. */
|
16406 |
|
|
if (bound_attr == DW_AT_lower_bound
|
16407 |
|
|
&& host_integerp (bound, 0)
|
16408 |
|
|
&& (dflt = lower_bound_default ()) != -1
|
16409 |
|
|
&& tree_low_cst (bound, 0) == dflt)
|
16410 |
|
|
;
|
16411 |
|
|
|
16412 |
|
|
/* Otherwise represent the bound as an unsigned value with the
|
16413 |
|
|
precision of its type. The precision and signedness of the
|
16414 |
|
|
type will be necessary to re-interpret it unambiguously. */
|
16415 |
|
|
else if (prec < HOST_BITS_PER_WIDE_INT)
|
16416 |
|
|
{
|
16417 |
|
|
unsigned HOST_WIDE_INT mask
|
16418 |
|
|
= ((unsigned HOST_WIDE_INT) 1 << prec) - 1;
|
16419 |
|
|
add_AT_unsigned (subrange_die, bound_attr,
|
16420 |
|
|
TREE_INT_CST_LOW (bound) & mask);
|
16421 |
|
|
}
|
16422 |
|
|
else if (prec == HOST_BITS_PER_WIDE_INT
|
16423 |
|
|
|| TREE_INT_CST_HIGH (bound) == 0)
|
16424 |
|
|
add_AT_unsigned (subrange_die, bound_attr,
|
16425 |
|
|
TREE_INT_CST_LOW (bound));
|
16426 |
|
|
else
|
16427 |
|
|
add_AT_double (subrange_die, bound_attr, TREE_INT_CST_HIGH (bound),
|
16428 |
|
|
TREE_INT_CST_LOW (bound));
|
16429 |
|
|
}
|
16430 |
|
|
break;
|
16431 |
|
|
|
16432 |
|
|
CASE_CONVERT:
|
16433 |
|
|
case VIEW_CONVERT_EXPR:
|
16434 |
|
|
add_bound_info (subrange_die, bound_attr, TREE_OPERAND (bound, 0));
|
16435 |
|
|
break;
|
16436 |
|
|
|
16437 |
|
|
case SAVE_EXPR:
|
16438 |
|
|
break;
|
16439 |
|
|
|
16440 |
|
|
case VAR_DECL:
|
16441 |
|
|
case PARM_DECL:
|
16442 |
|
|
case RESULT_DECL:
|
16443 |
|
|
{
|
16444 |
|
|
dw_die_ref decl_die = lookup_decl_die (bound);
|
16445 |
|
|
|
16446 |
|
|
/* ??? Can this happen, or should the variable have been bound
|
16447 |
|
|
first? Probably it can, since I imagine that we try to create
|
16448 |
|
|
the types of parameters in the order in which they exist in
|
16449 |
|
|
the list, and won't have created a forward reference to a
|
16450 |
|
|
later parameter. */
|
16451 |
|
|
if (decl_die != NULL)
|
16452 |
|
|
{
|
16453 |
|
|
add_AT_die_ref (subrange_die, bound_attr, decl_die);
|
16454 |
|
|
break;
|
16455 |
|
|
}
|
16456 |
|
|
want_address = 0;
|
16457 |
|
|
}
|
16458 |
|
|
/* FALLTHRU */
|
16459 |
|
|
|
16460 |
|
|
default:
|
16461 |
|
|
{
|
16462 |
|
|
/* Otherwise try to create a stack operation procedure to
|
16463 |
|
|
evaluate the value of the array bound. */
|
16464 |
|
|
|
16465 |
|
|
dw_die_ref ctx, decl_die;
|
16466 |
|
|
dw_loc_list_ref list;
|
16467 |
|
|
|
16468 |
|
|
list = loc_list_from_tree (bound, want_address);
|
16469 |
|
|
if (list == NULL)
|
16470 |
|
|
break;
|
16471 |
|
|
|
16472 |
|
|
if (single_element_loc_list_p (list))
|
16473 |
|
|
{
|
16474 |
|
|
add_AT_loc (subrange_die, bound_attr, list->expr);
|
16475 |
|
|
break;
|
16476 |
|
|
}
|
16477 |
|
|
|
16478 |
|
|
if (current_function_decl == 0)
|
16479 |
|
|
ctx = comp_unit_die;
|
16480 |
|
|
else
|
16481 |
|
|
ctx = lookup_decl_die (current_function_decl);
|
16482 |
|
|
|
16483 |
|
|
decl_die = new_die (DW_TAG_variable, ctx, bound);
|
16484 |
|
|
add_AT_flag (decl_die, DW_AT_artificial, 1);
|
16485 |
|
|
add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx);
|
16486 |
|
|
add_AT_location_description (decl_die, DW_AT_location, list);
|
16487 |
|
|
add_AT_die_ref (subrange_die, bound_attr, decl_die);
|
16488 |
|
|
break;
|
16489 |
|
|
}
|
16490 |
|
|
}
|
16491 |
|
|
}
|
16492 |
|
|
|
16493 |
|
|
/* Add subscript info to TYPE_DIE, describing an array TYPE, collapsing
|
16494 |
|
|
possibly nested array subscripts in a flat sequence if COLLAPSE_P is true.
|
16495 |
|
|
Note that the block of subscript information for an array type also
|
16496 |
|
|
includes information about the element type of the given array type. */
|
16497 |
|
|
|
16498 |
|
|
static void
|
16499 |
|
|
add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p)
|
16500 |
|
|
{
|
16501 |
|
|
unsigned dimension_number;
|
16502 |
|
|
tree lower, upper;
|
16503 |
|
|
dw_die_ref subrange_die;
|
16504 |
|
|
|
16505 |
|
|
for (dimension_number = 0;
|
16506 |
|
|
TREE_CODE (type) == ARRAY_TYPE && (dimension_number == 0 || collapse_p);
|
16507 |
|
|
type = TREE_TYPE (type), dimension_number++)
|
16508 |
|
|
{
|
16509 |
|
|
tree domain = TYPE_DOMAIN (type);
|
16510 |
|
|
|
16511 |
|
|
if (TYPE_STRING_FLAG (type) && is_fortran () && dimension_number > 0)
|
16512 |
|
|
break;
|
16513 |
|
|
|
16514 |
|
|
/* Arrays come in three flavors: Unspecified bounds, fixed bounds,
|
16515 |
|
|
and (in GNU C only) variable bounds. Handle all three forms
|
16516 |
|
|
here. */
|
16517 |
|
|
subrange_die = new_die (DW_TAG_subrange_type, type_die, NULL);
|
16518 |
|
|
if (domain)
|
16519 |
|
|
{
|
16520 |
|
|
/* We have an array type with specified bounds. */
|
16521 |
|
|
lower = TYPE_MIN_VALUE (domain);
|
16522 |
|
|
upper = TYPE_MAX_VALUE (domain);
|
16523 |
|
|
|
16524 |
|
|
/* Define the index type. */
|
16525 |
|
|
if (TREE_TYPE (domain))
|
16526 |
|
|
{
|
16527 |
|
|
/* ??? This is probably an Ada unnamed subrange type. Ignore the
|
16528 |
|
|
TREE_TYPE field. We can't emit debug info for this
|
16529 |
|
|
because it is an unnamed integral type. */
|
16530 |
|
|
if (TREE_CODE (domain) == INTEGER_TYPE
|
16531 |
|
|
&& TYPE_NAME (domain) == NULL_TREE
|
16532 |
|
|
&& TREE_CODE (TREE_TYPE (domain)) == INTEGER_TYPE
|
16533 |
|
|
&& TYPE_NAME (TREE_TYPE (domain)) == NULL_TREE)
|
16534 |
|
|
;
|
16535 |
|
|
else
|
16536 |
|
|
add_type_attribute (subrange_die, TREE_TYPE (domain), 0, 0,
|
16537 |
|
|
type_die);
|
16538 |
|
|
}
|
16539 |
|
|
|
16540 |
|
|
/* ??? If upper is NULL, the array has unspecified length,
|
16541 |
|
|
but it does have a lower bound. This happens with Fortran
|
16542 |
|
|
dimension arr(N:*)
|
16543 |
|
|
Since the debugger is definitely going to need to know N
|
16544 |
|
|
to produce useful results, go ahead and output the lower
|
16545 |
|
|
bound solo, and hope the debugger can cope. */
|
16546 |
|
|
|
16547 |
|
|
add_bound_info (subrange_die, DW_AT_lower_bound, lower);
|
16548 |
|
|
if (upper)
|
16549 |
|
|
add_bound_info (subrange_die, DW_AT_upper_bound, upper);
|
16550 |
|
|
}
|
16551 |
|
|
|
16552 |
|
|
/* Otherwise we have an array type with an unspecified length. The
|
16553 |
|
|
DWARF-2 spec does not say how to handle this; let's just leave out the
|
16554 |
|
|
bounds. */
|
16555 |
|
|
}
|
16556 |
|
|
}
|
16557 |
|
|
|
16558 |
|
|
static void
|
16559 |
|
|
add_byte_size_attribute (dw_die_ref die, tree tree_node)
|
16560 |
|
|
{
|
16561 |
|
|
unsigned size;
|
16562 |
|
|
|
16563 |
|
|
switch (TREE_CODE (tree_node))
|
16564 |
|
|
{
|
16565 |
|
|
case ERROR_MARK:
|
16566 |
|
|
size = 0;
|
16567 |
|
|
break;
|
16568 |
|
|
case ENUMERAL_TYPE:
|
16569 |
|
|
case RECORD_TYPE:
|
16570 |
|
|
case UNION_TYPE:
|
16571 |
|
|
case QUAL_UNION_TYPE:
|
16572 |
|
|
size = int_size_in_bytes (tree_node);
|
16573 |
|
|
break;
|
16574 |
|
|
case FIELD_DECL:
|
16575 |
|
|
/* For a data member of a struct or union, the DW_AT_byte_size is
|
16576 |
|
|
generally given as the number of bytes normally allocated for an
|
16577 |
|
|
object of the *declared* type of the member itself. This is true
|
16578 |
|
|
even for bit-fields. */
|
16579 |
|
|
size = simple_type_size_in_bits (field_type (tree_node)) / BITS_PER_UNIT;
|
16580 |
|
|
break;
|
16581 |
|
|
default:
|
16582 |
|
|
gcc_unreachable ();
|
16583 |
|
|
}
|
16584 |
|
|
|
16585 |
|
|
/* Note that `size' might be -1 when we get to this point. If it is, that
|
16586 |
|
|
indicates that the byte size of the entity in question is variable. We
|
16587 |
|
|
have no good way of expressing this fact in Dwarf at the present time,
|
16588 |
|
|
so just let the -1 pass on through. */
|
16589 |
|
|
add_AT_unsigned (die, DW_AT_byte_size, size);
|
16590 |
|
|
}
|
16591 |
|
|
|
16592 |
|
|
/* For a FIELD_DECL node which represents a bit-field, output an attribute
|
16593 |
|
|
which specifies the distance in bits from the highest order bit of the
|
16594 |
|
|
"containing object" for the bit-field to the highest order bit of the
|
16595 |
|
|
bit-field itself.
|
16596 |
|
|
|
16597 |
|
|
For any given bit-field, the "containing object" is a hypothetical object
|
16598 |
|
|
(of some integral or enum type) within which the given bit-field lives. The
|
16599 |
|
|
type of this hypothetical "containing object" is always the same as the
|
16600 |
|
|
declared type of the individual bit-field itself. The determination of the
|
16601 |
|
|
exact location of the "containing object" for a bit-field is rather
|
16602 |
|
|
complicated. It's handled by the `field_byte_offset' function (above).
|
16603 |
|
|
|
16604 |
|
|
Note that it is the size (in bytes) of the hypothetical "containing object"
|
16605 |
|
|
which will be given in the DW_AT_byte_size attribute for this bit-field.
|
16606 |
|
|
(See `byte_size_attribute' above). */
|
16607 |
|
|
|
16608 |
|
|
static inline void
|
16609 |
|
|
add_bit_offset_attribute (dw_die_ref die, tree decl)
|
16610 |
|
|
{
|
16611 |
|
|
HOST_WIDE_INT object_offset_in_bytes = field_byte_offset (decl);
|
16612 |
|
|
tree type = DECL_BIT_FIELD_TYPE (decl);
|
16613 |
|
|
HOST_WIDE_INT bitpos_int;
|
16614 |
|
|
HOST_WIDE_INT highest_order_object_bit_offset;
|
16615 |
|
|
HOST_WIDE_INT highest_order_field_bit_offset;
|
16616 |
|
|
HOST_WIDE_INT unsigned bit_offset;
|
16617 |
|
|
|
16618 |
|
|
/* Must be a field and a bit field. */
|
16619 |
|
|
gcc_assert (type && TREE_CODE (decl) == FIELD_DECL);
|
16620 |
|
|
|
16621 |
|
|
/* We can't yet handle bit-fields whose offsets are variable, so if we
|
16622 |
|
|
encounter such things, just return without generating any attribute
|
16623 |
|
|
whatsoever. Likewise for variable or too large size. */
|
16624 |
|
|
if (! host_integerp (bit_position (decl), 0)
|
16625 |
|
|
|| ! host_integerp (DECL_SIZE (decl), 1))
|
16626 |
|
|
return;
|
16627 |
|
|
|
16628 |
|
|
bitpos_int = int_bit_position (decl);
|
16629 |
|
|
|
16630 |
|
|
/* Note that the bit offset is always the distance (in bits) from the
|
16631 |
|
|
highest-order bit of the "containing object" to the highest-order bit of
|
16632 |
|
|
the bit-field itself. Since the "high-order end" of any object or field
|
16633 |
|
|
is different on big-endian and little-endian machines, the computation
|
16634 |
|
|
below must take account of these differences. */
|
16635 |
|
|
highest_order_object_bit_offset = object_offset_in_bytes * BITS_PER_UNIT;
|
16636 |
|
|
highest_order_field_bit_offset = bitpos_int;
|
16637 |
|
|
|
16638 |
|
|
if (! BYTES_BIG_ENDIAN)
|
16639 |
|
|
{
|
16640 |
|
|
highest_order_field_bit_offset += tree_low_cst (DECL_SIZE (decl), 0);
|
16641 |
|
|
highest_order_object_bit_offset += simple_type_size_in_bits (type);
|
16642 |
|
|
}
|
16643 |
|
|
|
16644 |
|
|
bit_offset
|
16645 |
|
|
= (! BYTES_BIG_ENDIAN
|
16646 |
|
|
? highest_order_object_bit_offset - highest_order_field_bit_offset
|
16647 |
|
|
: highest_order_field_bit_offset - highest_order_object_bit_offset);
|
16648 |
|
|
|
16649 |
|
|
add_AT_unsigned (die, DW_AT_bit_offset, bit_offset);
|
16650 |
|
|
}
|
16651 |
|
|
|
16652 |
|
|
/* For a FIELD_DECL node which represents a bit field, output an attribute
|
16653 |
|
|
which specifies the length in bits of the given field. */
|
16654 |
|
|
|
16655 |
|
|
static inline void
|
16656 |
|
|
add_bit_size_attribute (dw_die_ref die, tree decl)
|
16657 |
|
|
{
|
16658 |
|
|
/* Must be a field and a bit field. */
|
16659 |
|
|
gcc_assert (TREE_CODE (decl) == FIELD_DECL
|
16660 |
|
|
&& DECL_BIT_FIELD_TYPE (decl));
|
16661 |
|
|
|
16662 |
|
|
if (host_integerp (DECL_SIZE (decl), 1))
|
16663 |
|
|
add_AT_unsigned (die, DW_AT_bit_size, tree_low_cst (DECL_SIZE (decl), 1));
|
16664 |
|
|
}
|
16665 |
|
|
|
16666 |
|
|
/* If the compiled language is ANSI C, then add a 'prototyped'
|
16667 |
|
|
attribute, if arg types are given for the parameters of a function. */
|
16668 |
|
|
|
16669 |
|
|
static inline void
|
16670 |
|
|
add_prototyped_attribute (dw_die_ref die, tree func_type)
|
16671 |
|
|
{
|
16672 |
|
|
if (get_AT_unsigned (comp_unit_die, DW_AT_language) == DW_LANG_C89
|
16673 |
|
|
&& TYPE_ARG_TYPES (func_type) != NULL)
|
16674 |
|
|
add_AT_flag (die, DW_AT_prototyped, 1);
|
16675 |
|
|
}
|
16676 |
|
|
|
16677 |
|
|
/* Add an 'abstract_origin' attribute below a given DIE. The DIE is found
|
16678 |
|
|
by looking in either the type declaration or object declaration
|
16679 |
|
|
equate table. */
|
16680 |
|
|
|
16681 |
|
|
static inline dw_die_ref
|
16682 |
|
|
add_abstract_origin_attribute (dw_die_ref die, tree origin)
|
16683 |
|
|
{
|
16684 |
|
|
dw_die_ref origin_die = NULL;
|
16685 |
|
|
|
16686 |
|
|
if (TREE_CODE (origin) != FUNCTION_DECL)
|
16687 |
|
|
{
|
16688 |
|
|
/* We may have gotten separated from the block for the inlined
|
16689 |
|
|
function, if we're in an exception handler or some such; make
|
16690 |
|
|
sure that the abstract function has been written out.
|
16691 |
|
|
|
16692 |
|
|
Doing this for nested functions is wrong, however; functions are
|
16693 |
|
|
distinct units, and our context might not even be inline. */
|
16694 |
|
|
tree fn = origin;
|
16695 |
|
|
|
16696 |
|
|
if (TYPE_P (fn))
|
16697 |
|
|
fn = TYPE_STUB_DECL (fn);
|
16698 |
|
|
|
16699 |
|
|
fn = decl_function_context (fn);
|
16700 |
|
|
if (fn)
|
16701 |
|
|
dwarf2out_abstract_function (fn);
|
16702 |
|
|
}
|
16703 |
|
|
|
16704 |
|
|
if (DECL_P (origin))
|
16705 |
|
|
origin_die = lookup_decl_die (origin);
|
16706 |
|
|
else if (TYPE_P (origin))
|
16707 |
|
|
origin_die = lookup_type_die (origin);
|
16708 |
|
|
|
16709 |
|
|
/* XXX: Functions that are never lowered don't always have correct block
|
16710 |
|
|
trees (in the case of java, they simply have no block tree, in some other
|
16711 |
|
|
languages). For these functions, there is nothing we can really do to
|
16712 |
|
|
output correct debug info for inlined functions in all cases. Rather
|
16713 |
|
|
than die, we'll just produce deficient debug info now, in that we will
|
16714 |
|
|
have variables without a proper abstract origin. In the future, when all
|
16715 |
|
|
functions are lowered, we should re-add a gcc_assert (origin_die)
|
16716 |
|
|
here. */
|
16717 |
|
|
|
16718 |
|
|
if (origin_die)
|
16719 |
|
|
add_AT_die_ref (die, DW_AT_abstract_origin, origin_die);
|
16720 |
|
|
return origin_die;
|
16721 |
|
|
}
|
16722 |
|
|
|
16723 |
|
|
/* We do not currently support the pure_virtual attribute. */
|
16724 |
|
|
|
16725 |
|
|
static inline void
|
16726 |
|
|
add_pure_or_virtual_attribute (dw_die_ref die, tree func_decl)
|
16727 |
|
|
{
|
16728 |
|
|
if (DECL_VINDEX (func_decl))
|
16729 |
|
|
{
|
16730 |
|
|
add_AT_unsigned (die, DW_AT_virtuality, DW_VIRTUALITY_virtual);
|
16731 |
|
|
|
16732 |
|
|
if (host_integerp (DECL_VINDEX (func_decl), 0))
|
16733 |
|
|
add_AT_loc (die, DW_AT_vtable_elem_location,
|
16734 |
|
|
new_loc_descr (DW_OP_constu,
|
16735 |
|
|
tree_low_cst (DECL_VINDEX (func_decl), 0),
|
16736 |
|
|
0));
|
16737 |
|
|
|
16738 |
|
|
/* GNU extension: Record what type this method came from originally. */
|
16739 |
|
|
if (debug_info_level > DINFO_LEVEL_TERSE
|
16740 |
|
|
&& DECL_CONTEXT (func_decl))
|
16741 |
|
|
add_AT_die_ref (die, DW_AT_containing_type,
|
16742 |
|
|
lookup_type_die (DECL_CONTEXT (func_decl)));
|
16743 |
|
|
}
|
16744 |
|
|
}
|
16745 |
|
|
|
16746 |
|
|
/* Add source coordinate attributes for the given decl. */
|
16747 |
|
|
|
16748 |
|
|
static void
|
16749 |
|
|
add_src_coords_attributes (dw_die_ref die, tree decl)
|
16750 |
|
|
{
|
16751 |
|
|
expanded_location s = expand_location (DECL_SOURCE_LOCATION (decl));
|
16752 |
|
|
|
16753 |
|
|
add_AT_file (die, DW_AT_decl_file, lookup_filename (s.file));
|
16754 |
|
|
add_AT_unsigned (die, DW_AT_decl_line, s.line);
|
16755 |
|
|
}
|
16756 |
|
|
|
16757 |
|
|
/* Add a DW_AT_name attribute and source coordinate attribute for the
|
16758 |
|
|
given decl, but only if it actually has a name. */
|
16759 |
|
|
|
16760 |
|
|
static void
|
16761 |
|
|
add_name_and_src_coords_attributes (dw_die_ref die, tree decl)
|
16762 |
|
|
{
|
16763 |
|
|
tree decl_name;
|
16764 |
|
|
|
16765 |
|
|
decl_name = DECL_NAME (decl);
|
16766 |
|
|
if (decl_name != NULL && IDENTIFIER_POINTER (decl_name) != NULL)
|
16767 |
|
|
{
|
16768 |
|
|
const char *name = dwarf2_name (decl, 0);
|
16769 |
|
|
if (name)
|
16770 |
|
|
add_name_attribute (die, name);
|
16771 |
|
|
if (! DECL_ARTIFICIAL (decl))
|
16772 |
|
|
add_src_coords_attributes (die, decl);
|
16773 |
|
|
|
16774 |
|
|
if ((TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL)
|
16775 |
|
|
&& TREE_PUBLIC (decl)
|
16776 |
|
|
&& !DECL_ABSTRACT (decl)
|
16777 |
|
|
&& !(TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl))
|
16778 |
|
|
&& !is_fortran ())
|
16779 |
|
|
{
|
16780 |
|
|
/* Defer until we have an assembler name set. */
|
16781 |
|
|
if (!DECL_ASSEMBLER_NAME_SET_P (decl))
|
16782 |
|
|
{
|
16783 |
|
|
limbo_die_node *asm_name;
|
16784 |
|
|
|
16785 |
|
|
asm_name = GGC_CNEW (limbo_die_node);
|
16786 |
|
|
asm_name->die = die;
|
16787 |
|
|
asm_name->created_for = decl;
|
16788 |
|
|
asm_name->next = deferred_asm_name;
|
16789 |
|
|
deferred_asm_name = asm_name;
|
16790 |
|
|
}
|
16791 |
|
|
else if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl))
|
16792 |
|
|
add_AT_string (die, DW_AT_MIPS_linkage_name,
|
16793 |
|
|
IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
|
16794 |
|
|
}
|
16795 |
|
|
}
|
16796 |
|
|
|
16797 |
|
|
#ifdef VMS_DEBUGGING_INFO
|
16798 |
|
|
/* Get the function's name, as described by its RTL. This may be different
|
16799 |
|
|
from the DECL_NAME name used in the source file. */
|
16800 |
|
|
if (TREE_CODE (decl) == FUNCTION_DECL && TREE_ASM_WRITTEN (decl))
|
16801 |
|
|
{
|
16802 |
|
|
add_AT_addr (die, DW_AT_VMS_rtnbeg_pd_address,
|
16803 |
|
|
XEXP (DECL_RTL (decl), 0));
|
16804 |
|
|
VEC_safe_push (rtx, gc, used_rtx_array, XEXP (DECL_RTL (decl), 0));
|
16805 |
|
|
}
|
16806 |
|
|
#endif
|
16807 |
|
|
}
|
16808 |
|
|
|
16809 |
|
|
/* Push a new declaration scope. */
|
16810 |
|
|
|
16811 |
|
|
static void
|
16812 |
|
|
push_decl_scope (tree scope)
|
16813 |
|
|
{
|
16814 |
|
|
VEC_safe_push (tree, gc, decl_scope_table, scope);
|
16815 |
|
|
}
|
16816 |
|
|
|
16817 |
|
|
/* Pop a declaration scope. */
|
16818 |
|
|
|
16819 |
|
|
static inline void
|
16820 |
|
|
pop_decl_scope (void)
|
16821 |
|
|
{
|
16822 |
|
|
VEC_pop (tree, decl_scope_table);
|
16823 |
|
|
}
|
16824 |
|
|
|
16825 |
|
|
/* Return the DIE for the scope that immediately contains this type.
|
16826 |
|
|
Non-named types get global scope. Named types nested in other
|
16827 |
|
|
types get their containing scope if it's open, or global scope
|
16828 |
|
|
otherwise. All other types (i.e. function-local named types) get
|
16829 |
|
|
the current active scope. */
|
16830 |
|
|
|
16831 |
|
|
static dw_die_ref
|
16832 |
|
|
scope_die_for (tree t, dw_die_ref context_die)
|
16833 |
|
|
{
|
16834 |
|
|
dw_die_ref scope_die = NULL;
|
16835 |
|
|
tree containing_scope;
|
16836 |
|
|
int i;
|
16837 |
|
|
|
16838 |
|
|
/* Non-types always go in the current scope. */
|
16839 |
|
|
gcc_assert (TYPE_P (t));
|
16840 |
|
|
|
16841 |
|
|
containing_scope = TYPE_CONTEXT (t);
|
16842 |
|
|
|
16843 |
|
|
/* Use the containing namespace if it was passed in (for a declaration). */
|
16844 |
|
|
if (containing_scope && TREE_CODE (containing_scope) == NAMESPACE_DECL)
|
16845 |
|
|
{
|
16846 |
|
|
if (context_die == lookup_decl_die (containing_scope))
|
16847 |
|
|
/* OK */;
|
16848 |
|
|
else
|
16849 |
|
|
containing_scope = NULL_TREE;
|
16850 |
|
|
}
|
16851 |
|
|
|
16852 |
|
|
/* Ignore function type "scopes" from the C frontend. They mean that
|
16853 |
|
|
a tagged type is local to a parmlist of a function declarator, but
|
16854 |
|
|
that isn't useful to DWARF. */
|
16855 |
|
|
if (containing_scope && TREE_CODE (containing_scope) == FUNCTION_TYPE)
|
16856 |
|
|
containing_scope = NULL_TREE;
|
16857 |
|
|
|
16858 |
|
|
if (containing_scope == NULL_TREE)
|
16859 |
|
|
scope_die = comp_unit_die;
|
16860 |
|
|
else if (TYPE_P (containing_scope))
|
16861 |
|
|
{
|
16862 |
|
|
/* For types, we can just look up the appropriate DIE. But
|
16863 |
|
|
first we check to see if we're in the middle of emitting it
|
16864 |
|
|
so we know where the new DIE should go. */
|
16865 |
|
|
for (i = VEC_length (tree, decl_scope_table) - 1; i >= 0; --i)
|
16866 |
|
|
if (VEC_index (tree, decl_scope_table, i) == containing_scope)
|
16867 |
|
|
break;
|
16868 |
|
|
|
16869 |
|
|
if (i < 0)
|
16870 |
|
|
{
|
16871 |
|
|
gcc_assert (debug_info_level <= DINFO_LEVEL_TERSE
|
16872 |
|
|
|| TREE_ASM_WRITTEN (containing_scope));
|
16873 |
|
|
|
16874 |
|
|
/* If none of the current dies are suitable, we get file scope. */
|
16875 |
|
|
scope_die = comp_unit_die;
|
16876 |
|
|
}
|
16877 |
|
|
else
|
16878 |
|
|
scope_die = lookup_type_die (containing_scope);
|
16879 |
|
|
}
|
16880 |
|
|
else
|
16881 |
|
|
scope_die = context_die;
|
16882 |
|
|
|
16883 |
|
|
return scope_die;
|
16884 |
|
|
}
|
16885 |
|
|
|
16886 |
|
|
/* Returns nonzero if CONTEXT_DIE is internal to a function. */
|
16887 |
|
|
|
16888 |
|
|
static inline int
|
16889 |
|
|
local_scope_p (dw_die_ref context_die)
|
16890 |
|
|
{
|
16891 |
|
|
for (; context_die; context_die = context_die->die_parent)
|
16892 |
|
|
if (context_die->die_tag == DW_TAG_inlined_subroutine
|
16893 |
|
|
|| context_die->die_tag == DW_TAG_subprogram)
|
16894 |
|
|
return 1;
|
16895 |
|
|
|
16896 |
|
|
return 0;
|
16897 |
|
|
}
|
16898 |
|
|
|
16899 |
|
|
/* Returns nonzero if CONTEXT_DIE is a class. */
|
16900 |
|
|
|
16901 |
|
|
static inline int
|
16902 |
|
|
class_scope_p (dw_die_ref context_die)
|
16903 |
|
|
{
|
16904 |
|
|
return (context_die
|
16905 |
|
|
&& (context_die->die_tag == DW_TAG_structure_type
|
16906 |
|
|
|| context_die->die_tag == DW_TAG_class_type
|
16907 |
|
|
|| context_die->die_tag == DW_TAG_interface_type
|
16908 |
|
|
|| context_die->die_tag == DW_TAG_union_type));
|
16909 |
|
|
}
|
16910 |
|
|
|
16911 |
|
|
/* Returns nonzero if CONTEXT_DIE is a class or namespace, for deciding
|
16912 |
|
|
whether or not to treat a DIE in this context as a declaration. */
|
16913 |
|
|
|
16914 |
|
|
static inline int
|
16915 |
|
|
class_or_namespace_scope_p (dw_die_ref context_die)
|
16916 |
|
|
{
|
16917 |
|
|
return (class_scope_p (context_die)
|
16918 |
|
|
|| (context_die && context_die->die_tag == DW_TAG_namespace));
|
16919 |
|
|
}
|
16920 |
|
|
|
16921 |
|
|
/* Many forms of DIEs require a "type description" attribute. This
|
16922 |
|
|
routine locates the proper "type descriptor" die for the type given
|
16923 |
|
|
by 'type', and adds a DW_AT_type attribute below the given die. */
|
16924 |
|
|
|
16925 |
|
|
static void
|
16926 |
|
|
add_type_attribute (dw_die_ref object_die, tree type, int decl_const,
|
16927 |
|
|
int decl_volatile, dw_die_ref context_die)
|
16928 |
|
|
{
|
16929 |
|
|
enum tree_code code = TREE_CODE (type);
|
16930 |
|
|
dw_die_ref type_die = NULL;
|
16931 |
|
|
|
16932 |
|
|
/* ??? If this type is an unnamed subrange type of an integral, floating-point
|
16933 |
|
|
or fixed-point type, use the inner type. This is because we have no
|
16934 |
|
|
support for unnamed types in base_type_die. This can happen if this is
|
16935 |
|
|
an Ada subrange type. Correct solution is emit a subrange type die. */
|
16936 |
|
|
if ((code == INTEGER_TYPE || code == REAL_TYPE || code == FIXED_POINT_TYPE)
|
16937 |
|
|
&& TREE_TYPE (type) != 0 && TYPE_NAME (type) == 0)
|
16938 |
|
|
type = TREE_TYPE (type), code = TREE_CODE (type);
|
16939 |
|
|
|
16940 |
|
|
if (code == ERROR_MARK
|
16941 |
|
|
/* Handle a special case. For functions whose return type is void, we
|
16942 |
|
|
generate *no* type attribute. (Note that no object may have type
|
16943 |
|
|
`void', so this only applies to function return types). */
|
16944 |
|
|
|| code == VOID_TYPE)
|
16945 |
|
|
return;
|
16946 |
|
|
|
16947 |
|
|
type_die = modified_type_die (type,
|
16948 |
|
|
decl_const || TYPE_READONLY (type),
|
16949 |
|
|
decl_volatile || TYPE_VOLATILE (type),
|
16950 |
|
|
context_die);
|
16951 |
|
|
|
16952 |
|
|
if (type_die != NULL)
|
16953 |
|
|
add_AT_die_ref (object_die, DW_AT_type, type_die);
|
16954 |
|
|
}
|
16955 |
|
|
|
16956 |
|
|
/* Given an object die, add the calling convention attribute for the
|
16957 |
|
|
function call type. */
|
16958 |
|
|
static void
|
16959 |
|
|
add_calling_convention_attribute (dw_die_ref subr_die, tree decl)
|
16960 |
|
|
{
|
16961 |
|
|
enum dwarf_calling_convention value = DW_CC_normal;
|
16962 |
|
|
|
16963 |
|
|
value = ((enum dwarf_calling_convention)
|
16964 |
|
|
targetm.dwarf_calling_convention (TREE_TYPE (decl)));
|
16965 |
|
|
|
16966 |
|
|
/* DWARF doesn't provide a way to identify a program's source-level
|
16967 |
|
|
entry point. DW_AT_calling_convention attributes are only meant
|
16968 |
|
|
to describe functions' calling conventions. However, lacking a
|
16969 |
|
|
better way to signal the Fortran main program, we use this for the
|
16970 |
|
|
time being, following existing custom. */
|
16971 |
|
|
if (is_fortran ()
|
16972 |
|
|
&& !strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), "MAIN__"))
|
16973 |
|
|
value = DW_CC_program;
|
16974 |
|
|
|
16975 |
|
|
/* Only add the attribute if the backend requests it, and
|
16976 |
|
|
is not DW_CC_normal. */
|
16977 |
|
|
if (value && (value != DW_CC_normal))
|
16978 |
|
|
add_AT_unsigned (subr_die, DW_AT_calling_convention, value);
|
16979 |
|
|
}
|
16980 |
|
|
|
16981 |
|
|
/* Given a tree pointer to a struct, class, union, or enum type node, return
|
16982 |
|
|
a pointer to the (string) tag name for the given type, or zero if the type
|
16983 |
|
|
was declared without a tag. */
|
16984 |
|
|
|
16985 |
|
|
static const char *
|
16986 |
|
|
type_tag (const_tree type)
|
16987 |
|
|
{
|
16988 |
|
|
const char *name = 0;
|
16989 |
|
|
|
16990 |
|
|
if (TYPE_NAME (type) != 0)
|
16991 |
|
|
{
|
16992 |
|
|
tree t = 0;
|
16993 |
|
|
|
16994 |
|
|
/* Find the IDENTIFIER_NODE for the type name. */
|
16995 |
|
|
if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
|
16996 |
|
|
t = TYPE_NAME (type);
|
16997 |
|
|
|
16998 |
|
|
/* The g++ front end makes the TYPE_NAME of *each* tagged type point to
|
16999 |
|
|
a TYPE_DECL node, regardless of whether or not a `typedef' was
|
17000 |
|
|
involved. */
|
17001 |
|
|
else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
|
17002 |
|
|
&& ! DECL_IGNORED_P (TYPE_NAME (type)))
|
17003 |
|
|
{
|
17004 |
|
|
/* We want to be extra verbose. Don't call dwarf_name if
|
17005 |
|
|
DECL_NAME isn't set. The default hook for decl_printable_name
|
17006 |
|
|
doesn't like that, and in this context it's correct to return
|
17007 |
|
|
0, instead of "<anonymous>" or the like. */
|
17008 |
|
|
if (DECL_NAME (TYPE_NAME (type)))
|
17009 |
|
|
name = lang_hooks.dwarf_name (TYPE_NAME (type), 2);
|
17010 |
|
|
}
|
17011 |
|
|
|
17012 |
|
|
/* Now get the name as a string, or invent one. */
|
17013 |
|
|
if (!name && t != 0)
|
17014 |
|
|
name = IDENTIFIER_POINTER (t);
|
17015 |
|
|
}
|
17016 |
|
|
|
17017 |
|
|
return (name == 0 || *name == '\0') ? 0 : name;
|
17018 |
|
|
}
|
17019 |
|
|
|
17020 |
|
|
/* Return the type associated with a data member, make a special check
|
17021 |
|
|
for bit field types. */
|
17022 |
|
|
|
17023 |
|
|
static inline tree
|
17024 |
|
|
member_declared_type (const_tree member)
|
17025 |
|
|
{
|
17026 |
|
|
return (DECL_BIT_FIELD_TYPE (member)
|
17027 |
|
|
? DECL_BIT_FIELD_TYPE (member) : TREE_TYPE (member));
|
17028 |
|
|
}
|
17029 |
|
|
|
17030 |
|
|
/* Get the decl's label, as described by its RTL. This may be different
|
17031 |
|
|
from the DECL_NAME name used in the source file. */
|
17032 |
|
|
|
17033 |
|
|
#if 0
|
17034 |
|
|
static const char *
|
17035 |
|
|
decl_start_label (tree decl)
|
17036 |
|
|
{
|
17037 |
|
|
rtx x;
|
17038 |
|
|
const char *fnname;
|
17039 |
|
|
|
17040 |
|
|
x = DECL_RTL (decl);
|
17041 |
|
|
gcc_assert (MEM_P (x));
|
17042 |
|
|
|
17043 |
|
|
x = XEXP (x, 0);
|
17044 |
|
|
gcc_assert (GET_CODE (x) == SYMBOL_REF);
|
17045 |
|
|
|
17046 |
|
|
fnname = XSTR (x, 0);
|
17047 |
|
|
return fnname;
|
17048 |
|
|
}
|
17049 |
|
|
#endif
|
17050 |
|
|
|
17051 |
|
|
/* These routines generate the internal representation of the DIE's for
|
17052 |
|
|
the compilation unit. Debugging information is collected by walking
|
17053 |
|
|
the declaration trees passed in from dwarf2out_decl(). */
|
17054 |
|
|
|
17055 |
|
|
static void
|
17056 |
|
|
gen_array_type_die (tree type, dw_die_ref context_die)
|
17057 |
|
|
{
|
17058 |
|
|
dw_die_ref scope_die = scope_die_for (type, context_die);
|
17059 |
|
|
dw_die_ref array_die;
|
17060 |
|
|
|
17061 |
|
|
/* GNU compilers represent multidimensional array types as sequences of one
|
17062 |
|
|
dimensional array types whose element types are themselves array types.
|
17063 |
|
|
We sometimes squish that down to a single array_type DIE with multiple
|
17064 |
|
|
subscripts in the Dwarf debugging info. The draft Dwarf specification
|
17065 |
|
|
say that we are allowed to do this kind of compression in C, because
|
17066 |
|
|
there is no difference between an array of arrays and a multidimensional
|
17067 |
|
|
array. We don't do this for Ada to remain as close as possible to the
|
17068 |
|
|
actual representation, which is especially important against the language
|
17069 |
|
|
flexibilty wrt arrays of variable size. */
|
17070 |
|
|
|
17071 |
|
|
bool collapse_nested_arrays = !is_ada ();
|
17072 |
|
|
tree element_type;
|
17073 |
|
|
|
17074 |
|
|
/* Emit DW_TAG_string_type for Fortran character types (with kind 1 only, as
|
17075 |
|
|
DW_TAG_string_type doesn't have DW_AT_type attribute). */
|
17076 |
|
|
if (TYPE_STRING_FLAG (type)
|
17077 |
|
|
&& TREE_CODE (type) == ARRAY_TYPE
|
17078 |
|
|
&& is_fortran ()
|
17079 |
|
|
&& TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (char_type_node))
|
17080 |
|
|
{
|
17081 |
|
|
HOST_WIDE_INT size;
|
17082 |
|
|
|
17083 |
|
|
array_die = new_die (DW_TAG_string_type, scope_die, type);
|
17084 |
|
|
add_name_attribute (array_die, type_tag (type));
|
17085 |
|
|
equate_type_number_to_die (type, array_die);
|
17086 |
|
|
size = int_size_in_bytes (type);
|
17087 |
|
|
if (size >= 0)
|
17088 |
|
|
add_AT_unsigned (array_die, DW_AT_byte_size, size);
|
17089 |
|
|
else if (TYPE_DOMAIN (type) != NULL_TREE
|
17090 |
|
|
&& TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
|
17091 |
|
|
&& DECL_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
|
17092 |
|
|
{
|
17093 |
|
|
tree szdecl = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
|
17094 |
|
|
dw_loc_list_ref loc = loc_list_from_tree (szdecl, 2);
|
17095 |
|
|
|
17096 |
|
|
size = int_size_in_bytes (TREE_TYPE (szdecl));
|
17097 |
|
|
if (loc && size > 0)
|
17098 |
|
|
{
|
17099 |
|
|
add_AT_location_description (array_die, DW_AT_string_length, loc);
|
17100 |
|
|
if (size != DWARF2_ADDR_SIZE)
|
17101 |
|
|
add_AT_unsigned (array_die, DW_AT_byte_size, size);
|
17102 |
|
|
}
|
17103 |
|
|
}
|
17104 |
|
|
return;
|
17105 |
|
|
}
|
17106 |
|
|
|
17107 |
|
|
/* ??? The SGI dwarf reader fails for array of array of enum types
|
17108 |
|
|
(e.g. const enum machine_mode insn_operand_mode[2][10]) unless the inner
|
17109 |
|
|
array type comes before the outer array type. We thus call gen_type_die
|
17110 |
|
|
before we new_die and must prevent nested array types collapsing for this
|
17111 |
|
|
target. */
|
17112 |
|
|
|
17113 |
|
|
#ifdef MIPS_DEBUGGING_INFO
|
17114 |
|
|
gen_type_die (TREE_TYPE (type), context_die);
|
17115 |
|
|
collapse_nested_arrays = false;
|
17116 |
|
|
#endif
|
17117 |
|
|
|
17118 |
|
|
array_die = new_die (DW_TAG_array_type, scope_die, type);
|
17119 |
|
|
add_name_attribute (array_die, type_tag (type));
|
17120 |
|
|
equate_type_number_to_die (type, array_die);
|
17121 |
|
|
|
17122 |
|
|
if (TREE_CODE (type) == VECTOR_TYPE)
|
17123 |
|
|
{
|
17124 |
|
|
/* The frontend feeds us a representation for the vector as a struct
|
17125 |
|
|
containing an array. Pull out the array type. */
|
17126 |
|
|
type = TREE_TYPE (TYPE_FIELDS (TYPE_DEBUG_REPRESENTATION_TYPE (type)));
|
17127 |
|
|
add_AT_flag (array_die, DW_AT_GNU_vector, 1);
|
17128 |
|
|
}
|
17129 |
|
|
|
17130 |
|
|
/* For Fortran multidimensional arrays use DW_ORD_col_major ordering. */
|
17131 |
|
|
if (is_fortran ()
|
17132 |
|
|
&& TREE_CODE (type) == ARRAY_TYPE
|
17133 |
|
|
&& TREE_CODE (TREE_TYPE (type)) == ARRAY_TYPE
|
17134 |
|
|
&& !TYPE_STRING_FLAG (TREE_TYPE (type)))
|
17135 |
|
|
add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_col_major);
|
17136 |
|
|
|
17137 |
|
|
#if 0
|
17138 |
|
|
/* We default the array ordering. SDB will probably do
|
17139 |
|
|
the right things even if DW_AT_ordering is not present. It's not even
|
17140 |
|
|
an issue until we start to get into multidimensional arrays anyway. If
|
17141 |
|
|
SDB is ever caught doing the Wrong Thing for multi-dimensional arrays,
|
17142 |
|
|
then we'll have to put the DW_AT_ordering attribute back in. (But if
|
17143 |
|
|
and when we find out that we need to put these in, we will only do so
|
17144 |
|
|
for multidimensional arrays. */
|
17145 |
|
|
add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_row_major);
|
17146 |
|
|
#endif
|
17147 |
|
|
|
17148 |
|
|
#ifdef MIPS_DEBUGGING_INFO
|
17149 |
|
|
/* The SGI compilers handle arrays of unknown bound by setting
|
17150 |
|
|
AT_declaration and not emitting any subrange DIEs. */
|
17151 |
|
|
if (! TYPE_DOMAIN (type))
|
17152 |
|
|
add_AT_flag (array_die, DW_AT_declaration, 1);
|
17153 |
|
|
else
|
17154 |
|
|
#endif
|
17155 |
|
|
add_subscript_info (array_die, type, collapse_nested_arrays);
|
17156 |
|
|
|
17157 |
|
|
/* Add representation of the type of the elements of this array type and
|
17158 |
|
|
emit the corresponding DIE if we haven't done it already. */
|
17159 |
|
|
element_type = TREE_TYPE (type);
|
17160 |
|
|
if (collapse_nested_arrays)
|
17161 |
|
|
while (TREE_CODE (element_type) == ARRAY_TYPE)
|
17162 |
|
|
{
|
17163 |
|
|
if (TYPE_STRING_FLAG (element_type) && is_fortran ())
|
17164 |
|
|
break;
|
17165 |
|
|
element_type = TREE_TYPE (element_type);
|
17166 |
|
|
}
|
17167 |
|
|
|
17168 |
|
|
#ifndef MIPS_DEBUGGING_INFO
|
17169 |
|
|
gen_type_die (element_type, context_die);
|
17170 |
|
|
#endif
|
17171 |
|
|
|
17172 |
|
|
add_type_attribute (array_die, element_type, 0, 0, context_die);
|
17173 |
|
|
|
17174 |
|
|
if (get_AT (array_die, DW_AT_name))
|
17175 |
|
|
add_pubtype (type, array_die);
|
17176 |
|
|
}
|
17177 |
|
|
|
17178 |
|
|
static dw_loc_descr_ref
|
17179 |
|
|
descr_info_loc (tree val, tree base_decl)
|
17180 |
|
|
{
|
17181 |
|
|
HOST_WIDE_INT size;
|
17182 |
|
|
dw_loc_descr_ref loc, loc2;
|
17183 |
|
|
enum dwarf_location_atom op;
|
17184 |
|
|
|
17185 |
|
|
if (val == base_decl)
|
17186 |
|
|
return new_loc_descr (DW_OP_push_object_address, 0, 0);
|
17187 |
|
|
|
17188 |
|
|
switch (TREE_CODE (val))
|
17189 |
|
|
{
|
17190 |
|
|
CASE_CONVERT:
|
17191 |
|
|
return descr_info_loc (TREE_OPERAND (val, 0), base_decl);
|
17192 |
|
|
case VAR_DECL:
|
17193 |
|
|
return loc_descriptor_from_tree (val, 0);
|
17194 |
|
|
case INTEGER_CST:
|
17195 |
|
|
if (host_integerp (val, 0))
|
17196 |
|
|
return int_loc_descriptor (tree_low_cst (val, 0));
|
17197 |
|
|
break;
|
17198 |
|
|
case INDIRECT_REF:
|
17199 |
|
|
size = int_size_in_bytes (TREE_TYPE (val));
|
17200 |
|
|
if (size < 0)
|
17201 |
|
|
break;
|
17202 |
|
|
loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
|
17203 |
|
|
if (!loc)
|
17204 |
|
|
break;
|
17205 |
|
|
if (size == DWARF2_ADDR_SIZE)
|
17206 |
|
|
add_loc_descr (&loc, new_loc_descr (DW_OP_deref, 0, 0));
|
17207 |
|
|
else
|
17208 |
|
|
add_loc_descr (&loc, new_loc_descr (DW_OP_deref_size, size, 0));
|
17209 |
|
|
return loc;
|
17210 |
|
|
case POINTER_PLUS_EXPR:
|
17211 |
|
|
case PLUS_EXPR:
|
17212 |
|
|
if (host_integerp (TREE_OPERAND (val, 1), 1)
|
17213 |
|
|
&& (unsigned HOST_WIDE_INT) tree_low_cst (TREE_OPERAND (val, 1), 1)
|
17214 |
|
|
< 16384)
|
17215 |
|
|
{
|
17216 |
|
|
loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
|
17217 |
|
|
if (!loc)
|
17218 |
|
|
break;
|
17219 |
|
|
loc_descr_plus_const (&loc, tree_low_cst (TREE_OPERAND (val, 1), 0));
|
17220 |
|
|
}
|
17221 |
|
|
else
|
17222 |
|
|
{
|
17223 |
|
|
op = DW_OP_plus;
|
17224 |
|
|
do_binop:
|
17225 |
|
|
loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
|
17226 |
|
|
if (!loc)
|
17227 |
|
|
break;
|
17228 |
|
|
loc2 = descr_info_loc (TREE_OPERAND (val, 1), base_decl);
|
17229 |
|
|
if (!loc2)
|
17230 |
|
|
break;
|
17231 |
|
|
add_loc_descr (&loc, loc2);
|
17232 |
|
|
add_loc_descr (&loc2, new_loc_descr (op, 0, 0));
|
17233 |
|
|
}
|
17234 |
|
|
return loc;
|
17235 |
|
|
case MINUS_EXPR:
|
17236 |
|
|
op = DW_OP_minus;
|
17237 |
|
|
goto do_binop;
|
17238 |
|
|
case MULT_EXPR:
|
17239 |
|
|
op = DW_OP_mul;
|
17240 |
|
|
goto do_binop;
|
17241 |
|
|
case EQ_EXPR:
|
17242 |
|
|
op = DW_OP_eq;
|
17243 |
|
|
goto do_binop;
|
17244 |
|
|
case NE_EXPR:
|
17245 |
|
|
op = DW_OP_ne;
|
17246 |
|
|
goto do_binop;
|
17247 |
|
|
default:
|
17248 |
|
|
break;
|
17249 |
|
|
}
|
17250 |
|
|
return NULL;
|
17251 |
|
|
}
|
17252 |
|
|
|
17253 |
|
|
static void
|
17254 |
|
|
add_descr_info_field (dw_die_ref die, enum dwarf_attribute attr,
|
17255 |
|
|
tree val, tree base_decl)
|
17256 |
|
|
{
|
17257 |
|
|
dw_loc_descr_ref loc;
|
17258 |
|
|
|
17259 |
|
|
if (host_integerp (val, 0))
|
17260 |
|
|
{
|
17261 |
|
|
add_AT_unsigned (die, attr, tree_low_cst (val, 0));
|
17262 |
|
|
return;
|
17263 |
|
|
}
|
17264 |
|
|
|
17265 |
|
|
loc = descr_info_loc (val, base_decl);
|
17266 |
|
|
if (!loc)
|
17267 |
|
|
return;
|
17268 |
|
|
|
17269 |
|
|
add_AT_loc (die, attr, loc);
|
17270 |
|
|
}
|
17271 |
|
|
|
17272 |
|
|
/* This routine generates DIE for array with hidden descriptor, details
|
17273 |
|
|
are filled into *info by a langhook. */
|
17274 |
|
|
|
17275 |
|
|
static void
|
17276 |
|
|
gen_descr_array_type_die (tree type, struct array_descr_info *info,
|
17277 |
|
|
dw_die_ref context_die)
|
17278 |
|
|
{
|
17279 |
|
|
dw_die_ref scope_die = scope_die_for (type, context_die);
|
17280 |
|
|
dw_die_ref array_die;
|
17281 |
|
|
int dim;
|
17282 |
|
|
|
17283 |
|
|
array_die = new_die (DW_TAG_array_type, scope_die, type);
|
17284 |
|
|
add_name_attribute (array_die, type_tag (type));
|
17285 |
|
|
equate_type_number_to_die (type, array_die);
|
17286 |
|
|
|
17287 |
|
|
/* For Fortran multidimensional arrays use DW_ORD_col_major ordering. */
|
17288 |
|
|
if (is_fortran ()
|
17289 |
|
|
&& info->ndimensions >= 2)
|
17290 |
|
|
add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_col_major);
|
17291 |
|
|
|
17292 |
|
|
if (info->data_location)
|
17293 |
|
|
add_descr_info_field (array_die, DW_AT_data_location, info->data_location,
|
17294 |
|
|
info->base_decl);
|
17295 |
|
|
if (info->associated)
|
17296 |
|
|
add_descr_info_field (array_die, DW_AT_associated, info->associated,
|
17297 |
|
|
info->base_decl);
|
17298 |
|
|
if (info->allocated)
|
17299 |
|
|
add_descr_info_field (array_die, DW_AT_allocated, info->allocated,
|
17300 |
|
|
info->base_decl);
|
17301 |
|
|
|
17302 |
|
|
for (dim = 0; dim < info->ndimensions; dim++)
|
17303 |
|
|
{
|
17304 |
|
|
dw_die_ref subrange_die
|
17305 |
|
|
= new_die (DW_TAG_subrange_type, array_die, NULL);
|
17306 |
|
|
|
17307 |
|
|
if (info->dimen[dim].lower_bound)
|
17308 |
|
|
{
|
17309 |
|
|
/* If it is the default value, omit it. */
|
17310 |
|
|
int dflt;
|
17311 |
|
|
|
17312 |
|
|
if (host_integerp (info->dimen[dim].lower_bound, 0)
|
17313 |
|
|
&& (dflt = lower_bound_default ()) != -1
|
17314 |
|
|
&& tree_low_cst (info->dimen[dim].lower_bound, 0) == dflt)
|
17315 |
|
|
;
|
17316 |
|
|
else
|
17317 |
|
|
add_descr_info_field (subrange_die, DW_AT_lower_bound,
|
17318 |
|
|
info->dimen[dim].lower_bound,
|
17319 |
|
|
info->base_decl);
|
17320 |
|
|
}
|
17321 |
|
|
if (info->dimen[dim].upper_bound)
|
17322 |
|
|
add_descr_info_field (subrange_die, DW_AT_upper_bound,
|
17323 |
|
|
info->dimen[dim].upper_bound,
|
17324 |
|
|
info->base_decl);
|
17325 |
|
|
if (info->dimen[dim].stride)
|
17326 |
|
|
add_descr_info_field (subrange_die, DW_AT_byte_stride,
|
17327 |
|
|
info->dimen[dim].stride,
|
17328 |
|
|
info->base_decl);
|
17329 |
|
|
}
|
17330 |
|
|
|
17331 |
|
|
gen_type_die (info->element_type, context_die);
|
17332 |
|
|
add_type_attribute (array_die, info->element_type, 0, 0, context_die);
|
17333 |
|
|
|
17334 |
|
|
if (get_AT (array_die, DW_AT_name))
|
17335 |
|
|
add_pubtype (type, array_die);
|
17336 |
|
|
}
|
17337 |
|
|
|
17338 |
|
|
#if 0
|
17339 |
|
|
static void
|
17340 |
|
|
gen_entry_point_die (tree decl, dw_die_ref context_die)
|
17341 |
|
|
{
|
17342 |
|
|
tree origin = decl_ultimate_origin (decl);
|
17343 |
|
|
dw_die_ref decl_die = new_die (DW_TAG_entry_point, context_die, decl);
|
17344 |
|
|
|
17345 |
|
|
if (origin != NULL)
|
17346 |
|
|
add_abstract_origin_attribute (decl_die, origin);
|
17347 |
|
|
else
|
17348 |
|
|
{
|
17349 |
|
|
add_name_and_src_coords_attributes (decl_die, decl);
|
17350 |
|
|
add_type_attribute (decl_die, TREE_TYPE (TREE_TYPE (decl)),
|
17351 |
|
|
0, 0, context_die);
|
17352 |
|
|
}
|
17353 |
|
|
|
17354 |
|
|
if (DECL_ABSTRACT (decl))
|
17355 |
|
|
equate_decl_number_to_die (decl, decl_die);
|
17356 |
|
|
else
|
17357 |
|
|
add_AT_lbl_id (decl_die, DW_AT_low_pc, decl_start_label (decl));
|
17358 |
|
|
}
|
17359 |
|
|
#endif
|
17360 |
|
|
|
17361 |
|
|
/* Walk through the list of incomplete types again, trying once more to
|
17362 |
|
|
emit full debugging info for them. */
|
17363 |
|
|
|
17364 |
|
|
static void
|
17365 |
|
|
retry_incomplete_types (void)
|
17366 |
|
|
{
|
17367 |
|
|
int i;
|
17368 |
|
|
|
17369 |
|
|
for (i = VEC_length (tree, incomplete_types) - 1; i >= 0; i--)
|
17370 |
|
|
if (should_emit_struct_debug (VEC_index (tree, incomplete_types, i),
|
17371 |
|
|
DINFO_USAGE_DIR_USE))
|
17372 |
|
|
gen_type_die (VEC_index (tree, incomplete_types, i), comp_unit_die);
|
17373 |
|
|
}
|
17374 |
|
|
|
17375 |
|
|
/* Determine what tag to use for a record type. */
|
17376 |
|
|
|
17377 |
|
|
static enum dwarf_tag
|
17378 |
|
|
record_type_tag (tree type)
|
17379 |
|
|
{
|
17380 |
|
|
if (! lang_hooks.types.classify_record)
|
17381 |
|
|
return DW_TAG_structure_type;
|
17382 |
|
|
|
17383 |
|
|
switch (lang_hooks.types.classify_record (type))
|
17384 |
|
|
{
|
17385 |
|
|
case RECORD_IS_STRUCT:
|
17386 |
|
|
return DW_TAG_structure_type;
|
17387 |
|
|
|
17388 |
|
|
case RECORD_IS_CLASS:
|
17389 |
|
|
return DW_TAG_class_type;
|
17390 |
|
|
|
17391 |
|
|
case RECORD_IS_INTERFACE:
|
17392 |
|
|
if (dwarf_version >= 3 || !dwarf_strict)
|
17393 |
|
|
return DW_TAG_interface_type;
|
17394 |
|
|
return DW_TAG_structure_type;
|
17395 |
|
|
|
17396 |
|
|
default:
|
17397 |
|
|
gcc_unreachable ();
|
17398 |
|
|
}
|
17399 |
|
|
}
|
17400 |
|
|
|
17401 |
|
|
/* Generate a DIE to represent an enumeration type. Note that these DIEs
|
17402 |
|
|
include all of the information about the enumeration values also. Each
|
17403 |
|
|
enumerated type name/value is listed as a child of the enumerated type
|
17404 |
|
|
DIE. */
|
17405 |
|
|
|
17406 |
|
|
static dw_die_ref
|
17407 |
|
|
gen_enumeration_type_die (tree type, dw_die_ref context_die)
|
17408 |
|
|
{
|
17409 |
|
|
dw_die_ref type_die = lookup_type_die (type);
|
17410 |
|
|
|
17411 |
|
|
if (type_die == NULL)
|
17412 |
|
|
{
|
17413 |
|
|
type_die = new_die (DW_TAG_enumeration_type,
|
17414 |
|
|
scope_die_for (type, context_die), type);
|
17415 |
|
|
equate_type_number_to_die (type, type_die);
|
17416 |
|
|
add_name_attribute (type_die, type_tag (type));
|
17417 |
|
|
}
|
17418 |
|
|
else if (! TYPE_SIZE (type))
|
17419 |
|
|
return type_die;
|
17420 |
|
|
else
|
17421 |
|
|
remove_AT (type_die, DW_AT_declaration);
|
17422 |
|
|
|
17423 |
|
|
/* Handle a GNU C/C++ extension, i.e. incomplete enum types. If the
|
17424 |
|
|
given enum type is incomplete, do not generate the DW_AT_byte_size
|
17425 |
|
|
attribute or the DW_AT_element_list attribute. */
|
17426 |
|
|
if (TYPE_SIZE (type))
|
17427 |
|
|
{
|
17428 |
|
|
tree link;
|
17429 |
|
|
|
17430 |
|
|
TREE_ASM_WRITTEN (type) = 1;
|
17431 |
|
|
add_byte_size_attribute (type_die, type);
|
17432 |
|
|
if (TYPE_STUB_DECL (type) != NULL_TREE)
|
17433 |
|
|
add_src_coords_attributes (type_die, TYPE_STUB_DECL (type));
|
17434 |
|
|
|
17435 |
|
|
/* If the first reference to this type was as the return type of an
|
17436 |
|
|
inline function, then it may not have a parent. Fix this now. */
|
17437 |
|
|
if (type_die->die_parent == NULL)
|
17438 |
|
|
add_child_die (scope_die_for (type, context_die), type_die);
|
17439 |
|
|
|
17440 |
|
|
for (link = TYPE_VALUES (type);
|
17441 |
|
|
link != NULL; link = TREE_CHAIN (link))
|
17442 |
|
|
{
|
17443 |
|
|
dw_die_ref enum_die = new_die (DW_TAG_enumerator, type_die, link);
|
17444 |
|
|
tree value = TREE_VALUE (link);
|
17445 |
|
|
|
17446 |
|
|
add_name_attribute (enum_die,
|
17447 |
|
|
IDENTIFIER_POINTER (TREE_PURPOSE (link)));
|
17448 |
|
|
|
17449 |
|
|
if (TREE_CODE (value) == CONST_DECL)
|
17450 |
|
|
value = DECL_INITIAL (value);
|
17451 |
|
|
|
17452 |
|
|
if (host_integerp (value, TYPE_UNSIGNED (TREE_TYPE (value))))
|
17453 |
|
|
/* DWARF2 does not provide a way of indicating whether or
|
17454 |
|
|
not enumeration constants are signed or unsigned. GDB
|
17455 |
|
|
always assumes the values are signed, so we output all
|
17456 |
|
|
values as if they were signed. That means that
|
17457 |
|
|
enumeration constants with very large unsigned values
|
17458 |
|
|
will appear to have negative values in the debugger. */
|
17459 |
|
|
add_AT_int (enum_die, DW_AT_const_value,
|
17460 |
|
|
tree_low_cst (value, tree_int_cst_sgn (value) > 0));
|
17461 |
|
|
}
|
17462 |
|
|
}
|
17463 |
|
|
else
|
17464 |
|
|
add_AT_flag (type_die, DW_AT_declaration, 1);
|
17465 |
|
|
|
17466 |
|
|
if (get_AT (type_die, DW_AT_name))
|
17467 |
|
|
add_pubtype (type, type_die);
|
17468 |
|
|
|
17469 |
|
|
return type_die;
|
17470 |
|
|
}
|
17471 |
|
|
|
17472 |
|
|
/* Generate a DIE to represent either a real live formal parameter decl or to
|
17473 |
|
|
represent just the type of some formal parameter position in some function
|
17474 |
|
|
type.
|
17475 |
|
|
|
17476 |
|
|
Note that this routine is a bit unusual because its argument may be a
|
17477 |
|
|
..._DECL node (i.e. either a PARM_DECL or perhaps a VAR_DECL which
|
17478 |
|
|
represents an inlining of some PARM_DECL) or else some sort of a ..._TYPE
|
17479 |
|
|
node. If it's the former then this function is being called to output a
|
17480 |
|
|
DIE to represent a formal parameter object (or some inlining thereof). If
|
17481 |
|
|
it's the latter, then this function is only being called to output a
|
17482 |
|
|
DW_TAG_formal_parameter DIE to stand as a placeholder for some formal
|
17483 |
|
|
argument type of some subprogram type.
|
17484 |
|
|
If EMIT_NAME_P is true, name and source coordinate attributes
|
17485 |
|
|
are emitted. */
|
17486 |
|
|
|
17487 |
|
|
static dw_die_ref
|
17488 |
|
|
gen_formal_parameter_die (tree node, tree origin, bool emit_name_p,
|
17489 |
|
|
dw_die_ref context_die)
|
17490 |
|
|
{
|
17491 |
|
|
tree node_or_origin = node ? node : origin;
|
17492 |
|
|
tree ultimate_origin;
|
17493 |
|
|
dw_die_ref parm_die
|
17494 |
|
|
= new_die (DW_TAG_formal_parameter, context_die, node);
|
17495 |
|
|
|
17496 |
|
|
switch (TREE_CODE_CLASS (TREE_CODE (node_or_origin)))
|
17497 |
|
|
{
|
17498 |
|
|
case tcc_declaration:
|
17499 |
|
|
ultimate_origin = decl_ultimate_origin (node_or_origin);
|
17500 |
|
|
if (node || ultimate_origin)
|
17501 |
|
|
origin = ultimate_origin;
|
17502 |
|
|
if (origin != NULL)
|
17503 |
|
|
add_abstract_origin_attribute (parm_die, origin);
|
17504 |
|
|
else
|
17505 |
|
|
{
|
17506 |
|
|
tree type = TREE_TYPE (node);
|
17507 |
|
|
if (emit_name_p)
|
17508 |
|
|
add_name_and_src_coords_attributes (parm_die, node);
|
17509 |
|
|
if (decl_by_reference_p (node))
|
17510 |
|
|
add_type_attribute (parm_die, TREE_TYPE (type), 0, 0,
|
17511 |
|
|
context_die);
|
17512 |
|
|
else
|
17513 |
|
|
add_type_attribute (parm_die, type,
|
17514 |
|
|
TREE_READONLY (node),
|
17515 |
|
|
TREE_THIS_VOLATILE (node),
|
17516 |
|
|
context_die);
|
17517 |
|
|
if (DECL_ARTIFICIAL (node))
|
17518 |
|
|
add_AT_flag (parm_die, DW_AT_artificial, 1);
|
17519 |
|
|
}
|
17520 |
|
|
|
17521 |
|
|
if (node && node != origin)
|
17522 |
|
|
equate_decl_number_to_die (node, parm_die);
|
17523 |
|
|
if (! DECL_ABSTRACT (node_or_origin))
|
17524 |
|
|
add_location_or_const_value_attribute (parm_die, node_or_origin,
|
17525 |
|
|
DW_AT_location);
|
17526 |
|
|
|
17527 |
|
|
break;
|
17528 |
|
|
|
17529 |
|
|
case tcc_type:
|
17530 |
|
|
/* We were called with some kind of a ..._TYPE node. */
|
17531 |
|
|
add_type_attribute (parm_die, node_or_origin, 0, 0, context_die);
|
17532 |
|
|
break;
|
17533 |
|
|
|
17534 |
|
|
default:
|
17535 |
|
|
gcc_unreachable ();
|
17536 |
|
|
}
|
17537 |
|
|
|
17538 |
|
|
return parm_die;
|
17539 |
|
|
}
|
17540 |
|
|
|
17541 |
|
|
/* Generate and return a DW_TAG_GNU_formal_parameter_pack. Also generate
|
17542 |
|
|
children DW_TAG_formal_parameter DIEs representing the arguments of the
|
17543 |
|
|
parameter pack.
|
17544 |
|
|
|
17545 |
|
|
PARM_PACK must be a function parameter pack.
|
17546 |
|
|
PACK_ARG is the first argument of the parameter pack. Its TREE_CHAIN
|
17547 |
|
|
must point to the subsequent arguments of the function PACK_ARG belongs to.
|
17548 |
|
|
SUBR_DIE is the DIE of the function PACK_ARG belongs to.
|
17549 |
|
|
If NEXT_ARG is non NULL, *NEXT_ARG is set to the function argument
|
17550 |
|
|
following the last one for which a DIE was generated. */
|
17551 |
|
|
|
17552 |
|
|
static dw_die_ref
|
17553 |
|
|
gen_formal_parameter_pack_die (tree parm_pack,
|
17554 |
|
|
tree pack_arg,
|
17555 |
|
|
dw_die_ref subr_die,
|
17556 |
|
|
tree *next_arg)
|
17557 |
|
|
{
|
17558 |
|
|
tree arg;
|
17559 |
|
|
dw_die_ref parm_pack_die;
|
17560 |
|
|
|
17561 |
|
|
gcc_assert (parm_pack
|
17562 |
|
|
&& lang_hooks.function_parameter_pack_p (parm_pack)
|
17563 |
|
|
&& subr_die);
|
17564 |
|
|
|
17565 |
|
|
parm_pack_die = new_die (DW_TAG_GNU_formal_parameter_pack, subr_die, parm_pack);
|
17566 |
|
|
add_src_coords_attributes (parm_pack_die, parm_pack);
|
17567 |
|
|
|
17568 |
|
|
for (arg = pack_arg; arg; arg = TREE_CHAIN (arg))
|
17569 |
|
|
{
|
17570 |
|
|
if (! lang_hooks.decls.function_parm_expanded_from_pack_p (arg,
|
17571 |
|
|
parm_pack))
|
17572 |
|
|
break;
|
17573 |
|
|
gen_formal_parameter_die (arg, NULL,
|
17574 |
|
|
false /* Don't emit name attribute. */,
|
17575 |
|
|
parm_pack_die);
|
17576 |
|
|
}
|
17577 |
|
|
if (next_arg)
|
17578 |
|
|
*next_arg = arg;
|
17579 |
|
|
return parm_pack_die;
|
17580 |
|
|
}
|
17581 |
|
|
|
17582 |
|
|
/* Generate a special type of DIE used as a stand-in for a trailing ellipsis
|
17583 |
|
|
at the end of an (ANSI prototyped) formal parameters list. */
|
17584 |
|
|
|
17585 |
|
|
static void
|
17586 |
|
|
gen_unspecified_parameters_die (tree decl_or_type, dw_die_ref context_die)
|
17587 |
|
|
{
|
17588 |
|
|
new_die (DW_TAG_unspecified_parameters, context_die, decl_or_type);
|
17589 |
|
|
}
|
17590 |
|
|
|
17591 |
|
|
/* Generate a list of nameless DW_TAG_formal_parameter DIEs (and perhaps a
|
17592 |
|
|
DW_TAG_unspecified_parameters DIE) to represent the types of the formal
|
17593 |
|
|
parameters as specified in some function type specification (except for
|
17594 |
|
|
those which appear as part of a function *definition*). */
|
17595 |
|
|
|
17596 |
|
|
static void
|
17597 |
|
|
gen_formal_types_die (tree function_or_method_type, dw_die_ref context_die)
|
17598 |
|
|
{
|
17599 |
|
|
tree link;
|
17600 |
|
|
tree formal_type = NULL;
|
17601 |
|
|
tree first_parm_type;
|
17602 |
|
|
tree arg;
|
17603 |
|
|
|
17604 |
|
|
if (TREE_CODE (function_or_method_type) == FUNCTION_DECL)
|
17605 |
|
|
{
|
17606 |
|
|
arg = DECL_ARGUMENTS (function_or_method_type);
|
17607 |
|
|
function_or_method_type = TREE_TYPE (function_or_method_type);
|
17608 |
|
|
}
|
17609 |
|
|
else
|
17610 |
|
|
arg = NULL_TREE;
|
17611 |
|
|
|
17612 |
|
|
first_parm_type = TYPE_ARG_TYPES (function_or_method_type);
|
17613 |
|
|
|
17614 |
|
|
/* Make our first pass over the list of formal parameter types and output a
|
17615 |
|
|
DW_TAG_formal_parameter DIE for each one. */
|
17616 |
|
|
for (link = first_parm_type; link; )
|
17617 |
|
|
{
|
17618 |
|
|
dw_die_ref parm_die;
|
17619 |
|
|
|
17620 |
|
|
formal_type = TREE_VALUE (link);
|
17621 |
|
|
if (formal_type == void_type_node)
|
17622 |
|
|
break;
|
17623 |
|
|
|
17624 |
|
|
/* Output a (nameless) DIE to represent the formal parameter itself. */
|
17625 |
|
|
parm_die = gen_formal_parameter_die (formal_type, NULL,
|
17626 |
|
|
true /* Emit name attribute. */,
|
17627 |
|
|
context_die);
|
17628 |
|
|
if ((TREE_CODE (function_or_method_type) == METHOD_TYPE
|
17629 |
|
|
&& link == first_parm_type)
|
17630 |
|
|
|| (arg && DECL_ARTIFICIAL (arg)))
|
17631 |
|
|
add_AT_flag (parm_die, DW_AT_artificial, 1);
|
17632 |
|
|
|
17633 |
|
|
link = TREE_CHAIN (link);
|
17634 |
|
|
if (arg)
|
17635 |
|
|
arg = TREE_CHAIN (arg);
|
17636 |
|
|
}
|
17637 |
|
|
|
17638 |
|
|
/* If this function type has an ellipsis, add a
|
17639 |
|
|
DW_TAG_unspecified_parameters DIE to the end of the parameter list. */
|
17640 |
|
|
if (formal_type != void_type_node)
|
17641 |
|
|
gen_unspecified_parameters_die (function_or_method_type, context_die);
|
17642 |
|
|
|
17643 |
|
|
/* Make our second (and final) pass over the list of formal parameter types
|
17644 |
|
|
and output DIEs to represent those types (as necessary). */
|
17645 |
|
|
for (link = TYPE_ARG_TYPES (function_or_method_type);
|
17646 |
|
|
link && TREE_VALUE (link);
|
17647 |
|
|
link = TREE_CHAIN (link))
|
17648 |
|
|
gen_type_die (TREE_VALUE (link), context_die);
|
17649 |
|
|
}
|
17650 |
|
|
|
17651 |
|
|
/* We want to generate the DIE for TYPE so that we can generate the
|
17652 |
|
|
die for MEMBER, which has been defined; we will need to refer back
|
17653 |
|
|
to the member declaration nested within TYPE. If we're trying to
|
17654 |
|
|
generate minimal debug info for TYPE, processing TYPE won't do the
|
17655 |
|
|
trick; we need to attach the member declaration by hand. */
|
17656 |
|
|
|
17657 |
|
|
static void
|
17658 |
|
|
gen_type_die_for_member (tree type, tree member, dw_die_ref context_die)
|
17659 |
|
|
{
|
17660 |
|
|
gen_type_die (type, context_die);
|
17661 |
|
|
|
17662 |
|
|
/* If we're trying to avoid duplicate debug info, we may not have
|
17663 |
|
|
emitted the member decl for this function. Emit it now. */
|
17664 |
|
|
if (TYPE_STUB_DECL (type)
|
17665 |
|
|
&& TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type))
|
17666 |
|
|
&& ! lookup_decl_die (member))
|
17667 |
|
|
{
|
17668 |
|
|
dw_die_ref type_die;
|
17669 |
|
|
gcc_assert (!decl_ultimate_origin (member));
|
17670 |
|
|
|
17671 |
|
|
push_decl_scope (type);
|
17672 |
|
|
type_die = lookup_type_die (type);
|
17673 |
|
|
if (TREE_CODE (member) == FUNCTION_DECL)
|
17674 |
|
|
gen_subprogram_die (member, type_die);
|
17675 |
|
|
else if (TREE_CODE (member) == FIELD_DECL)
|
17676 |
|
|
{
|
17677 |
|
|
/* Ignore the nameless fields that are used to skip bits but handle
|
17678 |
|
|
C++ anonymous unions and structs. */
|
17679 |
|
|
if (DECL_NAME (member) != NULL_TREE
|
17680 |
|
|
|| TREE_CODE (TREE_TYPE (member)) == UNION_TYPE
|
17681 |
|
|
|| TREE_CODE (TREE_TYPE (member)) == RECORD_TYPE)
|
17682 |
|
|
{
|
17683 |
|
|
gen_type_die (member_declared_type (member), type_die);
|
17684 |
|
|
gen_field_die (member, type_die);
|
17685 |
|
|
}
|
17686 |
|
|
}
|
17687 |
|
|
else
|
17688 |
|
|
gen_variable_die (member, NULL_TREE, type_die);
|
17689 |
|
|
|
17690 |
|
|
pop_decl_scope ();
|
17691 |
|
|
}
|
17692 |
|
|
}
|
17693 |
|
|
|
17694 |
|
|
/* Generate the DWARF2 info for the "abstract" instance of a function which we
|
17695 |
|
|
may later generate inlined and/or out-of-line instances of. */
|
17696 |
|
|
|
17697 |
|
|
static void
|
17698 |
|
|
dwarf2out_abstract_function (tree decl)
|
17699 |
|
|
{
|
17700 |
|
|
dw_die_ref old_die;
|
17701 |
|
|
tree save_fn;
|
17702 |
|
|
tree context;
|
17703 |
|
|
int was_abstract;
|
17704 |
|
|
htab_t old_decl_loc_table;
|
17705 |
|
|
|
17706 |
|
|
/* Make sure we have the actual abstract inline, not a clone. */
|
17707 |
|
|
decl = DECL_ORIGIN (decl);
|
17708 |
|
|
|
17709 |
|
|
old_die = lookup_decl_die (decl);
|
17710 |
|
|
if (old_die && get_AT (old_die, DW_AT_inline))
|
17711 |
|
|
/* We've already generated the abstract instance. */
|
17712 |
|
|
return;
|
17713 |
|
|
|
17714 |
|
|
/* We can be called while recursively when seeing block defining inlined subroutine
|
17715 |
|
|
DIE. Be sure to not clobber the outer location table nor use it or we would
|
17716 |
|
|
get locations in abstract instantces. */
|
17717 |
|
|
old_decl_loc_table = decl_loc_table;
|
17718 |
|
|
decl_loc_table = NULL;
|
17719 |
|
|
|
17720 |
|
|
/* Be sure we've emitted the in-class declaration DIE (if any) first, so
|
17721 |
|
|
we don't get confused by DECL_ABSTRACT. */
|
17722 |
|
|
if (debug_info_level > DINFO_LEVEL_TERSE)
|
17723 |
|
|
{
|
17724 |
|
|
context = decl_class_context (decl);
|
17725 |
|
|
if (context)
|
17726 |
|
|
gen_type_die_for_member
|
17727 |
|
|
(context, decl, decl_function_context (decl) ? NULL : comp_unit_die);
|
17728 |
|
|
}
|
17729 |
|
|
|
17730 |
|
|
/* Pretend we've just finished compiling this function. */
|
17731 |
|
|
save_fn = current_function_decl;
|
17732 |
|
|
current_function_decl = decl;
|
17733 |
|
|
push_cfun (DECL_STRUCT_FUNCTION (decl));
|
17734 |
|
|
|
17735 |
|
|
was_abstract = DECL_ABSTRACT (decl);
|
17736 |
|
|
set_decl_abstract_flags (decl, 1);
|
17737 |
|
|
dwarf2out_decl (decl);
|
17738 |
|
|
if (! was_abstract)
|
17739 |
|
|
set_decl_abstract_flags (decl, 0);
|
17740 |
|
|
|
17741 |
|
|
current_function_decl = save_fn;
|
17742 |
|
|
decl_loc_table = old_decl_loc_table;
|
17743 |
|
|
pop_cfun ();
|
17744 |
|
|
}
|
17745 |
|
|
|
17746 |
|
|
/* Helper function of premark_used_types() which gets called through
|
17747 |
|
|
htab_traverse.
|
17748 |
|
|
|
17749 |
|
|
Marks the DIE of a given type in *SLOT as perennial, so it never gets
|
17750 |
|
|
marked as unused by prune_unused_types. */
|
17751 |
|
|
|
17752 |
|
|
static int
|
17753 |
|
|
premark_used_types_helper (void **slot, void *data ATTRIBUTE_UNUSED)
|
17754 |
|
|
{
|
17755 |
|
|
tree type;
|
17756 |
|
|
dw_die_ref die;
|
17757 |
|
|
|
17758 |
|
|
type = (tree) *slot;
|
17759 |
|
|
die = lookup_type_die (type);
|
17760 |
|
|
if (die != NULL)
|
17761 |
|
|
die->die_perennial_p = 1;
|
17762 |
|
|
return 1;
|
17763 |
|
|
}
|
17764 |
|
|
|
17765 |
|
|
/* Helper function of premark_types_used_by_global_vars which gets called
|
17766 |
|
|
through htab_traverse.
|
17767 |
|
|
|
17768 |
|
|
Marks the DIE of a given type in *SLOT as perennial, so it never gets
|
17769 |
|
|
marked as unused by prune_unused_types. The DIE of the type is marked
|
17770 |
|
|
only if the global variable using the type will actually be emitted. */
|
17771 |
|
|
|
17772 |
|
|
static int
|
17773 |
|
|
premark_types_used_by_global_vars_helper (void **slot,
|
17774 |
|
|
void *data ATTRIBUTE_UNUSED)
|
17775 |
|
|
{
|
17776 |
|
|
struct types_used_by_vars_entry *entry;
|
17777 |
|
|
dw_die_ref die;
|
17778 |
|
|
|
17779 |
|
|
entry = (struct types_used_by_vars_entry *) *slot;
|
17780 |
|
|
gcc_assert (entry->type != NULL
|
17781 |
|
|
&& entry->var_decl != NULL);
|
17782 |
|
|
die = lookup_type_die (entry->type);
|
17783 |
|
|
if (die)
|
17784 |
|
|
{
|
17785 |
|
|
/* Ask cgraph if the global variable really is to be emitted.
|
17786 |
|
|
If yes, then we'll keep the DIE of ENTRY->TYPE. */
|
17787 |
|
|
struct varpool_node *node = varpool_node (entry->var_decl);
|
17788 |
|
|
if (node->needed)
|
17789 |
|
|
{
|
17790 |
|
|
die->die_perennial_p = 1;
|
17791 |
|
|
/* Keep the parent DIEs as well. */
|
17792 |
|
|
while ((die = die->die_parent) && die->die_perennial_p == 0)
|
17793 |
|
|
die->die_perennial_p = 1;
|
17794 |
|
|
}
|
17795 |
|
|
}
|
17796 |
|
|
return 1;
|
17797 |
|
|
}
|
17798 |
|
|
|
17799 |
|
|
/* Mark all members of used_types_hash as perennial. */
|
17800 |
|
|
|
17801 |
|
|
static void
|
17802 |
|
|
premark_used_types (void)
|
17803 |
|
|
{
|
17804 |
|
|
if (cfun && cfun->used_types_hash)
|
17805 |
|
|
htab_traverse (cfun->used_types_hash, premark_used_types_helper, NULL);
|
17806 |
|
|
}
|
17807 |
|
|
|
17808 |
|
|
/* Mark all members of types_used_by_vars_entry as perennial. */
|
17809 |
|
|
|
17810 |
|
|
static void
|
17811 |
|
|
premark_types_used_by_global_vars (void)
|
17812 |
|
|
{
|
17813 |
|
|
if (types_used_by_vars_hash)
|
17814 |
|
|
htab_traverse (types_used_by_vars_hash,
|
17815 |
|
|
premark_types_used_by_global_vars_helper, NULL);
|
17816 |
|
|
}
|
17817 |
|
|
|
17818 |
|
|
/* Generate a DIE to represent a declared function (either file-scope or
|
17819 |
|
|
block-local). */
|
17820 |
|
|
|
17821 |
|
|
static void
|
17822 |
|
|
gen_subprogram_die (tree decl, dw_die_ref context_die)
|
17823 |
|
|
{
|
17824 |
|
|
char label_id[MAX_ARTIFICIAL_LABEL_BYTES];
|
17825 |
|
|
tree origin = decl_ultimate_origin (decl);
|
17826 |
|
|
dw_die_ref subr_die;
|
17827 |
|
|
tree fn_arg_types;
|
17828 |
|
|
tree outer_scope;
|
17829 |
|
|
dw_die_ref old_die = lookup_decl_die (decl);
|
17830 |
|
|
int declaration = (current_function_decl != decl
|
17831 |
|
|
|| class_or_namespace_scope_p (context_die));
|
17832 |
|
|
|
17833 |
|
|
premark_used_types ();
|
17834 |
|
|
|
17835 |
|
|
/* It is possible to have both DECL_ABSTRACT and DECLARATION be true if we
|
17836 |
|
|
started to generate the abstract instance of an inline, decided to output
|
17837 |
|
|
its containing class, and proceeded to emit the declaration of the inline
|
17838 |
|
|
from the member list for the class. If so, DECLARATION takes priority;
|
17839 |
|
|
we'll get back to the abstract instance when done with the class. */
|
17840 |
|
|
|
17841 |
|
|
/* The class-scope declaration DIE must be the primary DIE. */
|
17842 |
|
|
if (origin && declaration && class_or_namespace_scope_p (context_die))
|
17843 |
|
|
{
|
17844 |
|
|
origin = NULL;
|
17845 |
|
|
gcc_assert (!old_die);
|
17846 |
|
|
}
|
17847 |
|
|
|
17848 |
|
|
/* Now that the C++ front end lazily declares artificial member fns, we
|
17849 |
|
|
might need to retrofit the declaration into its class. */
|
17850 |
|
|
if (!declaration && !origin && !old_die
|
17851 |
|
|
&& DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl))
|
17852 |
|
|
&& !class_or_namespace_scope_p (context_die)
|
17853 |
|
|
&& debug_info_level > DINFO_LEVEL_TERSE)
|
17854 |
|
|
old_die = force_decl_die (decl);
|
17855 |
|
|
|
17856 |
|
|
if (origin != NULL)
|
17857 |
|
|
{
|
17858 |
|
|
gcc_assert (!declaration || local_scope_p (context_die));
|
17859 |
|
|
|
17860 |
|
|
/* Fixup die_parent for the abstract instance of a nested
|
17861 |
|
|
inline function. */
|
17862 |
|
|
if (old_die && old_die->die_parent == NULL)
|
17863 |
|
|
add_child_die (context_die, old_die);
|
17864 |
|
|
|
17865 |
|
|
subr_die = new_die (DW_TAG_subprogram, context_die, decl);
|
17866 |
|
|
add_abstract_origin_attribute (subr_die, origin);
|
17867 |
|
|
}
|
17868 |
|
|
else if (old_die)
|
17869 |
|
|
{
|
17870 |
|
|
expanded_location s = expand_location (DECL_SOURCE_LOCATION (decl));
|
17871 |
|
|
struct dwarf_file_data * file_index = lookup_filename (s.file);
|
17872 |
|
|
|
17873 |
|
|
if (!get_AT_flag (old_die, DW_AT_declaration)
|
17874 |
|
|
/* We can have a normal definition following an inline one in the
|
17875 |
|
|
case of redefinition of GNU C extern inlines.
|
17876 |
|
|
It seems reasonable to use AT_specification in this case. */
|
17877 |
|
|
&& !get_AT (old_die, DW_AT_inline))
|
17878 |
|
|
{
|
17879 |
|
|
/* Detect and ignore this case, where we are trying to output
|
17880 |
|
|
something we have already output. */
|
17881 |
|
|
return;
|
17882 |
|
|
}
|
17883 |
|
|
|
17884 |
|
|
/* If the definition comes from the same place as the declaration,
|
17885 |
|
|
maybe use the old DIE. We always want the DIE for this function
|
17886 |
|
|
that has the *_pc attributes to be under comp_unit_die so the
|
17887 |
|
|
debugger can find it. We also need to do this for abstract
|
17888 |
|
|
instances of inlines, since the spec requires the out-of-line copy
|
17889 |
|
|
to have the same parent. For local class methods, this doesn't
|
17890 |
|
|
apply; we just use the old DIE. */
|
17891 |
|
|
if ((old_die->die_parent == comp_unit_die || context_die == NULL)
|
17892 |
|
|
&& (DECL_ARTIFICIAL (decl)
|
17893 |
|
|
|| (get_AT_file (old_die, DW_AT_decl_file) == file_index
|
17894 |
|
|
&& (get_AT_unsigned (old_die, DW_AT_decl_line)
|
17895 |
|
|
== (unsigned) s.line))))
|
17896 |
|
|
{
|
17897 |
|
|
subr_die = old_die;
|
17898 |
|
|
|
17899 |
|
|
/* Clear out the declaration attribute and the formal parameters.
|
17900 |
|
|
Do not remove all children, because it is possible that this
|
17901 |
|
|
declaration die was forced using force_decl_die(). In such
|
17902 |
|
|
cases die that forced declaration die (e.g. TAG_imported_module)
|
17903 |
|
|
is one of the children that we do not want to remove. */
|
17904 |
|
|
remove_AT (subr_die, DW_AT_declaration);
|
17905 |
|
|
remove_child_TAG (subr_die, DW_TAG_formal_parameter);
|
17906 |
|
|
}
|
17907 |
|
|
else
|
17908 |
|
|
{
|
17909 |
|
|
subr_die = new_die (DW_TAG_subprogram, context_die, decl);
|
17910 |
|
|
add_AT_specification (subr_die, old_die);
|
17911 |
|
|
if (get_AT_file (old_die, DW_AT_decl_file) != file_index)
|
17912 |
|
|
add_AT_file (subr_die, DW_AT_decl_file, file_index);
|
17913 |
|
|
if (get_AT_unsigned (old_die, DW_AT_decl_line) != (unsigned) s.line)
|
17914 |
|
|
add_AT_unsigned (subr_die, DW_AT_decl_line, s.line);
|
17915 |
|
|
}
|
17916 |
|
|
}
|
17917 |
|
|
else
|
17918 |
|
|
{
|
17919 |
|
|
subr_die = new_die (DW_TAG_subprogram, context_die, decl);
|
17920 |
|
|
|
17921 |
|
|
if (TREE_PUBLIC (decl))
|
17922 |
|
|
add_AT_flag (subr_die, DW_AT_external, 1);
|
17923 |
|
|
|
17924 |
|
|
add_name_and_src_coords_attributes (subr_die, decl);
|
17925 |
|
|
if (debug_info_level > DINFO_LEVEL_TERSE)
|
17926 |
|
|
{
|
17927 |
|
|
add_prototyped_attribute (subr_die, TREE_TYPE (decl));
|
17928 |
|
|
add_type_attribute (subr_die, TREE_TYPE (TREE_TYPE (decl)),
|
17929 |
|
|
0, 0, context_die);
|
17930 |
|
|
}
|
17931 |
|
|
|
17932 |
|
|
add_pure_or_virtual_attribute (subr_die, decl);
|
17933 |
|
|
if (DECL_ARTIFICIAL (decl))
|
17934 |
|
|
add_AT_flag (subr_die, DW_AT_artificial, 1);
|
17935 |
|
|
|
17936 |
|
|
if (TREE_PROTECTED (decl))
|
17937 |
|
|
add_AT_unsigned (subr_die, DW_AT_accessibility, DW_ACCESS_protected);
|
17938 |
|
|
else if (TREE_PRIVATE (decl))
|
17939 |
|
|
add_AT_unsigned (subr_die, DW_AT_accessibility, DW_ACCESS_private);
|
17940 |
|
|
}
|
17941 |
|
|
|
17942 |
|
|
if (declaration)
|
17943 |
|
|
{
|
17944 |
|
|
if (!old_die || !get_AT (old_die, DW_AT_inline))
|
17945 |
|
|
{
|
17946 |
|
|
add_AT_flag (subr_die, DW_AT_declaration, 1);
|
17947 |
|
|
|
17948 |
|
|
/* If this is an explicit function declaration then generate
|
17949 |
|
|
a DW_AT_explicit attribute. */
|
17950 |
|
|
if (lang_hooks.decls.function_decl_explicit_p (decl)
|
17951 |
|
|
&& (dwarf_version >= 3 || !dwarf_strict))
|
17952 |
|
|
add_AT_flag (subr_die, DW_AT_explicit, 1);
|
17953 |
|
|
|
17954 |
|
|
/* The first time we see a member function, it is in the context of
|
17955 |
|
|
the class to which it belongs. We make sure of this by emitting
|
17956 |
|
|
the class first. The next time is the definition, which is
|
17957 |
|
|
handled above. The two may come from the same source text.
|
17958 |
|
|
|
17959 |
|
|
Note that force_decl_die() forces function declaration die. It is
|
17960 |
|
|
later reused to represent definition. */
|
17961 |
|
|
equate_decl_number_to_die (decl, subr_die);
|
17962 |
|
|
}
|
17963 |
|
|
}
|
17964 |
|
|
else if (DECL_ABSTRACT (decl))
|
17965 |
|
|
{
|
17966 |
|
|
if (DECL_DECLARED_INLINE_P (decl))
|
17967 |
|
|
{
|
17968 |
|
|
if (cgraph_function_possibly_inlined_p (decl))
|
17969 |
|
|
add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_declared_inlined);
|
17970 |
|
|
else
|
17971 |
|
|
add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_declared_not_inlined);
|
17972 |
|
|
}
|
17973 |
|
|
else
|
17974 |
|
|
{
|
17975 |
|
|
if (cgraph_function_possibly_inlined_p (decl))
|
17976 |
|
|
add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_inlined);
|
17977 |
|
|
else
|
17978 |
|
|
add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_not_inlined);
|
17979 |
|
|
}
|
17980 |
|
|
|
17981 |
|
|
if (DECL_DECLARED_INLINE_P (decl)
|
17982 |
|
|
&& lookup_attribute ("artificial", DECL_ATTRIBUTES (decl)))
|
17983 |
|
|
add_AT_flag (subr_die, DW_AT_artificial, 1);
|
17984 |
|
|
|
17985 |
|
|
equate_decl_number_to_die (decl, subr_die);
|
17986 |
|
|
}
|
17987 |
|
|
else if (!DECL_EXTERNAL (decl))
|
17988 |
|
|
{
|
17989 |
|
|
HOST_WIDE_INT cfa_fb_offset;
|
17990 |
|
|
|
17991 |
|
|
if (!old_die || !get_AT (old_die, DW_AT_inline))
|
17992 |
|
|
equate_decl_number_to_die (decl, subr_die);
|
17993 |
|
|
|
17994 |
|
|
if (!flag_reorder_blocks_and_partition)
|
17995 |
|
|
{
|
17996 |
|
|
ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_BEGIN_LABEL,
|
17997 |
|
|
current_function_funcdef_no);
|
17998 |
|
|
add_AT_lbl_id (subr_die, DW_AT_low_pc, label_id);
|
17999 |
|
|
ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL,
|
18000 |
|
|
current_function_funcdef_no);
|
18001 |
|
|
add_AT_lbl_id (subr_die, DW_AT_high_pc, label_id);
|
18002 |
|
|
|
18003 |
|
|
add_pubname (decl, subr_die);
|
18004 |
|
|
add_arange (decl, subr_die);
|
18005 |
|
|
}
|
18006 |
|
|
else
|
18007 |
|
|
{ /* Do nothing for now; maybe need to duplicate die, one for
|
18008 |
|
|
hot section and one for cold section, then use the hot/cold
|
18009 |
|
|
section begin/end labels to generate the aranges... */
|
18010 |
|
|
/*
|
18011 |
|
|
add_AT_lbl_id (subr_die, DW_AT_low_pc, hot_section_label);
|
18012 |
|
|
add_AT_lbl_id (subr_die, DW_AT_high_pc, hot_section_end_label);
|
18013 |
|
|
add_AT_lbl_id (subr_die, DW_AT_lo_user, unlikely_section_label);
|
18014 |
|
|
add_AT_lbl_id (subr_die, DW_AT_hi_user, cold_section_end_label);
|
18015 |
|
|
|
18016 |
|
|
add_pubname (decl, subr_die);
|
18017 |
|
|
add_arange (decl, subr_die);
|
18018 |
|
|
add_arange (decl, subr_die);
|
18019 |
|
|
*/
|
18020 |
|
|
}
|
18021 |
|
|
|
18022 |
|
|
#ifdef MIPS_DEBUGGING_INFO
|
18023 |
|
|
/* Add a reference to the FDE for this routine. */
|
18024 |
|
|
add_AT_fde_ref (subr_die, DW_AT_MIPS_fde, current_funcdef_fde);
|
18025 |
|
|
#endif
|
18026 |
|
|
|
18027 |
|
|
cfa_fb_offset = CFA_FRAME_BASE_OFFSET (decl);
|
18028 |
|
|
|
18029 |
|
|
/* We define the "frame base" as the function's CFA. This is more
|
18030 |
|
|
convenient for several reasons: (1) It's stable across the prologue
|
18031 |
|
|
and epilogue, which makes it better than just a frame pointer,
|
18032 |
|
|
(2) With dwarf3, there exists a one-byte encoding that allows us
|
18033 |
|
|
to reference the .debug_frame data by proxy, but failing that,
|
18034 |
|
|
(3) We can at least reuse the code inspection and interpretation
|
18035 |
|
|
code that determines the CFA position at various points in the
|
18036 |
|
|
function. */
|
18037 |
|
|
if (dwarf_version >= 3)
|
18038 |
|
|
{
|
18039 |
|
|
dw_loc_descr_ref op = new_loc_descr (DW_OP_call_frame_cfa, 0, 0);
|
18040 |
|
|
add_AT_loc (subr_die, DW_AT_frame_base, op);
|
18041 |
|
|
}
|
18042 |
|
|
else
|
18043 |
|
|
{
|
18044 |
|
|
dw_loc_list_ref list = convert_cfa_to_fb_loc_list (cfa_fb_offset);
|
18045 |
|
|
if (list->dw_loc_next)
|
18046 |
|
|
add_AT_loc_list (subr_die, DW_AT_frame_base, list);
|
18047 |
|
|
else
|
18048 |
|
|
add_AT_loc (subr_die, DW_AT_frame_base, list->expr);
|
18049 |
|
|
}
|
18050 |
|
|
|
18051 |
|
|
/* Compute a displacement from the "steady-state frame pointer" to
|
18052 |
|
|
the CFA. The former is what all stack slots and argument slots
|
18053 |
|
|
will reference in the rtl; the later is what we've told the
|
18054 |
|
|
debugger about. We'll need to adjust all frame_base references
|
18055 |
|
|
by this displacement. */
|
18056 |
|
|
compute_frame_pointer_to_fb_displacement (cfa_fb_offset);
|
18057 |
|
|
|
18058 |
|
|
if (cfun->static_chain_decl)
|
18059 |
|
|
add_AT_location_description (subr_die, DW_AT_static_link,
|
18060 |
|
|
loc_list_from_tree (cfun->static_chain_decl, 2));
|
18061 |
|
|
}
|
18062 |
|
|
|
18063 |
|
|
/* Generate child dies for template paramaters. */
|
18064 |
|
|
if (debug_info_level > DINFO_LEVEL_TERSE)
|
18065 |
|
|
gen_generic_params_dies (decl);
|
18066 |
|
|
|
18067 |
|
|
/* Now output descriptions of the arguments for this function. This gets
|
18068 |
|
|
(unnecessarily?) complex because of the fact that the DECL_ARGUMENT list
|
18069 |
|
|
for a FUNCTION_DECL doesn't indicate cases where there was a trailing
|
18070 |
|
|
`...' at the end of the formal parameter list. In order to find out if
|
18071 |
|
|
there was a trailing ellipsis or not, we must instead look at the type
|
18072 |
|
|
associated with the FUNCTION_DECL. This will be a node of type
|
18073 |
|
|
FUNCTION_TYPE. If the chain of type nodes hanging off of this
|
18074 |
|
|
FUNCTION_TYPE node ends with a void_type_node then there should *not* be
|
18075 |
|
|
an ellipsis at the end. */
|
18076 |
|
|
|
18077 |
|
|
/* In the case where we are describing a mere function declaration, all we
|
18078 |
|
|
need to do here (and all we *can* do here) is to describe the *types* of
|
18079 |
|
|
its formal parameters. */
|
18080 |
|
|
if (debug_info_level <= DINFO_LEVEL_TERSE)
|
18081 |
|
|
;
|
18082 |
|
|
else if (declaration)
|
18083 |
|
|
gen_formal_types_die (decl, subr_die);
|
18084 |
|
|
else
|
18085 |
|
|
{
|
18086 |
|
|
/* Generate DIEs to represent all known formal parameters. */
|
18087 |
|
|
tree parm = DECL_ARGUMENTS (decl);
|
18088 |
|
|
tree generic_decl = lang_hooks.decls.get_generic_function_decl (decl);
|
18089 |
|
|
tree generic_decl_parm = generic_decl
|
18090 |
|
|
? DECL_ARGUMENTS (generic_decl)
|
18091 |
|
|
: NULL;
|
18092 |
|
|
|
18093 |
|
|
/* Now we want to walk the list of parameters of the function and
|
18094 |
|
|
emit their relevant DIEs.
|
18095 |
|
|
|
18096 |
|
|
We consider the case of DECL being an instance of a generic function
|
18097 |
|
|
as well as it being a normal function.
|
18098 |
|
|
|
18099 |
|
|
If DECL is an instance of a generic function we walk the
|
18100 |
|
|
parameters of the generic function declaration _and_ the parameters of
|
18101 |
|
|
DECL itself. This is useful because we want to emit specific DIEs for
|
18102 |
|
|
function parameter packs and those are declared as part of the
|
18103 |
|
|
generic function declaration. In that particular case,
|
18104 |
|
|
the parameter pack yields a DW_TAG_GNU_formal_parameter_pack DIE.
|
18105 |
|
|
That DIE has children DIEs representing the set of arguments
|
18106 |
|
|
of the pack. Note that the set of pack arguments can be empty.
|
18107 |
|
|
In that case, the DW_TAG_GNU_formal_parameter_pack DIE will not have any
|
18108 |
|
|
children DIE.
|
18109 |
|
|
|
18110 |
|
|
Otherwise, we just consider the parameters of DECL. */
|
18111 |
|
|
while (generic_decl_parm || parm)
|
18112 |
|
|
{
|
18113 |
|
|
if (generic_decl_parm
|
18114 |
|
|
&& lang_hooks.function_parameter_pack_p (generic_decl_parm))
|
18115 |
|
|
gen_formal_parameter_pack_die (generic_decl_parm,
|
18116 |
|
|
parm, subr_die,
|
18117 |
|
|
&parm);
|
18118 |
|
|
else if (parm)
|
18119 |
|
|
{
|
18120 |
|
|
gen_decl_die (parm, NULL, subr_die);
|
18121 |
|
|
parm = TREE_CHAIN (parm);
|
18122 |
|
|
}
|
18123 |
|
|
|
18124 |
|
|
if (generic_decl_parm)
|
18125 |
|
|
generic_decl_parm = TREE_CHAIN (generic_decl_parm);
|
18126 |
|
|
}
|
18127 |
|
|
|
18128 |
|
|
/* Decide whether we need an unspecified_parameters DIE at the end.
|
18129 |
|
|
There are 2 more cases to do this for: 1) the ansi ... declaration -
|
18130 |
|
|
this is detectable when the end of the arg list is not a
|
18131 |
|
|
void_type_node 2) an unprototyped function declaration (not a
|
18132 |
|
|
definition). This just means that we have no info about the
|
18133 |
|
|
parameters at all. */
|
18134 |
|
|
fn_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl));
|
18135 |
|
|
if (fn_arg_types != NULL)
|
18136 |
|
|
{
|
18137 |
|
|
/* This is the prototyped case, check for.... */
|
18138 |
|
|
if (TREE_VALUE (tree_last (fn_arg_types)) != void_type_node)
|
18139 |
|
|
gen_unspecified_parameters_die (decl, subr_die);
|
18140 |
|
|
}
|
18141 |
|
|
else if (DECL_INITIAL (decl) == NULL_TREE)
|
18142 |
|
|
gen_unspecified_parameters_die (decl, subr_die);
|
18143 |
|
|
}
|
18144 |
|
|
|
18145 |
|
|
/* Output Dwarf info for all of the stuff within the body of the function
|
18146 |
|
|
(if it has one - it may be just a declaration). */
|
18147 |
|
|
outer_scope = DECL_INITIAL (decl);
|
18148 |
|
|
|
18149 |
|
|
/* OUTER_SCOPE is a pointer to the outermost BLOCK node created to represent
|
18150 |
|
|
a function. This BLOCK actually represents the outermost binding contour
|
18151 |
|
|
for the function, i.e. the contour in which the function's formal
|
18152 |
|
|
parameters and labels get declared. Curiously, it appears that the front
|
18153 |
|
|
end doesn't actually put the PARM_DECL nodes for the current function onto
|
18154 |
|
|
the BLOCK_VARS list for this outer scope, but are strung off of the
|
18155 |
|
|
DECL_ARGUMENTS list for the function instead.
|
18156 |
|
|
|
18157 |
|
|
The BLOCK_VARS list for the `outer_scope' does provide us with a list of
|
18158 |
|
|
the LABEL_DECL nodes for the function however, and we output DWARF info
|
18159 |
|
|
for those in decls_for_scope. Just within the `outer_scope' there will be
|
18160 |
|
|
a BLOCK node representing the function's outermost pair of curly braces,
|
18161 |
|
|
and any blocks used for the base and member initializers of a C++
|
18162 |
|
|
constructor function. */
|
18163 |
|
|
if (! declaration && TREE_CODE (outer_scope) != ERROR_MARK)
|
18164 |
|
|
{
|
18165 |
|
|
/* Emit a DW_TAG_variable DIE for a named return value. */
|
18166 |
|
|
if (DECL_NAME (DECL_RESULT (decl)))
|
18167 |
|
|
gen_decl_die (DECL_RESULT (decl), NULL, subr_die);
|
18168 |
|
|
|
18169 |
|
|
current_function_has_inlines = 0;
|
18170 |
|
|
decls_for_scope (outer_scope, subr_die, 0);
|
18171 |
|
|
|
18172 |
|
|
#if 0 && defined (MIPS_DEBUGGING_INFO)
|
18173 |
|
|
if (current_function_has_inlines)
|
18174 |
|
|
{
|
18175 |
|
|
add_AT_flag (subr_die, DW_AT_MIPS_has_inlines, 1);
|
18176 |
|
|
if (! comp_unit_has_inlines)
|
18177 |
|
|
{
|
18178 |
|
|
add_AT_flag (comp_unit_die, DW_AT_MIPS_has_inlines, 1);
|
18179 |
|
|
comp_unit_has_inlines = 1;
|
18180 |
|
|
}
|
18181 |
|
|
}
|
18182 |
|
|
#endif
|
18183 |
|
|
}
|
18184 |
|
|
/* Add the calling convention attribute if requested. */
|
18185 |
|
|
add_calling_convention_attribute (subr_die, decl);
|
18186 |
|
|
|
18187 |
|
|
}
|
18188 |
|
|
|
18189 |
|
|
/* Returns a hash value for X (which really is a die_struct). */
|
18190 |
|
|
|
18191 |
|
|
static hashval_t
|
18192 |
|
|
common_block_die_table_hash (const void *x)
|
18193 |
|
|
{
|
18194 |
|
|
const_dw_die_ref d = (const_dw_die_ref) x;
|
18195 |
|
|
return (hashval_t) d->decl_id ^ htab_hash_pointer (d->die_parent);
|
18196 |
|
|
}
|
18197 |
|
|
|
18198 |
|
|
/* Return nonzero if decl_id and die_parent of die_struct X is the same
|
18199 |
|
|
as decl_id and die_parent of die_struct Y. */
|
18200 |
|
|
|
18201 |
|
|
static int
|
18202 |
|
|
common_block_die_table_eq (const void *x, const void *y)
|
18203 |
|
|
{
|
18204 |
|
|
const_dw_die_ref d = (const_dw_die_ref) x;
|
18205 |
|
|
const_dw_die_ref e = (const_dw_die_ref) y;
|
18206 |
|
|
return d->decl_id == e->decl_id && d->die_parent == e->die_parent;
|
18207 |
|
|
}
|
18208 |
|
|
|
18209 |
|
|
/* Generate a DIE to represent a declared data object.
|
18210 |
|
|
Either DECL or ORIGIN must be non-null. */
|
18211 |
|
|
|
18212 |
|
|
static void
|
18213 |
|
|
gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
|
18214 |
|
|
{
|
18215 |
|
|
HOST_WIDE_INT off;
|
18216 |
|
|
tree com_decl;
|
18217 |
|
|
tree decl_or_origin = decl ? decl : origin;
|
18218 |
|
|
tree ultimate_origin;
|
18219 |
|
|
dw_die_ref var_die;
|
18220 |
|
|
dw_die_ref old_die = decl ? lookup_decl_die (decl) : NULL;
|
18221 |
|
|
dw_die_ref origin_die;
|
18222 |
|
|
int declaration = (DECL_EXTERNAL (decl_or_origin)
|
18223 |
|
|
|| class_or_namespace_scope_p (context_die));
|
18224 |
|
|
|
18225 |
|
|
ultimate_origin = decl_ultimate_origin (decl_or_origin);
|
18226 |
|
|
if (decl || ultimate_origin)
|
18227 |
|
|
origin = ultimate_origin;
|
18228 |
|
|
com_decl = fortran_common (decl_or_origin, &off);
|
18229 |
|
|
|
18230 |
|
|
/* Symbol in common gets emitted as a child of the common block, in the form
|
18231 |
|
|
of a data member. */
|
18232 |
|
|
if (com_decl)
|
18233 |
|
|
{
|
18234 |
|
|
dw_die_ref com_die;
|
18235 |
|
|
dw_loc_list_ref loc;
|
18236 |
|
|
die_node com_die_arg;
|
18237 |
|
|
|
18238 |
|
|
var_die = lookup_decl_die (decl_or_origin);
|
18239 |
|
|
if (var_die)
|
18240 |
|
|
{
|
18241 |
|
|
if (get_AT (var_die, DW_AT_location) == NULL)
|
18242 |
|
|
{
|
18243 |
|
|
loc = loc_list_from_tree (com_decl, off ? 1 : 2);
|
18244 |
|
|
if (loc)
|
18245 |
|
|
{
|
18246 |
|
|
if (off)
|
18247 |
|
|
{
|
18248 |
|
|
/* Optimize the common case. */
|
18249 |
|
|
if (single_element_loc_list_p (loc)
|
18250 |
|
|
&& loc->expr->dw_loc_opc == DW_OP_addr
|
18251 |
|
|
&& loc->expr->dw_loc_next == NULL
|
18252 |
|
|
&& GET_CODE (loc->expr->dw_loc_oprnd1.v.val_addr)
|
18253 |
|
|
== SYMBOL_REF)
|
18254 |
|
|
loc->expr->dw_loc_oprnd1.v.val_addr
|
18255 |
|
|
= plus_constant (loc->expr->dw_loc_oprnd1.v.val_addr, off);
|
18256 |
|
|
else
|
18257 |
|
|
loc_list_plus_const (loc, off);
|
18258 |
|
|
}
|
18259 |
|
|
add_AT_location_description (var_die, DW_AT_location, loc);
|
18260 |
|
|
remove_AT (var_die, DW_AT_declaration);
|
18261 |
|
|
}
|
18262 |
|
|
}
|
18263 |
|
|
return;
|
18264 |
|
|
}
|
18265 |
|
|
|
18266 |
|
|
if (common_block_die_table == NULL)
|
18267 |
|
|
common_block_die_table
|
18268 |
|
|
= htab_create_ggc (10, common_block_die_table_hash,
|
18269 |
|
|
common_block_die_table_eq, NULL);
|
18270 |
|
|
|
18271 |
|
|
com_die_arg.decl_id = DECL_UID (com_decl);
|
18272 |
|
|
com_die_arg.die_parent = context_die;
|
18273 |
|
|
com_die = (dw_die_ref) htab_find (common_block_die_table, &com_die_arg);
|
18274 |
|
|
loc = loc_list_from_tree (com_decl, 2);
|
18275 |
|
|
if (com_die == NULL)
|
18276 |
|
|
{
|
18277 |
|
|
const char *cnam
|
18278 |
|
|
= IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (com_decl));
|
18279 |
|
|
void **slot;
|
18280 |
|
|
|
18281 |
|
|
com_die = new_die (DW_TAG_common_block, context_die, decl);
|
18282 |
|
|
add_name_and_src_coords_attributes (com_die, com_decl);
|
18283 |
|
|
if (loc)
|
18284 |
|
|
{
|
18285 |
|
|
add_AT_location_description (com_die, DW_AT_location, loc);
|
18286 |
|
|
/* Avoid sharing the same loc descriptor between
|
18287 |
|
|
DW_TAG_common_block and DW_TAG_variable. */
|
18288 |
|
|
loc = loc_list_from_tree (com_decl, 2);
|
18289 |
|
|
}
|
18290 |
|
|
else if (DECL_EXTERNAL (decl))
|
18291 |
|
|
add_AT_flag (com_die, DW_AT_declaration, 1);
|
18292 |
|
|
add_pubname_string (cnam, com_die); /* ??? needed? */
|
18293 |
|
|
com_die->decl_id = DECL_UID (com_decl);
|
18294 |
|
|
slot = htab_find_slot (common_block_die_table, com_die, INSERT);
|
18295 |
|
|
*slot = (void *) com_die;
|
18296 |
|
|
}
|
18297 |
|
|
else if (get_AT (com_die, DW_AT_location) == NULL && loc)
|
18298 |
|
|
{
|
18299 |
|
|
add_AT_location_description (com_die, DW_AT_location, loc);
|
18300 |
|
|
loc = loc_list_from_tree (com_decl, 2);
|
18301 |
|
|
remove_AT (com_die, DW_AT_declaration);
|
18302 |
|
|
}
|
18303 |
|
|
var_die = new_die (DW_TAG_variable, com_die, decl);
|
18304 |
|
|
add_name_and_src_coords_attributes (var_die, decl);
|
18305 |
|
|
add_type_attribute (var_die, TREE_TYPE (decl), TREE_READONLY (decl),
|
18306 |
|
|
TREE_THIS_VOLATILE (decl), context_die);
|
18307 |
|
|
add_AT_flag (var_die, DW_AT_external, 1);
|
18308 |
|
|
if (loc)
|
18309 |
|
|
{
|
18310 |
|
|
if (off)
|
18311 |
|
|
{
|
18312 |
|
|
/* Optimize the common case. */
|
18313 |
|
|
if (single_element_loc_list_p (loc)
|
18314 |
|
|
&& loc->expr->dw_loc_opc == DW_OP_addr
|
18315 |
|
|
&& loc->expr->dw_loc_next == NULL
|
18316 |
|
|
&& GET_CODE (loc->expr->dw_loc_oprnd1.v.val_addr) == SYMBOL_REF)
|
18317 |
|
|
loc->expr->dw_loc_oprnd1.v.val_addr
|
18318 |
|
|
= plus_constant (loc->expr->dw_loc_oprnd1.v.val_addr, off);
|
18319 |
|
|
else
|
18320 |
|
|
loc_list_plus_const (loc, off);
|
18321 |
|
|
}
|
18322 |
|
|
add_AT_location_description (var_die, DW_AT_location, loc);
|
18323 |
|
|
}
|
18324 |
|
|
else if (DECL_EXTERNAL (decl))
|
18325 |
|
|
add_AT_flag (var_die, DW_AT_declaration, 1);
|
18326 |
|
|
equate_decl_number_to_die (decl, var_die);
|
18327 |
|
|
return;
|
18328 |
|
|
}
|
18329 |
|
|
|
18330 |
|
|
/* If the compiler emitted a definition for the DECL declaration
|
18331 |
|
|
and if we already emitted a DIE for it, don't emit a second
|
18332 |
|
|
DIE for it again. Allow re-declarations of DECLs that are
|
18333 |
|
|
inside functions, though. */
|
18334 |
|
|
if (old_die && declaration && !local_scope_p (context_die))
|
18335 |
|
|
return;
|
18336 |
|
|
|
18337 |
|
|
/* For static data members, the declaration in the class is supposed
|
18338 |
|
|
to have DW_TAG_member tag; the specification should still be
|
18339 |
|
|
DW_TAG_variable referencing the DW_TAG_member DIE. */
|
18340 |
|
|
if (declaration && class_scope_p (context_die))
|
18341 |
|
|
var_die = new_die (DW_TAG_member, context_die, decl);
|
18342 |
|
|
else
|
18343 |
|
|
var_die = new_die (DW_TAG_variable, context_die, decl);
|
18344 |
|
|
|
18345 |
|
|
origin_die = NULL;
|
18346 |
|
|
if (origin != NULL)
|
18347 |
|
|
origin_die = add_abstract_origin_attribute (var_die, origin);
|
18348 |
|
|
|
18349 |
|
|
/* Loop unrolling can create multiple blocks that refer to the same
|
18350 |
|
|
static variable, so we must test for the DW_AT_declaration flag.
|
18351 |
|
|
|
18352 |
|
|
??? Loop unrolling/reorder_blocks should perhaps be rewritten to
|
18353 |
|
|
copy decls and set the DECL_ABSTRACT flag on them instead of
|
18354 |
|
|
sharing them.
|
18355 |
|
|
|
18356 |
|
|
??? Duplicated blocks have been rewritten to use .debug_ranges.
|
18357 |
|
|
|
18358 |
|
|
??? The declare_in_namespace support causes us to get two DIEs for one
|
18359 |
|
|
variable, both of which are declarations. We want to avoid considering
|
18360 |
|
|
one to be a specification, so we must test that this DIE is not a
|
18361 |
|
|
declaration. */
|
18362 |
|
|
else if (old_die && TREE_STATIC (decl) && ! declaration
|
18363 |
|
|
&& get_AT_flag (old_die, DW_AT_declaration) == 1)
|
18364 |
|
|
{
|
18365 |
|
|
/* This is a definition of a C++ class level static. */
|
18366 |
|
|
add_AT_specification (var_die, old_die);
|
18367 |
|
|
if (DECL_NAME (decl))
|
18368 |
|
|
{
|
18369 |
|
|
expanded_location s = expand_location (DECL_SOURCE_LOCATION (decl));
|
18370 |
|
|
struct dwarf_file_data * file_index = lookup_filename (s.file);
|
18371 |
|
|
|
18372 |
|
|
if (get_AT_file (old_die, DW_AT_decl_file) != file_index)
|
18373 |
|
|
add_AT_file (var_die, DW_AT_decl_file, file_index);
|
18374 |
|
|
|
18375 |
|
|
if (get_AT_unsigned (old_die, DW_AT_decl_line) != (unsigned) s.line)
|
18376 |
|
|
add_AT_unsigned (var_die, DW_AT_decl_line, s.line);
|
18377 |
|
|
}
|
18378 |
|
|
}
|
18379 |
|
|
else
|
18380 |
|
|
{
|
18381 |
|
|
tree type = TREE_TYPE (decl);
|
18382 |
|
|
|
18383 |
|
|
add_name_and_src_coords_attributes (var_die, decl);
|
18384 |
|
|
if (decl_by_reference_p (decl))
|
18385 |
|
|
add_type_attribute (var_die, TREE_TYPE (type), 0, 0, context_die);
|
18386 |
|
|
else
|
18387 |
|
|
add_type_attribute (var_die, type, TREE_READONLY (decl),
|
18388 |
|
|
TREE_THIS_VOLATILE (decl), context_die);
|
18389 |
|
|
|
18390 |
|
|
if (TREE_PUBLIC (decl))
|
18391 |
|
|
add_AT_flag (var_die, DW_AT_external, 1);
|
18392 |
|
|
|
18393 |
|
|
if (DECL_ARTIFICIAL (decl))
|
18394 |
|
|
add_AT_flag (var_die, DW_AT_artificial, 1);
|
18395 |
|
|
|
18396 |
|
|
if (TREE_PROTECTED (decl))
|
18397 |
|
|
add_AT_unsigned (var_die, DW_AT_accessibility, DW_ACCESS_protected);
|
18398 |
|
|
else if (TREE_PRIVATE (decl))
|
18399 |
|
|
add_AT_unsigned (var_die, DW_AT_accessibility, DW_ACCESS_private);
|
18400 |
|
|
}
|
18401 |
|
|
|
18402 |
|
|
if (declaration)
|
18403 |
|
|
add_AT_flag (var_die, DW_AT_declaration, 1);
|
18404 |
|
|
|
18405 |
|
|
if (decl && (DECL_ABSTRACT (decl) || declaration))
|
18406 |
|
|
equate_decl_number_to_die (decl, var_die);
|
18407 |
|
|
|
18408 |
|
|
if (! declaration
|
18409 |
|
|
&& (! DECL_ABSTRACT (decl_or_origin)
|
18410 |
|
|
/* Local static vars are shared between all clones/inlines,
|
18411 |
|
|
so emit DW_AT_location on the abstract DIE if DECL_RTL is
|
18412 |
|
|
already set. */
|
18413 |
|
|
|| (TREE_CODE (decl_or_origin) == VAR_DECL
|
18414 |
|
|
&& TREE_STATIC (decl_or_origin)
|
18415 |
|
|
&& DECL_RTL_SET_P (decl_or_origin)))
|
18416 |
|
|
/* When abstract origin already has DW_AT_location attribute, no need
|
18417 |
|
|
to add it again. */
|
18418 |
|
|
&& (origin_die == NULL || get_AT (origin_die, DW_AT_location) == NULL))
|
18419 |
|
|
{
|
18420 |
|
|
if (TREE_CODE (decl_or_origin) == VAR_DECL && TREE_STATIC (decl_or_origin)
|
18421 |
|
|
&& !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl_or_origin)))
|
18422 |
|
|
defer_location (decl_or_origin, var_die);
|
18423 |
|
|
else
|
18424 |
|
|
add_location_or_const_value_attribute (var_die,
|
18425 |
|
|
decl_or_origin,
|
18426 |
|
|
DW_AT_location);
|
18427 |
|
|
add_pubname (decl_or_origin, var_die);
|
18428 |
|
|
}
|
18429 |
|
|
else
|
18430 |
|
|
tree_add_const_value_attribute_for_decl (var_die, decl_or_origin);
|
18431 |
|
|
}
|
18432 |
|
|
|
18433 |
|
|
/* Generate a DIE to represent a named constant. */
|
18434 |
|
|
|
18435 |
|
|
static void
|
18436 |
|
|
gen_const_die (tree decl, dw_die_ref context_die)
|
18437 |
|
|
{
|
18438 |
|
|
dw_die_ref const_die;
|
18439 |
|
|
tree type = TREE_TYPE (decl);
|
18440 |
|
|
|
18441 |
|
|
const_die = new_die (DW_TAG_constant, context_die, decl);
|
18442 |
|
|
add_name_and_src_coords_attributes (const_die, decl);
|
18443 |
|
|
add_type_attribute (const_die, type, 1, 0, context_die);
|
18444 |
|
|
if (TREE_PUBLIC (decl))
|
18445 |
|
|
add_AT_flag (const_die, DW_AT_external, 1);
|
18446 |
|
|
if (DECL_ARTIFICIAL (decl))
|
18447 |
|
|
add_AT_flag (const_die, DW_AT_artificial, 1);
|
18448 |
|
|
tree_add_const_value_attribute_for_decl (const_die, decl);
|
18449 |
|
|
}
|
18450 |
|
|
|
18451 |
|
|
/* Generate a DIE to represent a label identifier. */
|
18452 |
|
|
|
18453 |
|
|
static void
|
18454 |
|
|
gen_label_die (tree decl, dw_die_ref context_die)
|
18455 |
|
|
{
|
18456 |
|
|
tree origin = decl_ultimate_origin (decl);
|
18457 |
|
|
dw_die_ref lbl_die = new_die (DW_TAG_label, context_die, decl);
|
18458 |
|
|
rtx insn;
|
18459 |
|
|
char label[MAX_ARTIFICIAL_LABEL_BYTES];
|
18460 |
|
|
|
18461 |
|
|
if (origin != NULL)
|
18462 |
|
|
add_abstract_origin_attribute (lbl_die, origin);
|
18463 |
|
|
else
|
18464 |
|
|
add_name_and_src_coords_attributes (lbl_die, decl);
|
18465 |
|
|
|
18466 |
|
|
if (DECL_ABSTRACT (decl))
|
18467 |
|
|
equate_decl_number_to_die (decl, lbl_die);
|
18468 |
|
|
else
|
18469 |
|
|
{
|
18470 |
|
|
insn = DECL_RTL_IF_SET (decl);
|
18471 |
|
|
|
18472 |
|
|
/* Deleted labels are programmer specified labels which have been
|
18473 |
|
|
eliminated because of various optimizations. We still emit them
|
18474 |
|
|
here so that it is possible to put breakpoints on them. */
|
18475 |
|
|
if (insn
|
18476 |
|
|
&& (LABEL_P (insn)
|
18477 |
|
|
|| ((NOTE_P (insn)
|
18478 |
|
|
&& NOTE_KIND (insn) == NOTE_INSN_DELETED_LABEL))))
|
18479 |
|
|
{
|
18480 |
|
|
/* When optimization is enabled (via -O) some parts of the compiler
|
18481 |
|
|
(e.g. jump.c and cse.c) may try to delete CODE_LABEL insns which
|
18482 |
|
|
represent source-level labels which were explicitly declared by
|
18483 |
|
|
the user. This really shouldn't be happening though, so catch
|
18484 |
|
|
it if it ever does happen. */
|
18485 |
|
|
gcc_assert (!INSN_DELETED_P (insn));
|
18486 |
|
|
|
18487 |
|
|
ASM_GENERATE_INTERNAL_LABEL (label, "L", CODE_LABEL_NUMBER (insn));
|
18488 |
|
|
add_AT_lbl_id (lbl_die, DW_AT_low_pc, label);
|
18489 |
|
|
}
|
18490 |
|
|
}
|
18491 |
|
|
}
|
18492 |
|
|
|
18493 |
|
|
/* A helper function for gen_inlined_subroutine_die. Add source coordinate
|
18494 |
|
|
attributes to the DIE for a block STMT, to describe where the inlined
|
18495 |
|
|
function was called from. This is similar to add_src_coords_attributes. */
|
18496 |
|
|
|
18497 |
|
|
static inline void
|
18498 |
|
|
add_call_src_coords_attributes (tree stmt, dw_die_ref die)
|
18499 |
|
|
{
|
18500 |
|
|
expanded_location s = expand_location (BLOCK_SOURCE_LOCATION (stmt));
|
18501 |
|
|
|
18502 |
|
|
if (dwarf_version >= 3 || !dwarf_strict)
|
18503 |
|
|
{
|
18504 |
|
|
add_AT_file (die, DW_AT_call_file, lookup_filename (s.file));
|
18505 |
|
|
add_AT_unsigned (die, DW_AT_call_line, s.line);
|
18506 |
|
|
}
|
18507 |
|
|
}
|
18508 |
|
|
|
18509 |
|
|
|
18510 |
|
|
/* A helper function for gen_lexical_block_die and gen_inlined_subroutine_die.
|
18511 |
|
|
Add low_pc and high_pc attributes to the DIE for a block STMT. */
|
18512 |
|
|
|
18513 |
|
|
static inline void
|
18514 |
|
|
add_high_low_attributes (tree stmt, dw_die_ref die)
|
18515 |
|
|
{
|
18516 |
|
|
char label[MAX_ARTIFICIAL_LABEL_BYTES];
|
18517 |
|
|
|
18518 |
|
|
if (BLOCK_FRAGMENT_CHAIN (stmt)
|
18519 |
|
|
&& (dwarf_version >= 3 || !dwarf_strict))
|
18520 |
|
|
{
|
18521 |
|
|
tree chain;
|
18522 |
|
|
|
18523 |
|
|
if (inlined_function_outer_scope_p (stmt))
|
18524 |
|
|
{
|
18525 |
|
|
ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL,
|
18526 |
|
|
BLOCK_NUMBER (stmt));
|
18527 |
|
|
add_AT_lbl_id (die, DW_AT_entry_pc, label);
|
18528 |
|
|
}
|
18529 |
|
|
|
18530 |
|
|
add_AT_range_list (die, DW_AT_ranges, add_ranges (stmt));
|
18531 |
|
|
|
18532 |
|
|
chain = BLOCK_FRAGMENT_CHAIN (stmt);
|
18533 |
|
|
do
|
18534 |
|
|
{
|
18535 |
|
|
add_ranges (chain);
|
18536 |
|
|
chain = BLOCK_FRAGMENT_CHAIN (chain);
|
18537 |
|
|
}
|
18538 |
|
|
while (chain);
|
18539 |
|
|
add_ranges (NULL);
|
18540 |
|
|
}
|
18541 |
|
|
else
|
18542 |
|
|
{
|
18543 |
|
|
ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL,
|
18544 |
|
|
BLOCK_NUMBER (stmt));
|
18545 |
|
|
add_AT_lbl_id (die, DW_AT_low_pc, label);
|
18546 |
|
|
ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_END_LABEL,
|
18547 |
|
|
BLOCK_NUMBER (stmt));
|
18548 |
|
|
add_AT_lbl_id (die, DW_AT_high_pc, label);
|
18549 |
|
|
}
|
18550 |
|
|
}
|
18551 |
|
|
|
18552 |
|
|
/* Generate a DIE for a lexical block. */
|
18553 |
|
|
|
18554 |
|
|
static void
|
18555 |
|
|
gen_lexical_block_die (tree stmt, dw_die_ref context_die, int depth)
|
18556 |
|
|
{
|
18557 |
|
|
dw_die_ref stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt);
|
18558 |
|
|
|
18559 |
|
|
if (! BLOCK_ABSTRACT (stmt) && TREE_ASM_WRITTEN (stmt))
|
18560 |
|
|
add_high_low_attributes (stmt, stmt_die);
|
18561 |
|
|
|
18562 |
|
|
decls_for_scope (stmt, stmt_die, depth);
|
18563 |
|
|
}
|
18564 |
|
|
|
18565 |
|
|
/* Generate a DIE for an inlined subprogram. */
|
18566 |
|
|
|
18567 |
|
|
static void
|
18568 |
|
|
gen_inlined_subroutine_die (tree stmt, dw_die_ref context_die, int depth)
|
18569 |
|
|
{
|
18570 |
|
|
tree decl;
|
18571 |
|
|
|
18572 |
|
|
/* The instance of function that is effectively being inlined shall not
|
18573 |
|
|
be abstract. */
|
18574 |
|
|
gcc_assert (! BLOCK_ABSTRACT (stmt));
|
18575 |
|
|
|
18576 |
|
|
decl = block_ultimate_origin (stmt);
|
18577 |
|
|
|
18578 |
|
|
/* Emit info for the abstract instance first, if we haven't yet. We
|
18579 |
|
|
must emit this even if the block is abstract, otherwise when we
|
18580 |
|
|
emit the block below (or elsewhere), we may end up trying to emit
|
18581 |
|
|
a die whose origin die hasn't been emitted, and crashing. */
|
18582 |
|
|
dwarf2out_abstract_function (decl);
|
18583 |
|
|
|
18584 |
|
|
if (! BLOCK_ABSTRACT (stmt))
|
18585 |
|
|
{
|
18586 |
|
|
dw_die_ref subr_die
|
18587 |
|
|
= new_die (DW_TAG_inlined_subroutine, context_die, stmt);
|
18588 |
|
|
|
18589 |
|
|
add_abstract_origin_attribute (subr_die, decl);
|
18590 |
|
|
if (TREE_ASM_WRITTEN (stmt))
|
18591 |
|
|
add_high_low_attributes (stmt, subr_die);
|
18592 |
|
|
add_call_src_coords_attributes (stmt, subr_die);
|
18593 |
|
|
|
18594 |
|
|
decls_for_scope (stmt, subr_die, depth);
|
18595 |
|
|
current_function_has_inlines = 1;
|
18596 |
|
|
}
|
18597 |
|
|
}
|
18598 |
|
|
|
18599 |
|
|
/* Generate a DIE for a field in a record, or structure. */
|
18600 |
|
|
|
18601 |
|
|
static void
|
18602 |
|
|
gen_field_die (tree decl, dw_die_ref context_die)
|
18603 |
|
|
{
|
18604 |
|
|
dw_die_ref decl_die;
|
18605 |
|
|
|
18606 |
|
|
if (TREE_TYPE (decl) == error_mark_node)
|
18607 |
|
|
return;
|
18608 |
|
|
|
18609 |
|
|
decl_die = new_die (DW_TAG_member, context_die, decl);
|
18610 |
|
|
add_name_and_src_coords_attributes (decl_die, decl);
|
18611 |
|
|
add_type_attribute (decl_die, member_declared_type (decl),
|
18612 |
|
|
TREE_READONLY (decl), TREE_THIS_VOLATILE (decl),
|
18613 |
|
|
context_die);
|
18614 |
|
|
|
18615 |
|
|
if (DECL_BIT_FIELD_TYPE (decl))
|
18616 |
|
|
{
|
18617 |
|
|
add_byte_size_attribute (decl_die, decl);
|
18618 |
|
|
add_bit_size_attribute (decl_die, decl);
|
18619 |
|
|
add_bit_offset_attribute (decl_die, decl);
|
18620 |
|
|
}
|
18621 |
|
|
|
18622 |
|
|
if (TREE_CODE (DECL_FIELD_CONTEXT (decl)) != UNION_TYPE)
|
18623 |
|
|
add_data_member_location_attribute (decl_die, decl);
|
18624 |
|
|
|
18625 |
|
|
if (DECL_ARTIFICIAL (decl))
|
18626 |
|
|
add_AT_flag (decl_die, DW_AT_artificial, 1);
|
18627 |
|
|
|
18628 |
|
|
if (TREE_PROTECTED (decl))
|
18629 |
|
|
add_AT_unsigned (decl_die, DW_AT_accessibility, DW_ACCESS_protected);
|
18630 |
|
|
else if (TREE_PRIVATE (decl))
|
18631 |
|
|
add_AT_unsigned (decl_die, DW_AT_accessibility, DW_ACCESS_private);
|
18632 |
|
|
|
18633 |
|
|
/* Equate decl number to die, so that we can look up this decl later on. */
|
18634 |
|
|
equate_decl_number_to_die (decl, decl_die);
|
18635 |
|
|
}
|
18636 |
|
|
|
18637 |
|
|
#if 0
|
18638 |
|
|
/* Don't generate either pointer_type DIEs or reference_type DIEs here.
|
18639 |
|
|
Use modified_type_die instead.
|
18640 |
|
|
We keep this code here just in case these types of DIEs may be needed to
|
18641 |
|
|
represent certain things in other languages (e.g. Pascal) someday. */
|
18642 |
|
|
|
18643 |
|
|
static void
|
18644 |
|
|
gen_pointer_type_die (tree type, dw_die_ref context_die)
|
18645 |
|
|
{
|
18646 |
|
|
dw_die_ref ptr_die
|
18647 |
|
|
= new_die (DW_TAG_pointer_type, scope_die_for (type, context_die), type);
|
18648 |
|
|
|
18649 |
|
|
equate_type_number_to_die (type, ptr_die);
|
18650 |
|
|
add_type_attribute (ptr_die, TREE_TYPE (type), 0, 0, context_die);
|
18651 |
|
|
add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE);
|
18652 |
|
|
}
|
18653 |
|
|
|
18654 |
|
|
/* Don't generate either pointer_type DIEs or reference_type DIEs here.
|
18655 |
|
|
Use modified_type_die instead.
|
18656 |
|
|
We keep this code here just in case these types of DIEs may be needed to
|
18657 |
|
|
represent certain things in other languages (e.g. Pascal) someday. */
|
18658 |
|
|
|
18659 |
|
|
static void
|
18660 |
|
|
gen_reference_type_die (tree type, dw_die_ref context_die)
|
18661 |
|
|
{
|
18662 |
|
|
dw_die_ref ref_die
|
18663 |
|
|
= new_die (DW_TAG_reference_type, scope_die_for (type, context_die), type);
|
18664 |
|
|
|
18665 |
|
|
equate_type_number_to_die (type, ref_die);
|
18666 |
|
|
add_type_attribute (ref_die, TREE_TYPE (type), 0, 0, context_die);
|
18667 |
|
|
add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE);
|
18668 |
|
|
}
|
18669 |
|
|
#endif
|
18670 |
|
|
|
18671 |
|
|
/* Generate a DIE for a pointer to a member type. */
|
18672 |
|
|
|
18673 |
|
|
static void
|
18674 |
|
|
gen_ptr_to_mbr_type_die (tree type, dw_die_ref context_die)
|
18675 |
|
|
{
|
18676 |
|
|
dw_die_ref ptr_die
|
18677 |
|
|
= new_die (DW_TAG_ptr_to_member_type,
|
18678 |
|
|
scope_die_for (type, context_die), type);
|
18679 |
|
|
|
18680 |
|
|
equate_type_number_to_die (type, ptr_die);
|
18681 |
|
|
add_AT_die_ref (ptr_die, DW_AT_containing_type,
|
18682 |
|
|
lookup_type_die (TYPE_OFFSET_BASETYPE (type)));
|
18683 |
|
|
add_type_attribute (ptr_die, TREE_TYPE (type), 0, 0, context_die);
|
18684 |
|
|
}
|
18685 |
|
|
|
18686 |
|
|
/* Generate the DIE for the compilation unit. */
|
18687 |
|
|
|
18688 |
|
|
static dw_die_ref
|
18689 |
|
|
gen_compile_unit_die (const char *filename)
|
18690 |
|
|
{
|
18691 |
|
|
dw_die_ref die;
|
18692 |
|
|
char producer[250];
|
18693 |
|
|
const char *language_string = lang_hooks.name;
|
18694 |
|
|
int language;
|
18695 |
|
|
|
18696 |
|
|
die = new_die (DW_TAG_compile_unit, NULL, NULL);
|
18697 |
|
|
|
18698 |
|
|
if (filename)
|
18699 |
|
|
{
|
18700 |
|
|
add_name_attribute (die, filename);
|
18701 |
|
|
/* Don't add cwd for <built-in>. */
|
18702 |
|
|
if (!IS_ABSOLUTE_PATH (filename) && filename[0] != '<')
|
18703 |
|
|
add_comp_dir_attribute (die);
|
18704 |
|
|
}
|
18705 |
|
|
|
18706 |
|
|
sprintf (producer, "%s %s", language_string, version_string);
|
18707 |
|
|
|
18708 |
|
|
#ifdef MIPS_DEBUGGING_INFO
|
18709 |
|
|
/* The MIPS/SGI compilers place the 'cc' command line options in the producer
|
18710 |
|
|
string. The SGI debugger looks for -g, -g1, -g2, or -g3; if they do
|
18711 |
|
|
not appear in the producer string, the debugger reaches the conclusion
|
18712 |
|
|
that the object file is stripped and has no debugging information.
|
18713 |
|
|
To get the MIPS/SGI debugger to believe that there is debugging
|
18714 |
|
|
information in the object file, we add a -g to the producer string. */
|
18715 |
|
|
if (debug_info_level > DINFO_LEVEL_TERSE)
|
18716 |
|
|
strcat (producer, " -g");
|
18717 |
|
|
#endif
|
18718 |
|
|
|
18719 |
|
|
add_AT_string (die, DW_AT_producer, producer);
|
18720 |
|
|
|
18721 |
|
|
language = DW_LANG_C89;
|
18722 |
|
|
if (strcmp (language_string, "GNU C++") == 0)
|
18723 |
|
|
language = DW_LANG_C_plus_plus;
|
18724 |
|
|
else if (strcmp (language_string, "GNU F77") == 0)
|
18725 |
|
|
language = DW_LANG_Fortran77;
|
18726 |
|
|
else if (strcmp (language_string, "GNU Pascal") == 0)
|
18727 |
|
|
language = DW_LANG_Pascal83;
|
18728 |
|
|
else if (dwarf_version >= 3 || !dwarf_strict)
|
18729 |
|
|
{
|
18730 |
|
|
if (strcmp (language_string, "GNU Ada") == 0)
|
18731 |
|
|
language = DW_LANG_Ada95;
|
18732 |
|
|
else if (strcmp (language_string, "GNU Fortran") == 0)
|
18733 |
|
|
language = DW_LANG_Fortran95;
|
18734 |
|
|
else if (strcmp (language_string, "GNU Java") == 0)
|
18735 |
|
|
language = DW_LANG_Java;
|
18736 |
|
|
else if (strcmp (language_string, "GNU Objective-C") == 0)
|
18737 |
|
|
language = DW_LANG_ObjC;
|
18738 |
|
|
else if (strcmp (language_string, "GNU Objective-C++") == 0)
|
18739 |
|
|
language = DW_LANG_ObjC_plus_plus;
|
18740 |
|
|
}
|
18741 |
|
|
|
18742 |
|
|
add_AT_unsigned (die, DW_AT_language, language);
|
18743 |
|
|
return die;
|
18744 |
|
|
}
|
18745 |
|
|
|
18746 |
|
|
/* Generate the DIE for a base class. */
|
18747 |
|
|
|
18748 |
|
|
static void
|
18749 |
|
|
gen_inheritance_die (tree binfo, tree access, dw_die_ref context_die)
|
18750 |
|
|
{
|
18751 |
|
|
dw_die_ref die = new_die (DW_TAG_inheritance, context_die, binfo);
|
18752 |
|
|
|
18753 |
|
|
add_type_attribute (die, BINFO_TYPE (binfo), 0, 0, context_die);
|
18754 |
|
|
add_data_member_location_attribute (die, binfo);
|
18755 |
|
|
|
18756 |
|
|
if (BINFO_VIRTUAL_P (binfo))
|
18757 |
|
|
add_AT_unsigned (die, DW_AT_virtuality, DW_VIRTUALITY_virtual);
|
18758 |
|
|
|
18759 |
|
|
if (access == access_public_node)
|
18760 |
|
|
add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_public);
|
18761 |
|
|
else if (access == access_protected_node)
|
18762 |
|
|
add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_protected);
|
18763 |
|
|
}
|
18764 |
|
|
|
18765 |
|
|
/* Generate a DIE for a class member. */
|
18766 |
|
|
|
18767 |
|
|
static void
|
18768 |
|
|
gen_member_die (tree type, dw_die_ref context_die)
|
18769 |
|
|
{
|
18770 |
|
|
tree member;
|
18771 |
|
|
tree binfo = TYPE_BINFO (type);
|
18772 |
|
|
dw_die_ref child;
|
18773 |
|
|
|
18774 |
|
|
/* If this is not an incomplete type, output descriptions of each of its
|
18775 |
|
|
members. Note that as we output the DIEs necessary to represent the
|
18776 |
|
|
members of this record or union type, we will also be trying to output
|
18777 |
|
|
DIEs to represent the *types* of those members. However the `type'
|
18778 |
|
|
function (above) will specifically avoid generating type DIEs for member
|
18779 |
|
|
types *within* the list of member DIEs for this (containing) type except
|
18780 |
|
|
for those types (of members) which are explicitly marked as also being
|
18781 |
|
|
members of this (containing) type themselves. The g++ front- end can
|
18782 |
|
|
force any given type to be treated as a member of some other (containing)
|
18783 |
|
|
type by setting the TYPE_CONTEXT of the given (member) type to point to
|
18784 |
|
|
the TREE node representing the appropriate (containing) type. */
|
18785 |
|
|
|
18786 |
|
|
/* First output info about the base classes. */
|
18787 |
|
|
if (binfo)
|
18788 |
|
|
{
|
18789 |
|
|
VEC(tree,gc) *accesses = BINFO_BASE_ACCESSES (binfo);
|
18790 |
|
|
int i;
|
18791 |
|
|
tree base;
|
18792 |
|
|
|
18793 |
|
|
for (i = 0; BINFO_BASE_ITERATE (binfo, i, base); i++)
|
18794 |
|
|
gen_inheritance_die (base,
|
18795 |
|
|
(accesses ? VEC_index (tree, accesses, i)
|
18796 |
|
|
: access_public_node), context_die);
|
18797 |
|
|
}
|
18798 |
|
|
|
18799 |
|
|
/* Now output info about the data members and type members. */
|
18800 |
|
|
for (member = TYPE_FIELDS (type); member; member = TREE_CHAIN (member))
|
18801 |
|
|
{
|
18802 |
|
|
/* If we thought we were generating minimal debug info for TYPE
|
18803 |
|
|
and then changed our minds, some of the member declarations
|
18804 |
|
|
may have already been defined. Don't define them again, but
|
18805 |
|
|
do put them in the right order. */
|
18806 |
|
|
|
18807 |
|
|
child = lookup_decl_die (member);
|
18808 |
|
|
if (child)
|
18809 |
|
|
splice_child_die (context_die, child);
|
18810 |
|
|
else
|
18811 |
|
|
gen_decl_die (member, NULL, context_die);
|
18812 |
|
|
}
|
18813 |
|
|
|
18814 |
|
|
/* Now output info about the function members (if any). */
|
18815 |
|
|
for (member = TYPE_METHODS (type); member; member = TREE_CHAIN (member))
|
18816 |
|
|
{
|
18817 |
|
|
/* Don't include clones in the member list. */
|
18818 |
|
|
if (DECL_ABSTRACT_ORIGIN (member))
|
18819 |
|
|
continue;
|
18820 |
|
|
|
18821 |
|
|
child = lookup_decl_die (member);
|
18822 |
|
|
if (child)
|
18823 |
|
|
splice_child_die (context_die, child);
|
18824 |
|
|
else
|
18825 |
|
|
gen_decl_die (member, NULL, context_die);
|
18826 |
|
|
}
|
18827 |
|
|
}
|
18828 |
|
|
|
18829 |
|
|
/* Generate a DIE for a structure or union type. If TYPE_DECL_SUPPRESS_DEBUG
|
18830 |
|
|
is set, we pretend that the type was never defined, so we only get the
|
18831 |
|
|
member DIEs needed by later specification DIEs. */
|
18832 |
|
|
|
18833 |
|
|
static void
|
18834 |
|
|
gen_struct_or_union_type_die (tree type, dw_die_ref context_die,
|
18835 |
|
|
enum debug_info_usage usage)
|
18836 |
|
|
{
|
18837 |
|
|
dw_die_ref type_die = lookup_type_die (type);
|
18838 |
|
|
dw_die_ref scope_die = 0;
|
18839 |
|
|
int nested = 0;
|
18840 |
|
|
int complete = (TYPE_SIZE (type)
|
18841 |
|
|
&& (! TYPE_STUB_DECL (type)
|
18842 |
|
|
|| ! TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type))));
|
18843 |
|
|
int ns_decl = (context_die && context_die->die_tag == DW_TAG_namespace);
|
18844 |
|
|
complete = complete && should_emit_struct_debug (type, usage);
|
18845 |
|
|
|
18846 |
|
|
if (type_die && ! complete)
|
18847 |
|
|
return;
|
18848 |
|
|
|
18849 |
|
|
if (TYPE_CONTEXT (type) != NULL_TREE
|
18850 |
|
|
&& (AGGREGATE_TYPE_P (TYPE_CONTEXT (type))
|
18851 |
|
|
|| TREE_CODE (TYPE_CONTEXT (type)) == NAMESPACE_DECL))
|
18852 |
|
|
nested = 1;
|
18853 |
|
|
|
18854 |
|
|
scope_die = scope_die_for (type, context_die);
|
18855 |
|
|
|
18856 |
|
|
if (! type_die || (nested && scope_die == comp_unit_die))
|
18857 |
|
|
/* First occurrence of type or toplevel definition of nested class. */
|
18858 |
|
|
{
|
18859 |
|
|
dw_die_ref old_die = type_die;
|
18860 |
|
|
|
18861 |
|
|
type_die = new_die (TREE_CODE (type) == RECORD_TYPE
|
18862 |
|
|
? record_type_tag (type) : DW_TAG_union_type,
|
18863 |
|
|
scope_die, type);
|
18864 |
|
|
equate_type_number_to_die (type, type_die);
|
18865 |
|
|
if (old_die)
|
18866 |
|
|
add_AT_specification (type_die, old_die);
|
18867 |
|
|
else
|
18868 |
|
|
add_name_attribute (type_die, type_tag (type));
|
18869 |
|
|
}
|
18870 |
|
|
else
|
18871 |
|
|
remove_AT (type_die, DW_AT_declaration);
|
18872 |
|
|
|
18873 |
|
|
/* Generate child dies for template paramaters. */
|
18874 |
|
|
if (debug_info_level > DINFO_LEVEL_TERSE
|
18875 |
|
|
&& COMPLETE_TYPE_P (type))
|
18876 |
|
|
gen_generic_params_dies (type);
|
18877 |
|
|
|
18878 |
|
|
/* If this type has been completed, then give it a byte_size attribute and
|
18879 |
|
|
then give a list of members. */
|
18880 |
|
|
if (complete && !ns_decl)
|
18881 |
|
|
{
|
18882 |
|
|
/* Prevent infinite recursion in cases where the type of some member of
|
18883 |
|
|
this type is expressed in terms of this type itself. */
|
18884 |
|
|
TREE_ASM_WRITTEN (type) = 1;
|
18885 |
|
|
add_byte_size_attribute (type_die, type);
|
18886 |
|
|
if (TYPE_STUB_DECL (type) != NULL_TREE)
|
18887 |
|
|
add_src_coords_attributes (type_die, TYPE_STUB_DECL (type));
|
18888 |
|
|
|
18889 |
|
|
/* If the first reference to this type was as the return type of an
|
18890 |
|
|
inline function, then it may not have a parent. Fix this now. */
|
18891 |
|
|
if (type_die->die_parent == NULL)
|
18892 |
|
|
add_child_die (scope_die, type_die);
|
18893 |
|
|
|
18894 |
|
|
push_decl_scope (type);
|
18895 |
|
|
gen_member_die (type, type_die);
|
18896 |
|
|
pop_decl_scope ();
|
18897 |
|
|
|
18898 |
|
|
/* GNU extension: Record what type our vtable lives in. */
|
18899 |
|
|
if (TYPE_VFIELD (type))
|
18900 |
|
|
{
|
18901 |
|
|
tree vtype = DECL_FCONTEXT (TYPE_VFIELD (type));
|
18902 |
|
|
|
18903 |
|
|
gen_type_die (vtype, context_die);
|
18904 |
|
|
add_AT_die_ref (type_die, DW_AT_containing_type,
|
18905 |
|
|
lookup_type_die (vtype));
|
18906 |
|
|
}
|
18907 |
|
|
}
|
18908 |
|
|
else
|
18909 |
|
|
{
|
18910 |
|
|
add_AT_flag (type_die, DW_AT_declaration, 1);
|
18911 |
|
|
|
18912 |
|
|
/* We don't need to do this for function-local types. */
|
18913 |
|
|
if (TYPE_STUB_DECL (type)
|
18914 |
|
|
&& ! decl_function_context (TYPE_STUB_DECL (type)))
|
18915 |
|
|
VEC_safe_push (tree, gc, incomplete_types, type);
|
18916 |
|
|
}
|
18917 |
|
|
|
18918 |
|
|
if (get_AT (type_die, DW_AT_name))
|
18919 |
|
|
add_pubtype (type, type_die);
|
18920 |
|
|
}
|
18921 |
|
|
|
18922 |
|
|
/* Generate a DIE for a subroutine _type_. */
|
18923 |
|
|
|
18924 |
|
|
static void
|
18925 |
|
|
gen_subroutine_type_die (tree type, dw_die_ref context_die)
|
18926 |
|
|
{
|
18927 |
|
|
tree return_type = TREE_TYPE (type);
|
18928 |
|
|
dw_die_ref subr_die
|
18929 |
|
|
= new_die (DW_TAG_subroutine_type,
|
18930 |
|
|
scope_die_for (type, context_die), type);
|
18931 |
|
|
|
18932 |
|
|
equate_type_number_to_die (type, subr_die);
|
18933 |
|
|
add_prototyped_attribute (subr_die, type);
|
18934 |
|
|
add_type_attribute (subr_die, return_type, 0, 0, context_die);
|
18935 |
|
|
gen_formal_types_die (type, subr_die);
|
18936 |
|
|
|
18937 |
|
|
if (get_AT (subr_die, DW_AT_name))
|
18938 |
|
|
add_pubtype (type, subr_die);
|
18939 |
|
|
}
|
18940 |
|
|
|
18941 |
|
|
/* Generate a DIE for a type definition. */
|
18942 |
|
|
|
18943 |
|
|
static void
|
18944 |
|
|
gen_typedef_die (tree decl, dw_die_ref context_die)
|
18945 |
|
|
{
|
18946 |
|
|
dw_die_ref type_die;
|
18947 |
|
|
tree origin;
|
18948 |
|
|
|
18949 |
|
|
if (TREE_ASM_WRITTEN (decl))
|
18950 |
|
|
return;
|
18951 |
|
|
|
18952 |
|
|
TREE_ASM_WRITTEN (decl) = 1;
|
18953 |
|
|
type_die = new_die (DW_TAG_typedef, context_die, decl);
|
18954 |
|
|
origin = decl_ultimate_origin (decl);
|
18955 |
|
|
if (origin != NULL)
|
18956 |
|
|
add_abstract_origin_attribute (type_die, origin);
|
18957 |
|
|
else
|
18958 |
|
|
{
|
18959 |
|
|
tree type;
|
18960 |
|
|
|
18961 |
|
|
add_name_and_src_coords_attributes (type_die, decl);
|
18962 |
|
|
if (DECL_ORIGINAL_TYPE (decl))
|
18963 |
|
|
{
|
18964 |
|
|
type = DECL_ORIGINAL_TYPE (decl);
|
18965 |
|
|
|
18966 |
|
|
gcc_assert (type != TREE_TYPE (decl));
|
18967 |
|
|
equate_type_number_to_die (TREE_TYPE (decl), type_die);
|
18968 |
|
|
}
|
18969 |
|
|
else
|
18970 |
|
|
type = TREE_TYPE (decl);
|
18971 |
|
|
|
18972 |
|
|
add_type_attribute (type_die, type, TREE_READONLY (decl),
|
18973 |
|
|
TREE_THIS_VOLATILE (decl), context_die);
|
18974 |
|
|
}
|
18975 |
|
|
|
18976 |
|
|
if (DECL_ABSTRACT (decl))
|
18977 |
|
|
equate_decl_number_to_die (decl, type_die);
|
18978 |
|
|
|
18979 |
|
|
if (get_AT (type_die, DW_AT_name))
|
18980 |
|
|
add_pubtype (decl, type_die);
|
18981 |
|
|
}
|
18982 |
|
|
|
18983 |
|
|
/* Generate a type description DIE. */
|
18984 |
|
|
|
18985 |
|
|
static void
|
18986 |
|
|
gen_type_die_with_usage (tree type, dw_die_ref context_die,
|
18987 |
|
|
enum debug_info_usage usage)
|
18988 |
|
|
{
|
18989 |
|
|
int need_pop;
|
18990 |
|
|
struct array_descr_info info;
|
18991 |
|
|
|
18992 |
|
|
if (type == NULL_TREE || type == error_mark_node)
|
18993 |
|
|
return;
|
18994 |
|
|
|
18995 |
|
|
/* If TYPE is a typedef type variant, let's generate debug info
|
18996 |
|
|
for the parent typedef which TYPE is a type of. */
|
18997 |
|
|
if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
|
18998 |
|
|
&& DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
|
18999 |
|
|
{
|
19000 |
|
|
if (TREE_ASM_WRITTEN (type))
|
19001 |
|
|
return;
|
19002 |
|
|
|
19003 |
|
|
/* Prevent broken recursion; we can't hand off to the same type. */
|
19004 |
|
|
gcc_assert (DECL_ORIGINAL_TYPE (TYPE_NAME (type)) != type);
|
19005 |
|
|
|
19006 |
|
|
/* Use the DIE of the containing namespace as the parent DIE of
|
19007 |
|
|
the type description DIE we want to generate. */
|
19008 |
|
|
if (DECL_CONTEXT (TYPE_NAME (type))
|
19009 |
|
|
&& TREE_CODE (DECL_CONTEXT (TYPE_NAME (type))) == NAMESPACE_DECL)
|
19010 |
|
|
context_die = get_context_die (DECL_CONTEXT (TYPE_NAME (type)));
|
19011 |
|
|
|
19012 |
|
|
TREE_ASM_WRITTEN (type) = 1;
|
19013 |
|
|
gen_decl_die (TYPE_NAME (type), NULL, context_die);
|
19014 |
|
|
return;
|
19015 |
|
|
}
|
19016 |
|
|
|
19017 |
|
|
/* If this is an array type with hidden descriptor, handle it first. */
|
19018 |
|
|
if (!TREE_ASM_WRITTEN (type)
|
19019 |
|
|
&& lang_hooks.types.get_array_descr_info
|
19020 |
|
|
&& lang_hooks.types.get_array_descr_info (type, &info)
|
19021 |
|
|
&& (dwarf_version >= 3 || !dwarf_strict))
|
19022 |
|
|
{
|
19023 |
|
|
gen_descr_array_type_die (type, &info, context_die);
|
19024 |
|
|
TREE_ASM_WRITTEN (type) = 1;
|
19025 |
|
|
return;
|
19026 |
|
|
}
|
19027 |
|
|
|
19028 |
|
|
/* We are going to output a DIE to represent the unqualified version
|
19029 |
|
|
of this type (i.e. without any const or volatile qualifiers) so
|
19030 |
|
|
get the main variant (i.e. the unqualified version) of this type
|
19031 |
|
|
now. (Vectors are special because the debugging info is in the
|
19032 |
|
|
cloned type itself). */
|
19033 |
|
|
if (TREE_CODE (type) != VECTOR_TYPE)
|
19034 |
|
|
type = type_main_variant (type);
|
19035 |
|
|
|
19036 |
|
|
if (TREE_ASM_WRITTEN (type))
|
19037 |
|
|
return;
|
19038 |
|
|
|
19039 |
|
|
switch (TREE_CODE (type))
|
19040 |
|
|
{
|
19041 |
|
|
case ERROR_MARK:
|
19042 |
|
|
break;
|
19043 |
|
|
|
19044 |
|
|
case POINTER_TYPE:
|
19045 |
|
|
case REFERENCE_TYPE:
|
19046 |
|
|
/* We must set TREE_ASM_WRITTEN in case this is a recursive type. This
|
19047 |
|
|
ensures that the gen_type_die recursion will terminate even if the
|
19048 |
|
|
type is recursive. Recursive types are possible in Ada. */
|
19049 |
|
|
/* ??? We could perhaps do this for all types before the switch
|
19050 |
|
|
statement. */
|
19051 |
|
|
TREE_ASM_WRITTEN (type) = 1;
|
19052 |
|
|
|
19053 |
|
|
/* For these types, all that is required is that we output a DIE (or a
|
19054 |
|
|
set of DIEs) to represent the "basis" type. */
|
19055 |
|
|
gen_type_die_with_usage (TREE_TYPE (type), context_die,
|
19056 |
|
|
DINFO_USAGE_IND_USE);
|
19057 |
|
|
break;
|
19058 |
|
|
|
19059 |
|
|
case OFFSET_TYPE:
|
19060 |
|
|
/* This code is used for C++ pointer-to-data-member types.
|
19061 |
|
|
Output a description of the relevant class type. */
|
19062 |
|
|
gen_type_die_with_usage (TYPE_OFFSET_BASETYPE (type), context_die,
|
19063 |
|
|
DINFO_USAGE_IND_USE);
|
19064 |
|
|
|
19065 |
|
|
/* Output a description of the type of the object pointed to. */
|
19066 |
|
|
gen_type_die_with_usage (TREE_TYPE (type), context_die,
|
19067 |
|
|
DINFO_USAGE_IND_USE);
|
19068 |
|
|
|
19069 |
|
|
/* Now output a DIE to represent this pointer-to-data-member type
|
19070 |
|
|
itself. */
|
19071 |
|
|
gen_ptr_to_mbr_type_die (type, context_die);
|
19072 |
|
|
break;
|
19073 |
|
|
|
19074 |
|
|
case FUNCTION_TYPE:
|
19075 |
|
|
/* Force out return type (in case it wasn't forced out already). */
|
19076 |
|
|
gen_type_die_with_usage (TREE_TYPE (type), context_die,
|
19077 |
|
|
DINFO_USAGE_DIR_USE);
|
19078 |
|
|
gen_subroutine_type_die (type, context_die);
|
19079 |
|
|
break;
|
19080 |
|
|
|
19081 |
|
|
case METHOD_TYPE:
|
19082 |
|
|
/* Force out return type (in case it wasn't forced out already). */
|
19083 |
|
|
gen_type_die_with_usage (TREE_TYPE (type), context_die,
|
19084 |
|
|
DINFO_USAGE_DIR_USE);
|
19085 |
|
|
gen_subroutine_type_die (type, context_die);
|
19086 |
|
|
break;
|
19087 |
|
|
|
19088 |
|
|
case ARRAY_TYPE:
|
19089 |
|
|
gen_array_type_die (type, context_die);
|
19090 |
|
|
break;
|
19091 |
|
|
|
19092 |
|
|
case VECTOR_TYPE:
|
19093 |
|
|
gen_array_type_die (type, context_die);
|
19094 |
|
|
break;
|
19095 |
|
|
|
19096 |
|
|
case ENUMERAL_TYPE:
|
19097 |
|
|
case RECORD_TYPE:
|
19098 |
|
|
case UNION_TYPE:
|
19099 |
|
|
case QUAL_UNION_TYPE:
|
19100 |
|
|
/* If this is a nested type whose containing class hasn't been written
|
19101 |
|
|
out yet, writing it out will cover this one, too. This does not apply
|
19102 |
|
|
to instantiations of member class templates; they need to be added to
|
19103 |
|
|
the containing class as they are generated. FIXME: This hurts the
|
19104 |
|
|
idea of combining type decls from multiple TUs, since we can't predict
|
19105 |
|
|
what set of template instantiations we'll get. */
|
19106 |
|
|
if (TYPE_CONTEXT (type)
|
19107 |
|
|
&& AGGREGATE_TYPE_P (TYPE_CONTEXT (type))
|
19108 |
|
|
&& ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
|
19109 |
|
|
{
|
19110 |
|
|
gen_type_die_with_usage (TYPE_CONTEXT (type), context_die, usage);
|
19111 |
|
|
|
19112 |
|
|
if (TREE_ASM_WRITTEN (type))
|
19113 |
|
|
return;
|
19114 |
|
|
|
19115 |
|
|
/* If that failed, attach ourselves to the stub. */
|
19116 |
|
|
push_decl_scope (TYPE_CONTEXT (type));
|
19117 |
|
|
context_die = lookup_type_die (TYPE_CONTEXT (type));
|
19118 |
|
|
need_pop = 1;
|
19119 |
|
|
}
|
19120 |
|
|
else if (TYPE_CONTEXT (type) != NULL_TREE
|
19121 |
|
|
&& (TREE_CODE (TYPE_CONTEXT (type)) == FUNCTION_DECL))
|
19122 |
|
|
{
|
19123 |
|
|
/* If this type is local to a function that hasn't been written
|
19124 |
|
|
out yet, use a NULL context for now; it will be fixed up in
|
19125 |
|
|
decls_for_scope. */
|
19126 |
|
|
context_die = lookup_decl_die (TYPE_CONTEXT (type));
|
19127 |
|
|
need_pop = 0;
|
19128 |
|
|
}
|
19129 |
|
|
else
|
19130 |
|
|
{
|
19131 |
|
|
context_die = declare_in_namespace (type, context_die);
|
19132 |
|
|
need_pop = 0;
|
19133 |
|
|
}
|
19134 |
|
|
|
19135 |
|
|
if (TREE_CODE (type) == ENUMERAL_TYPE)
|
19136 |
|
|
{
|
19137 |
|
|
/* This might have been written out by the call to
|
19138 |
|
|
declare_in_namespace. */
|
19139 |
|
|
if (!TREE_ASM_WRITTEN (type))
|
19140 |
|
|
gen_enumeration_type_die (type, context_die);
|
19141 |
|
|
}
|
19142 |
|
|
else
|
19143 |
|
|
gen_struct_or_union_type_die (type, context_die, usage);
|
19144 |
|
|
|
19145 |
|
|
if (need_pop)
|
19146 |
|
|
pop_decl_scope ();
|
19147 |
|
|
|
19148 |
|
|
/* Don't set TREE_ASM_WRITTEN on an incomplete struct; we want to fix
|
19149 |
|
|
it up if it is ever completed. gen_*_type_die will set it for us
|
19150 |
|
|
when appropriate. */
|
19151 |
|
|
return;
|
19152 |
|
|
|
19153 |
|
|
case VOID_TYPE:
|
19154 |
|
|
case INTEGER_TYPE:
|
19155 |
|
|
case REAL_TYPE:
|
19156 |
|
|
case FIXED_POINT_TYPE:
|
19157 |
|
|
case COMPLEX_TYPE:
|
19158 |
|
|
case BOOLEAN_TYPE:
|
19159 |
|
|
/* No DIEs needed for fundamental types. */
|
19160 |
|
|
break;
|
19161 |
|
|
|
19162 |
|
|
case LANG_TYPE:
|
19163 |
|
|
/* No Dwarf representation currently defined. */
|
19164 |
|
|
break;
|
19165 |
|
|
|
19166 |
|
|
default:
|
19167 |
|
|
gcc_unreachable ();
|
19168 |
|
|
}
|
19169 |
|
|
|
19170 |
|
|
TREE_ASM_WRITTEN (type) = 1;
|
19171 |
|
|
}
|
19172 |
|
|
|
19173 |
|
|
static void
|
19174 |
|
|
gen_type_die (tree type, dw_die_ref context_die)
|
19175 |
|
|
{
|
19176 |
|
|
gen_type_die_with_usage (type, context_die, DINFO_USAGE_DIR_USE);
|
19177 |
|
|
}
|
19178 |
|
|
|
19179 |
|
|
/* Generate a DW_TAG_lexical_block DIE followed by DIEs to represent all of the
|
19180 |
|
|
things which are local to the given block. */
|
19181 |
|
|
|
19182 |
|
|
static void
|
19183 |
|
|
gen_block_die (tree stmt, dw_die_ref context_die, int depth)
|
19184 |
|
|
{
|
19185 |
|
|
int must_output_die = 0;
|
19186 |
|
|
bool inlined_func;
|
19187 |
|
|
|
19188 |
|
|
/* Ignore blocks that are NULL. */
|
19189 |
|
|
if (stmt == NULL_TREE)
|
19190 |
|
|
return;
|
19191 |
|
|
|
19192 |
|
|
inlined_func = inlined_function_outer_scope_p (stmt);
|
19193 |
|
|
|
19194 |
|
|
/* If the block is one fragment of a non-contiguous block, do not
|
19195 |
|
|
process the variables, since they will have been done by the
|
19196 |
|
|
origin block. Do process subblocks. */
|
19197 |
|
|
if (BLOCK_FRAGMENT_ORIGIN (stmt))
|
19198 |
|
|
{
|
19199 |
|
|
tree sub;
|
19200 |
|
|
|
19201 |
|
|
for (sub = BLOCK_SUBBLOCKS (stmt); sub; sub = BLOCK_CHAIN (sub))
|
19202 |
|
|
gen_block_die (sub, context_die, depth + 1);
|
19203 |
|
|
|
19204 |
|
|
return;
|
19205 |
|
|
}
|
19206 |
|
|
|
19207 |
|
|
/* Determine if we need to output any Dwarf DIEs at all to represent this
|
19208 |
|
|
block. */
|
19209 |
|
|
if (inlined_func)
|
19210 |
|
|
/* The outer scopes for inlinings *must* always be represented. We
|
19211 |
|
|
generate DW_TAG_inlined_subroutine DIEs for them. (See below.) */
|
19212 |
|
|
must_output_die = 1;
|
19213 |
|
|
else
|
19214 |
|
|
{
|
19215 |
|
|
/* Determine if this block directly contains any "significant"
|
19216 |
|
|
local declarations which we will need to output DIEs for. */
|
19217 |
|
|
if (debug_info_level > DINFO_LEVEL_TERSE)
|
19218 |
|
|
/* We are not in terse mode so *any* local declaration counts
|
19219 |
|
|
as being a "significant" one. */
|
19220 |
|
|
must_output_die = ((BLOCK_VARS (stmt) != NULL
|
19221 |
|
|
|| BLOCK_NUM_NONLOCALIZED_VARS (stmt))
|
19222 |
|
|
&& (TREE_USED (stmt)
|
19223 |
|
|
|| TREE_ASM_WRITTEN (stmt)
|
19224 |
|
|
|| BLOCK_ABSTRACT (stmt)));
|
19225 |
|
|
else if ((TREE_USED (stmt)
|
19226 |
|
|
|| TREE_ASM_WRITTEN (stmt)
|
19227 |
|
|
|| BLOCK_ABSTRACT (stmt))
|
19228 |
|
|
&& !dwarf2out_ignore_block (stmt))
|
19229 |
|
|
must_output_die = 1;
|
19230 |
|
|
}
|
19231 |
|
|
|
19232 |
|
|
/* It would be a waste of space to generate a Dwarf DW_TAG_lexical_block
|
19233 |
|
|
DIE for any block which contains no significant local declarations at
|
19234 |
|
|
all. Rather, in such cases we just call `decls_for_scope' so that any
|
19235 |
|
|
needed Dwarf info for any sub-blocks will get properly generated. Note
|
19236 |
|
|
that in terse mode, our definition of what constitutes a "significant"
|
19237 |
|
|
local declaration gets restricted to include only inlined function
|
19238 |
|
|
instances and local (nested) function definitions. */
|
19239 |
|
|
if (must_output_die)
|
19240 |
|
|
{
|
19241 |
|
|
if (inlined_func)
|
19242 |
|
|
{
|
19243 |
|
|
/* If STMT block is abstract, that means we have been called
|
19244 |
|
|
indirectly from dwarf2out_abstract_function.
|
19245 |
|
|
That function rightfully marks the descendent blocks (of
|
19246 |
|
|
the abstract function it is dealing with) as being abstract,
|
19247 |
|
|
precisely to prevent us from emitting any
|
19248 |
|
|
DW_TAG_inlined_subroutine DIE as a descendent
|
19249 |
|
|
of an abstract function instance. So in that case, we should
|
19250 |
|
|
not call gen_inlined_subroutine_die.
|
19251 |
|
|
|
19252 |
|
|
Later though, when cgraph asks dwarf2out to emit info
|
19253 |
|
|
for the concrete instance of the function decl into which
|
19254 |
|
|
the concrete instance of STMT got inlined, the later will lead
|
19255 |
|
|
to the generation of a DW_TAG_inlined_subroutine DIE. */
|
19256 |
|
|
if (! BLOCK_ABSTRACT (stmt))
|
19257 |
|
|
gen_inlined_subroutine_die (stmt, context_die, depth);
|
19258 |
|
|
}
|
19259 |
|
|
else
|
19260 |
|
|
gen_lexical_block_die (stmt, context_die, depth);
|
19261 |
|
|
}
|
19262 |
|
|
else
|
19263 |
|
|
decls_for_scope (stmt, context_die, depth);
|
19264 |
|
|
}
|
19265 |
|
|
|
19266 |
|
|
/* Process variable DECL (or variable with origin ORIGIN) within
|
19267 |
|
|
block STMT and add it to CONTEXT_DIE. */
|
19268 |
|
|
static void
|
19269 |
|
|
process_scope_var (tree stmt, tree decl, tree origin, dw_die_ref context_die)
|
19270 |
|
|
{
|
19271 |
|
|
dw_die_ref die;
|
19272 |
|
|
tree decl_or_origin = decl ? decl : origin;
|
19273 |
|
|
|
19274 |
|
|
if (TREE_CODE (decl_or_origin) == FUNCTION_DECL)
|
19275 |
|
|
die = lookup_decl_die (decl_or_origin);
|
19276 |
|
|
else if (TREE_CODE (decl_or_origin) == TYPE_DECL
|
19277 |
|
|
&& TYPE_DECL_IS_STUB (decl_or_origin))
|
19278 |
|
|
die = lookup_type_die (TREE_TYPE (decl_or_origin));
|
19279 |
|
|
else
|
19280 |
|
|
die = NULL;
|
19281 |
|
|
|
19282 |
|
|
if (die != NULL && die->die_parent == NULL)
|
19283 |
|
|
add_child_die (context_die, die);
|
19284 |
|
|
else if (TREE_CODE (decl_or_origin) == IMPORTED_DECL)
|
19285 |
|
|
dwarf2out_imported_module_or_decl_1 (decl_or_origin, DECL_NAME (decl_or_origin),
|
19286 |
|
|
stmt, context_die);
|
19287 |
|
|
else
|
19288 |
|
|
gen_decl_die (decl, origin, context_die);
|
19289 |
|
|
}
|
19290 |
|
|
|
19291 |
|
|
/* Generate all of the decls declared within a given scope and (recursively)
|
19292 |
|
|
all of its sub-blocks. */
|
19293 |
|
|
|
19294 |
|
|
static void
|
19295 |
|
|
decls_for_scope (tree stmt, dw_die_ref context_die, int depth)
|
19296 |
|
|
{
|
19297 |
|
|
tree decl;
|
19298 |
|
|
unsigned int i;
|
19299 |
|
|
tree subblocks;
|
19300 |
|
|
|
19301 |
|
|
/* Ignore NULL blocks. */
|
19302 |
|
|
if (stmt == NULL_TREE)
|
19303 |
|
|
return;
|
19304 |
|
|
|
19305 |
|
|
/* Output the DIEs to represent all of the data objects and typedefs
|
19306 |
|
|
declared directly within this block but not within any nested
|
19307 |
|
|
sub-blocks. Also, nested function and tag DIEs have been
|
19308 |
|
|
generated with a parent of NULL; fix that up now. */
|
19309 |
|
|
for (decl = BLOCK_VARS (stmt); decl != NULL; decl = TREE_CHAIN (decl))
|
19310 |
|
|
process_scope_var (stmt, decl, NULL_TREE, context_die);
|
19311 |
|
|
for (i = 0; i < BLOCK_NUM_NONLOCALIZED_VARS (stmt); i++)
|
19312 |
|
|
process_scope_var (stmt, NULL, BLOCK_NONLOCALIZED_VAR (stmt, i),
|
19313 |
|
|
context_die);
|
19314 |
|
|
|
19315 |
|
|
/* If we're at -g1, we're not interested in subblocks. */
|
19316 |
|
|
if (debug_info_level <= DINFO_LEVEL_TERSE)
|
19317 |
|
|
return;
|
19318 |
|
|
|
19319 |
|
|
/* Output the DIEs to represent all sub-blocks (and the items declared
|
19320 |
|
|
therein) of this block. */
|
19321 |
|
|
for (subblocks = BLOCK_SUBBLOCKS (stmt);
|
19322 |
|
|
subblocks != NULL;
|
19323 |
|
|
subblocks = BLOCK_CHAIN (subblocks))
|
19324 |
|
|
gen_block_die (subblocks, context_die, depth + 1);
|
19325 |
|
|
}
|
19326 |
|
|
|
19327 |
|
|
/* Is this a typedef we can avoid emitting? */
|
19328 |
|
|
|
19329 |
|
|
static inline int
|
19330 |
|
|
is_redundant_typedef (const_tree decl)
|
19331 |
|
|
{
|
19332 |
|
|
if (TYPE_DECL_IS_STUB (decl))
|
19333 |
|
|
return 1;
|
19334 |
|
|
|
19335 |
|
|
if (DECL_ARTIFICIAL (decl)
|
19336 |
|
|
&& DECL_CONTEXT (decl)
|
19337 |
|
|
&& is_tagged_type (DECL_CONTEXT (decl))
|
19338 |
|
|
&& TREE_CODE (TYPE_NAME (DECL_CONTEXT (decl))) == TYPE_DECL
|
19339 |
|
|
&& DECL_NAME (decl) == DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))))
|
19340 |
|
|
/* Also ignore the artificial member typedef for the class name. */
|
19341 |
|
|
return 1;
|
19342 |
|
|
|
19343 |
|
|
return 0;
|
19344 |
|
|
}
|
19345 |
|
|
|
19346 |
|
|
/* Returns the DIE for a context. */
|
19347 |
|
|
|
19348 |
|
|
static inline dw_die_ref
|
19349 |
|
|
get_context_die (tree context)
|
19350 |
|
|
{
|
19351 |
|
|
if (context)
|
19352 |
|
|
{
|
19353 |
|
|
/* Find die that represents this context. */
|
19354 |
|
|
if (TYPE_P (context))
|
19355 |
|
|
return force_type_die (TYPE_MAIN_VARIANT (context));
|
19356 |
|
|
else
|
19357 |
|
|
return force_decl_die (context);
|
19358 |
|
|
}
|
19359 |
|
|
return comp_unit_die;
|
19360 |
|
|
}
|
19361 |
|
|
|
19362 |
|
|
/* Returns the DIE for decl. A DIE will always be returned. */
|
19363 |
|
|
|
19364 |
|
|
static dw_die_ref
|
19365 |
|
|
force_decl_die (tree decl)
|
19366 |
|
|
{
|
19367 |
|
|
dw_die_ref decl_die;
|
19368 |
|
|
unsigned saved_external_flag;
|
19369 |
|
|
tree save_fn = NULL_TREE;
|
19370 |
|
|
decl_die = lookup_decl_die (decl);
|
19371 |
|
|
if (!decl_die)
|
19372 |
|
|
{
|
19373 |
|
|
dw_die_ref context_die = get_context_die (DECL_CONTEXT (decl));
|
19374 |
|
|
|
19375 |
|
|
decl_die = lookup_decl_die (decl);
|
19376 |
|
|
if (decl_die)
|
19377 |
|
|
return decl_die;
|
19378 |
|
|
|
19379 |
|
|
switch (TREE_CODE (decl))
|
19380 |
|
|
{
|
19381 |
|
|
case FUNCTION_DECL:
|
19382 |
|
|
/* Clear current_function_decl, so that gen_subprogram_die thinks
|
19383 |
|
|
that this is a declaration. At this point, we just want to force
|
19384 |
|
|
declaration die. */
|
19385 |
|
|
save_fn = current_function_decl;
|
19386 |
|
|
current_function_decl = NULL_TREE;
|
19387 |
|
|
gen_subprogram_die (decl, context_die);
|
19388 |
|
|
current_function_decl = save_fn;
|
19389 |
|
|
break;
|
19390 |
|
|
|
19391 |
|
|
case VAR_DECL:
|
19392 |
|
|
/* Set external flag to force declaration die. Restore it after
|
19393 |
|
|
gen_decl_die() call. */
|
19394 |
|
|
saved_external_flag = DECL_EXTERNAL (decl);
|
19395 |
|
|
DECL_EXTERNAL (decl) = 1;
|
19396 |
|
|
gen_decl_die (decl, NULL, context_die);
|
19397 |
|
|
DECL_EXTERNAL (decl) = saved_external_flag;
|
19398 |
|
|
break;
|
19399 |
|
|
|
19400 |
|
|
case NAMESPACE_DECL:
|
19401 |
|
|
if (dwarf_version >= 3 || !dwarf_strict)
|
19402 |
|
|
dwarf2out_decl (decl);
|
19403 |
|
|
else
|
19404 |
|
|
/* DWARF2 has neither DW_TAG_module, nor DW_TAG_namespace. */
|
19405 |
|
|
decl_die = comp_unit_die;
|
19406 |
|
|
break;
|
19407 |
|
|
|
19408 |
|
|
default:
|
19409 |
|
|
gcc_unreachable ();
|
19410 |
|
|
}
|
19411 |
|
|
|
19412 |
|
|
/* We should be able to find the DIE now. */
|
19413 |
|
|
if (!decl_die)
|
19414 |
|
|
decl_die = lookup_decl_die (decl);
|
19415 |
|
|
gcc_assert (decl_die);
|
19416 |
|
|
}
|
19417 |
|
|
|
19418 |
|
|
return decl_die;
|
19419 |
|
|
}
|
19420 |
|
|
|
19421 |
|
|
/* Returns the DIE for TYPE, that must not be a base type. A DIE is
|
19422 |
|
|
always returned. */
|
19423 |
|
|
|
19424 |
|
|
static dw_die_ref
|
19425 |
|
|
force_type_die (tree type)
|
19426 |
|
|
{
|
19427 |
|
|
dw_die_ref type_die;
|
19428 |
|
|
|
19429 |
|
|
type_die = lookup_type_die (type);
|
19430 |
|
|
if (!type_die)
|
19431 |
|
|
{
|
19432 |
|
|
dw_die_ref context_die = get_context_die (TYPE_CONTEXT (type));
|
19433 |
|
|
|
19434 |
|
|
type_die = modified_type_die (type, TYPE_READONLY (type),
|
19435 |
|
|
TYPE_VOLATILE (type), context_die);
|
19436 |
|
|
gcc_assert (type_die);
|
19437 |
|
|
}
|
19438 |
|
|
return type_die;
|
19439 |
|
|
}
|
19440 |
|
|
|
19441 |
|
|
/* Force out any required namespaces to be able to output DECL,
|
19442 |
|
|
and return the new context_die for it, if it's changed. */
|
19443 |
|
|
|
19444 |
|
|
static dw_die_ref
|
19445 |
|
|
setup_namespace_context (tree thing, dw_die_ref context_die)
|
19446 |
|
|
{
|
19447 |
|
|
tree context = (DECL_P (thing)
|
19448 |
|
|
? DECL_CONTEXT (thing) : TYPE_CONTEXT (thing));
|
19449 |
|
|
if (context && TREE_CODE (context) == NAMESPACE_DECL)
|
19450 |
|
|
/* Force out the namespace. */
|
19451 |
|
|
context_die = force_decl_die (context);
|
19452 |
|
|
|
19453 |
|
|
return context_die;
|
19454 |
|
|
}
|
19455 |
|
|
|
19456 |
|
|
/* Emit a declaration DIE for THING (which is either a DECL or a tagged
|
19457 |
|
|
type) within its namespace, if appropriate.
|
19458 |
|
|
|
19459 |
|
|
For compatibility with older debuggers, namespace DIEs only contain
|
19460 |
|
|
declarations; all definitions are emitted at CU scope. */
|
19461 |
|
|
|
19462 |
|
|
static dw_die_ref
|
19463 |
|
|
declare_in_namespace (tree thing, dw_die_ref context_die)
|
19464 |
|
|
{
|
19465 |
|
|
dw_die_ref ns_context;
|
19466 |
|
|
|
19467 |
|
|
if (debug_info_level <= DINFO_LEVEL_TERSE)
|
19468 |
|
|
return context_die;
|
19469 |
|
|
|
19470 |
|
|
/* If this decl is from an inlined function, then don't try to emit it in its
|
19471 |
|
|
namespace, as we will get confused. It would have already been emitted
|
19472 |
|
|
when the abstract instance of the inline function was emitted anyways. */
|
19473 |
|
|
if (DECL_P (thing) && DECL_ABSTRACT_ORIGIN (thing))
|
19474 |
|
|
return context_die;
|
19475 |
|
|
|
19476 |
|
|
ns_context = setup_namespace_context (thing, context_die);
|
19477 |
|
|
|
19478 |
|
|
if (ns_context != context_die)
|
19479 |
|
|
{
|
19480 |
|
|
if (is_fortran ())
|
19481 |
|
|
return ns_context;
|
19482 |
|
|
if (DECL_P (thing))
|
19483 |
|
|
gen_decl_die (thing, NULL, ns_context);
|
19484 |
|
|
else
|
19485 |
|
|
gen_type_die (thing, ns_context);
|
19486 |
|
|
}
|
19487 |
|
|
return context_die;
|
19488 |
|
|
}
|
19489 |
|
|
|
19490 |
|
|
/* Generate a DIE for a namespace or namespace alias. */
|
19491 |
|
|
|
19492 |
|
|
static void
|
19493 |
|
|
gen_namespace_die (tree decl, dw_die_ref context_die)
|
19494 |
|
|
{
|
19495 |
|
|
dw_die_ref namespace_die;
|
19496 |
|
|
|
19497 |
|
|
/* Namespace aliases have a DECL_ABSTRACT_ORIGIN of the namespace
|
19498 |
|
|
they are an alias of. */
|
19499 |
|
|
if (DECL_ABSTRACT_ORIGIN (decl) == NULL)
|
19500 |
|
|
{
|
19501 |
|
|
/* Output a real namespace or module. */
|
19502 |
|
|
context_die = setup_namespace_context (decl, comp_unit_die);
|
19503 |
|
|
namespace_die = new_die (is_fortran ()
|
19504 |
|
|
? DW_TAG_module : DW_TAG_namespace,
|
19505 |
|
|
context_die, decl);
|
19506 |
|
|
/* For Fortran modules defined in different CU don't add src coords. */
|
19507 |
|
|
if (namespace_die->die_tag == DW_TAG_module && DECL_EXTERNAL (decl))
|
19508 |
|
|
{
|
19509 |
|
|
const char *name = dwarf2_name (decl, 0);
|
19510 |
|
|
if (name)
|
19511 |
|
|
add_name_attribute (namespace_die, name);
|
19512 |
|
|
}
|
19513 |
|
|
else
|
19514 |
|
|
add_name_and_src_coords_attributes (namespace_die, decl);
|
19515 |
|
|
if (DECL_EXTERNAL (decl))
|
19516 |
|
|
add_AT_flag (namespace_die, DW_AT_declaration, 1);
|
19517 |
|
|
equate_decl_number_to_die (decl, namespace_die);
|
19518 |
|
|
}
|
19519 |
|
|
else
|
19520 |
|
|
{
|
19521 |
|
|
/* Output a namespace alias. */
|
19522 |
|
|
|
19523 |
|
|
/* Force out the namespace we are an alias of, if necessary. */
|
19524 |
|
|
dw_die_ref origin_die
|
19525 |
|
|
= force_decl_die (DECL_ABSTRACT_ORIGIN (decl));
|
19526 |
|
|
|
19527 |
|
|
if (DECL_CONTEXT (decl) == NULL_TREE
|
19528 |
|
|
|| TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL)
|
19529 |
|
|
context_die = setup_namespace_context (decl, comp_unit_die);
|
19530 |
|
|
/* Now create the namespace alias DIE. */
|
19531 |
|
|
namespace_die = new_die (DW_TAG_imported_declaration, context_die, decl);
|
19532 |
|
|
add_name_and_src_coords_attributes (namespace_die, decl);
|
19533 |
|
|
add_AT_die_ref (namespace_die, DW_AT_import, origin_die);
|
19534 |
|
|
equate_decl_number_to_die (decl, namespace_die);
|
19535 |
|
|
}
|
19536 |
|
|
}
|
19537 |
|
|
|
19538 |
|
|
/* Generate Dwarf debug information for a decl described by DECL. */
|
19539 |
|
|
|
19540 |
|
|
static void
|
19541 |
|
|
gen_decl_die (tree decl, tree origin, dw_die_ref context_die)
|
19542 |
|
|
{
|
19543 |
|
|
tree decl_or_origin = decl ? decl : origin;
|
19544 |
|
|
tree class_origin = NULL, ultimate_origin;
|
19545 |
|
|
|
19546 |
|
|
if (DECL_P (decl_or_origin) && DECL_IGNORED_P (decl_or_origin))
|
19547 |
|
|
return;
|
19548 |
|
|
|
19549 |
|
|
switch (TREE_CODE (decl_or_origin))
|
19550 |
|
|
{
|
19551 |
|
|
case ERROR_MARK:
|
19552 |
|
|
break;
|
19553 |
|
|
|
19554 |
|
|
case CONST_DECL:
|
19555 |
|
|
if (!is_fortran ())
|
19556 |
|
|
{
|
19557 |
|
|
/* The individual enumerators of an enum type get output when we output
|
19558 |
|
|
the Dwarf representation of the relevant enum type itself. */
|
19559 |
|
|
break;
|
19560 |
|
|
}
|
19561 |
|
|
|
19562 |
|
|
/* Emit its type. */
|
19563 |
|
|
gen_type_die (TREE_TYPE (decl), context_die);
|
19564 |
|
|
|
19565 |
|
|
/* And its containing namespace. */
|
19566 |
|
|
context_die = declare_in_namespace (decl, context_die);
|
19567 |
|
|
|
19568 |
|
|
gen_const_die (decl, context_die);
|
19569 |
|
|
break;
|
19570 |
|
|
|
19571 |
|
|
case FUNCTION_DECL:
|
19572 |
|
|
/* Don't output any DIEs to represent mere function declarations,
|
19573 |
|
|
unless they are class members or explicit block externs. */
|
19574 |
|
|
if (DECL_INITIAL (decl_or_origin) == NULL_TREE
|
19575 |
|
|
&& DECL_CONTEXT (decl_or_origin) == NULL_TREE
|
19576 |
|
|
&& (current_function_decl == NULL_TREE
|
19577 |
|
|
|| DECL_ARTIFICIAL (decl_or_origin)))
|
19578 |
|
|
break;
|
19579 |
|
|
|
19580 |
|
|
#if 0
|
19581 |
|
|
/* FIXME */
|
19582 |
|
|
/* This doesn't work because the C frontend sets DECL_ABSTRACT_ORIGIN
|
19583 |
|
|
on local redeclarations of global functions. That seems broken. */
|
19584 |
|
|
if (current_function_decl != decl)
|
19585 |
|
|
/* This is only a declaration. */;
|
19586 |
|
|
#endif
|
19587 |
|
|
|
19588 |
|
|
/* If we're emitting a clone, emit info for the abstract instance. */
|
19589 |
|
|
if (origin || DECL_ORIGIN (decl) != decl)
|
19590 |
|
|
dwarf2out_abstract_function (origin
|
19591 |
|
|
? DECL_ORIGIN (origin)
|
19592 |
|
|
: DECL_ABSTRACT_ORIGIN (decl));
|
19593 |
|
|
|
19594 |
|
|
/* If we're emitting an out-of-line copy of an inline function,
|
19595 |
|
|
emit info for the abstract instance and set up to refer to it. */
|
19596 |
|
|
else if (cgraph_function_possibly_inlined_p (decl)
|
19597 |
|
|
&& ! DECL_ABSTRACT (decl)
|
19598 |
|
|
&& ! class_or_namespace_scope_p (context_die)
|
19599 |
|
|
/* dwarf2out_abstract_function won't emit a die if this is just
|
19600 |
|
|
a declaration. We must avoid setting DECL_ABSTRACT_ORIGIN in
|
19601 |
|
|
that case, because that works only if we have a die. */
|
19602 |
|
|
&& DECL_INITIAL (decl) != NULL_TREE)
|
19603 |
|
|
{
|
19604 |
|
|
dwarf2out_abstract_function (decl);
|
19605 |
|
|
set_decl_origin_self (decl);
|
19606 |
|
|
}
|
19607 |
|
|
|
19608 |
|
|
/* Otherwise we're emitting the primary DIE for this decl. */
|
19609 |
|
|
else if (debug_info_level > DINFO_LEVEL_TERSE)
|
19610 |
|
|
{
|
19611 |
|
|
/* Before we describe the FUNCTION_DECL itself, make sure that we
|
19612 |
|
|
have described its return type. */
|
19613 |
|
|
gen_type_die (TREE_TYPE (TREE_TYPE (decl)), context_die);
|
19614 |
|
|
|
19615 |
|
|
/* And its virtual context. */
|
19616 |
|
|
if (DECL_VINDEX (decl) != NULL_TREE)
|
19617 |
|
|
gen_type_die (DECL_CONTEXT (decl), context_die);
|
19618 |
|
|
|
19619 |
|
|
/* And its containing type. */
|
19620 |
|
|
if (!origin)
|
19621 |
|
|
origin = decl_class_context (decl);
|
19622 |
|
|
if (origin != NULL_TREE)
|
19623 |
|
|
gen_type_die_for_member (origin, decl, context_die);
|
19624 |
|
|
|
19625 |
|
|
/* And its containing namespace. */
|
19626 |
|
|
context_die = declare_in_namespace (decl, context_die);
|
19627 |
|
|
}
|
19628 |
|
|
|
19629 |
|
|
/* Now output a DIE to represent the function itself. */
|
19630 |
|
|
if (decl)
|
19631 |
|
|
gen_subprogram_die (decl, context_die);
|
19632 |
|
|
break;
|
19633 |
|
|
|
19634 |
|
|
case TYPE_DECL:
|
19635 |
|
|
/* If we are in terse mode, don't generate any DIEs to represent any
|
19636 |
|
|
actual typedefs. */
|
19637 |
|
|
if (debug_info_level <= DINFO_LEVEL_TERSE)
|
19638 |
|
|
break;
|
19639 |
|
|
|
19640 |
|
|
/* In the special case of a TYPE_DECL node representing the declaration
|
19641 |
|
|
of some type tag, if the given TYPE_DECL is marked as having been
|
19642 |
|
|
instantiated from some other (original) TYPE_DECL node (e.g. one which
|
19643 |
|
|
was generated within the original definition of an inline function) we
|
19644 |
|
|
used to generate a special (abbreviated) DW_TAG_structure_type,
|
19645 |
|
|
DW_TAG_union_type, or DW_TAG_enumeration_type DIE here. But nothing
|
19646 |
|
|
should be actually referencing those DIEs, as variable DIEs with that
|
19647 |
|
|
type would be emitted already in the abstract origin, so it was always
|
19648 |
|
|
removed during unused type prunning. Don't add anything in this
|
19649 |
|
|
case. */
|
19650 |
|
|
if (TYPE_DECL_IS_STUB (decl) && decl_ultimate_origin (decl) != NULL_TREE)
|
19651 |
|
|
break;
|
19652 |
|
|
|
19653 |
|
|
if (is_redundant_typedef (decl))
|
19654 |
|
|
gen_type_die (TREE_TYPE (decl), context_die);
|
19655 |
|
|
else
|
19656 |
|
|
/* Output a DIE to represent the typedef itself. */
|
19657 |
|
|
gen_typedef_die (decl, context_die);
|
19658 |
|
|
break;
|
19659 |
|
|
|
19660 |
|
|
case LABEL_DECL:
|
19661 |
|
|
if (debug_info_level >= DINFO_LEVEL_NORMAL)
|
19662 |
|
|
gen_label_die (decl, context_die);
|
19663 |
|
|
break;
|
19664 |
|
|
|
19665 |
|
|
case VAR_DECL:
|
19666 |
|
|
case RESULT_DECL:
|
19667 |
|
|
/* If we are in terse mode, don't generate any DIEs to represent any
|
19668 |
|
|
variable declarations or definitions. */
|
19669 |
|
|
if (debug_info_level <= DINFO_LEVEL_TERSE)
|
19670 |
|
|
break;
|
19671 |
|
|
|
19672 |
|
|
/* Output any DIEs that are needed to specify the type of this data
|
19673 |
|
|
object. */
|
19674 |
|
|
if (decl_by_reference_p (decl_or_origin))
|
19675 |
|
|
gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
|
19676 |
|
|
else
|
19677 |
|
|
gen_type_die (TREE_TYPE (decl_or_origin), context_die);
|
19678 |
|
|
|
19679 |
|
|
/* And its containing type. */
|
19680 |
|
|
class_origin = decl_class_context (decl_or_origin);
|
19681 |
|
|
if (class_origin != NULL_TREE)
|
19682 |
|
|
gen_type_die_for_member (class_origin, decl_or_origin, context_die);
|
19683 |
|
|
|
19684 |
|
|
/* And its containing namespace. */
|
19685 |
|
|
context_die = declare_in_namespace (decl_or_origin, context_die);
|
19686 |
|
|
|
19687 |
|
|
/* Now output the DIE to represent the data object itself. This gets
|
19688 |
|
|
complicated because of the possibility that the VAR_DECL really
|
19689 |
|
|
represents an inlined instance of a formal parameter for an inline
|
19690 |
|
|
function. */
|
19691 |
|
|
ultimate_origin = decl_ultimate_origin (decl_or_origin);
|
19692 |
|
|
if (ultimate_origin != NULL_TREE
|
19693 |
|
|
&& TREE_CODE (ultimate_origin) == PARM_DECL)
|
19694 |
|
|
gen_formal_parameter_die (decl, origin,
|
19695 |
|
|
true /* Emit name attribute. */,
|
19696 |
|
|
context_die);
|
19697 |
|
|
else
|
19698 |
|
|
gen_variable_die (decl, origin, context_die);
|
19699 |
|
|
break;
|
19700 |
|
|
|
19701 |
|
|
case FIELD_DECL:
|
19702 |
|
|
/* Ignore the nameless fields that are used to skip bits but handle C++
|
19703 |
|
|
anonymous unions and structs. */
|
19704 |
|
|
if (DECL_NAME (decl) != NULL_TREE
|
19705 |
|
|
|| TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE
|
19706 |
|
|
|| TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
|
19707 |
|
|
{
|
19708 |
|
|
gen_type_die (member_declared_type (decl), context_die);
|
19709 |
|
|
gen_field_die (decl, context_die);
|
19710 |
|
|
}
|
19711 |
|
|
break;
|
19712 |
|
|
|
19713 |
|
|
case PARM_DECL:
|
19714 |
|
|
if (DECL_BY_REFERENCE (decl_or_origin))
|
19715 |
|
|
gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
|
19716 |
|
|
else
|
19717 |
|
|
gen_type_die (TREE_TYPE (decl_or_origin), context_die);
|
19718 |
|
|
gen_formal_parameter_die (decl, origin,
|
19719 |
|
|
true /* Emit name attribute. */,
|
19720 |
|
|
context_die);
|
19721 |
|
|
break;
|
19722 |
|
|
|
19723 |
|
|
case NAMESPACE_DECL:
|
19724 |
|
|
case IMPORTED_DECL:
|
19725 |
|
|
if (dwarf_version >= 3 || !dwarf_strict)
|
19726 |
|
|
gen_namespace_die (decl, context_die);
|
19727 |
|
|
break;
|
19728 |
|
|
|
19729 |
|
|
default:
|
19730 |
|
|
/* Probably some frontend-internal decl. Assume we don't care. */
|
19731 |
|
|
gcc_assert ((int)TREE_CODE (decl) > NUM_TREE_CODES);
|
19732 |
|
|
break;
|
19733 |
|
|
}
|
19734 |
|
|
}
|
19735 |
|
|
|
19736 |
|
|
/* Output debug information for global decl DECL. Called from toplev.c after
|
19737 |
|
|
compilation proper has finished. */
|
19738 |
|
|
|
19739 |
|
|
static void
|
19740 |
|
|
dwarf2out_global_decl (tree decl)
|
19741 |
|
|
{
|
19742 |
|
|
/* Output DWARF2 information for file-scope tentative data object
|
19743 |
|
|
declarations, file-scope (extern) function declarations (which
|
19744 |
|
|
had no corresponding body) and file-scope tagged type declarations
|
19745 |
|
|
and definitions which have not yet been forced out. */
|
19746 |
|
|
if (TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl))
|
19747 |
|
|
dwarf2out_decl (decl);
|
19748 |
|
|
}
|
19749 |
|
|
|
19750 |
|
|
/* Output debug information for type decl DECL. Called from toplev.c
|
19751 |
|
|
and from language front ends (to record built-in types). */
|
19752 |
|
|
static void
|
19753 |
|
|
dwarf2out_type_decl (tree decl, int local)
|
19754 |
|
|
{
|
19755 |
|
|
if (!local)
|
19756 |
|
|
dwarf2out_decl (decl);
|
19757 |
|
|
}
|
19758 |
|
|
|
19759 |
|
|
/* Output debug information for imported module or decl DECL.
|
19760 |
|
|
NAME is non-NULL name in the lexical block if the decl has been renamed.
|
19761 |
|
|
LEXICAL_BLOCK is the lexical block (which TREE_CODE is a BLOCK)
|
19762 |
|
|
that DECL belongs to.
|
19763 |
|
|
LEXICAL_BLOCK_DIE is the DIE of LEXICAL_BLOCK. */
|
19764 |
|
|
static void
|
19765 |
|
|
dwarf2out_imported_module_or_decl_1 (tree decl,
|
19766 |
|
|
tree name,
|
19767 |
|
|
tree lexical_block,
|
19768 |
|
|
dw_die_ref lexical_block_die)
|
19769 |
|
|
{
|
19770 |
|
|
expanded_location xloc;
|
19771 |
|
|
dw_die_ref imported_die = NULL;
|
19772 |
|
|
dw_die_ref at_import_die;
|
19773 |
|
|
|
19774 |
|
|
if (TREE_CODE (decl) == IMPORTED_DECL)
|
19775 |
|
|
{
|
19776 |
|
|
xloc = expand_location (DECL_SOURCE_LOCATION (decl));
|
19777 |
|
|
decl = IMPORTED_DECL_ASSOCIATED_DECL (decl);
|
19778 |
|
|
gcc_assert (decl);
|
19779 |
|
|
}
|
19780 |
|
|
else
|
19781 |
|
|
xloc = expand_location (input_location);
|
19782 |
|
|
|
19783 |
|
|
if (TREE_CODE (decl) == TYPE_DECL || TREE_CODE (decl) == CONST_DECL)
|
19784 |
|
|
{
|
19785 |
|
|
at_import_die = force_type_die (TREE_TYPE (decl));
|
19786 |
|
|
/* For namespace N { typedef void T; } using N::T; base_type_die
|
19787 |
|
|
returns NULL, but DW_TAG_imported_declaration requires
|
19788 |
|
|
the DW_AT_import tag. Force creation of DW_TAG_typedef. */
|
19789 |
|
|
if (!at_import_die)
|
19790 |
|
|
{
|
19791 |
|
|
gcc_assert (TREE_CODE (decl) == TYPE_DECL);
|
19792 |
|
|
gen_typedef_die (decl, get_context_die (DECL_CONTEXT (decl)));
|
19793 |
|
|
at_import_die = lookup_type_die (TREE_TYPE (decl));
|
19794 |
|
|
gcc_assert (at_import_die);
|
19795 |
|
|
}
|
19796 |
|
|
}
|
19797 |
|
|
else
|
19798 |
|
|
{
|
19799 |
|
|
at_import_die = lookup_decl_die (decl);
|
19800 |
|
|
if (!at_import_die)
|
19801 |
|
|
{
|
19802 |
|
|
/* If we're trying to avoid duplicate debug info, we may not have
|
19803 |
|
|
emitted the member decl for this field. Emit it now. */
|
19804 |
|
|
if (TREE_CODE (decl) == FIELD_DECL)
|
19805 |
|
|
{
|
19806 |
|
|
tree type = DECL_CONTEXT (decl);
|
19807 |
|
|
|
19808 |
|
|
if (TYPE_CONTEXT (type)
|
19809 |
|
|
&& TYPE_P (TYPE_CONTEXT (type))
|
19810 |
|
|
&& !should_emit_struct_debug (TYPE_CONTEXT (type),
|
19811 |
|
|
DINFO_USAGE_DIR_USE))
|
19812 |
|
|
return;
|
19813 |
|
|
gen_type_die_for_member (type, decl,
|
19814 |
|
|
get_context_die (TYPE_CONTEXT (type)));
|
19815 |
|
|
}
|
19816 |
|
|
at_import_die = force_decl_die (decl);
|
19817 |
|
|
}
|
19818 |
|
|
}
|
19819 |
|
|
|
19820 |
|
|
if (TREE_CODE (decl) == NAMESPACE_DECL)
|
19821 |
|
|
{
|
19822 |
|
|
if (dwarf_version >= 3 || !dwarf_strict)
|
19823 |
|
|
imported_die = new_die (DW_TAG_imported_module,
|
19824 |
|
|
lexical_block_die,
|
19825 |
|
|
lexical_block);
|
19826 |
|
|
else
|
19827 |
|
|
return;
|
19828 |
|
|
}
|
19829 |
|
|
else
|
19830 |
|
|
imported_die = new_die (DW_TAG_imported_declaration,
|
19831 |
|
|
lexical_block_die,
|
19832 |
|
|
lexical_block);
|
19833 |
|
|
|
19834 |
|
|
add_AT_file (imported_die, DW_AT_decl_file, lookup_filename (xloc.file));
|
19835 |
|
|
add_AT_unsigned (imported_die, DW_AT_decl_line, xloc.line);
|
19836 |
|
|
if (name)
|
19837 |
|
|
add_AT_string (imported_die, DW_AT_name,
|
19838 |
|
|
IDENTIFIER_POINTER (name));
|
19839 |
|
|
add_AT_die_ref (imported_die, DW_AT_import, at_import_die);
|
19840 |
|
|
}
|
19841 |
|
|
|
19842 |
|
|
/* Output debug information for imported module or decl DECL.
|
19843 |
|
|
NAME is non-NULL name in context if the decl has been renamed.
|
19844 |
|
|
CHILD is true if decl is one of the renamed decls as part of
|
19845 |
|
|
importing whole module. */
|
19846 |
|
|
|
19847 |
|
|
static void
|
19848 |
|
|
dwarf2out_imported_module_or_decl (tree decl, tree name, tree context,
|
19849 |
|
|
bool child)
|
19850 |
|
|
{
|
19851 |
|
|
/* dw_die_ref at_import_die; */
|
19852 |
|
|
dw_die_ref scope_die;
|
19853 |
|
|
|
19854 |
|
|
if (debug_info_level <= DINFO_LEVEL_TERSE)
|
19855 |
|
|
return;
|
19856 |
|
|
|
19857 |
|
|
gcc_assert (decl);
|
19858 |
|
|
|
19859 |
|
|
/* To emit DW_TAG_imported_module or DW_TAG_imported_decl, we need two DIEs.
|
19860 |
|
|
We need decl DIE for reference and scope die. First, get DIE for the decl
|
19861 |
|
|
itself. */
|
19862 |
|
|
|
19863 |
|
|
/* Get the scope die for decl context. Use comp_unit_die for global module
|
19864 |
|
|
or decl. If die is not found for non globals, force new die. */
|
19865 |
|
|
if (context
|
19866 |
|
|
&& TYPE_P (context)
|
19867 |
|
|
&& !should_emit_struct_debug (context, DINFO_USAGE_DIR_USE))
|
19868 |
|
|
return;
|
19869 |
|
|
|
19870 |
|
|
if (!(dwarf_version >= 3 || !dwarf_strict))
|
19871 |
|
|
return;
|
19872 |
|
|
|
19873 |
|
|
scope_die = get_context_die (context);
|
19874 |
|
|
|
19875 |
|
|
if (child)
|
19876 |
|
|
{
|
19877 |
|
|
gcc_assert (scope_die->die_child);
|
19878 |
|
|
gcc_assert (scope_die->die_child->die_tag == DW_TAG_imported_module);
|
19879 |
|
|
gcc_assert (TREE_CODE (decl) != NAMESPACE_DECL);
|
19880 |
|
|
scope_die = scope_die->die_child;
|
19881 |
|
|
}
|
19882 |
|
|
|
19883 |
|
|
/* OK, now we have DIEs for decl as well as scope. Emit imported die. */
|
19884 |
|
|
dwarf2out_imported_module_or_decl_1 (decl, name, context, scope_die);
|
19885 |
|
|
|
19886 |
|
|
}
|
19887 |
|
|
|
19888 |
|
|
/* Write the debugging output for DECL. */
|
19889 |
|
|
|
19890 |
|
|
void
|
19891 |
|
|
dwarf2out_decl (tree decl)
|
19892 |
|
|
{
|
19893 |
|
|
dw_die_ref context_die = comp_unit_die;
|
19894 |
|
|
|
19895 |
|
|
switch (TREE_CODE (decl))
|
19896 |
|
|
{
|
19897 |
|
|
case ERROR_MARK:
|
19898 |
|
|
return;
|
19899 |
|
|
|
19900 |
|
|
case FUNCTION_DECL:
|
19901 |
|
|
/* What we would really like to do here is to filter out all mere
|
19902 |
|
|
file-scope declarations of file-scope functions which are never
|
19903 |
|
|
referenced later within this translation unit (and keep all of ones
|
19904 |
|
|
that *are* referenced later on) but we aren't clairvoyant, so we have
|
19905 |
|
|
no idea which functions will be referenced in the future (i.e. later
|
19906 |
|
|
on within the current translation unit). So here we just ignore all
|
19907 |
|
|
file-scope function declarations which are not also definitions. If
|
19908 |
|
|
and when the debugger needs to know something about these functions,
|
19909 |
|
|
it will have to hunt around and find the DWARF information associated
|
19910 |
|
|
with the definition of the function.
|
19911 |
|
|
|
19912 |
|
|
We can't just check DECL_EXTERNAL to find out which FUNCTION_DECL
|
19913 |
|
|
nodes represent definitions and which ones represent mere
|
19914 |
|
|
declarations. We have to check DECL_INITIAL instead. That's because
|
19915 |
|
|
the C front-end supports some weird semantics for "extern inline"
|
19916 |
|
|
function definitions. These can get inlined within the current
|
19917 |
|
|
translation unit (and thus, we need to generate Dwarf info for their
|
19918 |
|
|
abstract instances so that the Dwarf info for the concrete inlined
|
19919 |
|
|
instances can have something to refer to) but the compiler never
|
19920 |
|
|
generates any out-of-lines instances of such things (despite the fact
|
19921 |
|
|
that they *are* definitions).
|
19922 |
|
|
|
19923 |
|
|
The important point is that the C front-end marks these "extern
|
19924 |
|
|
inline" functions as DECL_EXTERNAL, but we need to generate DWARF for
|
19925 |
|
|
them anyway. Note that the C++ front-end also plays some similar games
|
19926 |
|
|
for inline function definitions appearing within include files which
|
19927 |
|
|
also contain `#pragma interface' pragmas. */
|
19928 |
|
|
if (DECL_INITIAL (decl) == NULL_TREE)
|
19929 |
|
|
return;
|
19930 |
|
|
|
19931 |
|
|
/* If we're a nested function, initially use a parent of NULL; if we're
|
19932 |
|
|
a plain function, this will be fixed up in decls_for_scope. If
|
19933 |
|
|
we're a method, it will be ignored, since we already have a DIE. */
|
19934 |
|
|
if (decl_function_context (decl)
|
19935 |
|
|
/* But if we're in terse mode, we don't care about scope. */
|
19936 |
|
|
&& debug_info_level > DINFO_LEVEL_TERSE)
|
19937 |
|
|
context_die = NULL;
|
19938 |
|
|
break;
|
19939 |
|
|
|
19940 |
|
|
case VAR_DECL:
|
19941 |
|
|
/* Ignore this VAR_DECL if it refers to a file-scope extern data object
|
19942 |
|
|
declaration and if the declaration was never even referenced from
|
19943 |
|
|
within this entire compilation unit. We suppress these DIEs in
|
19944 |
|
|
order to save space in the .debug section (by eliminating entries
|
19945 |
|
|
which are probably useless). Note that we must not suppress
|
19946 |
|
|
block-local extern declarations (whether used or not) because that
|
19947 |
|
|
would screw-up the debugger's name lookup mechanism and cause it to
|
19948 |
|
|
miss things which really ought to be in scope at a given point. */
|
19949 |
|
|
if (DECL_EXTERNAL (decl) && !TREE_USED (decl))
|
19950 |
|
|
return;
|
19951 |
|
|
|
19952 |
|
|
/* For local statics lookup proper context die. */
|
19953 |
|
|
if (TREE_STATIC (decl) && decl_function_context (decl))
|
19954 |
|
|
context_die = lookup_decl_die (DECL_CONTEXT (decl));
|
19955 |
|
|
|
19956 |
|
|
/* If we are in terse mode, don't generate any DIEs to represent any
|
19957 |
|
|
variable declarations or definitions. */
|
19958 |
|
|
if (debug_info_level <= DINFO_LEVEL_TERSE)
|
19959 |
|
|
return;
|
19960 |
|
|
break;
|
19961 |
|
|
|
19962 |
|
|
case CONST_DECL:
|
19963 |
|
|
if (debug_info_level <= DINFO_LEVEL_TERSE)
|
19964 |
|
|
return;
|
19965 |
|
|
if (!is_fortran ())
|
19966 |
|
|
return;
|
19967 |
|
|
if (TREE_STATIC (decl) && decl_function_context (decl))
|
19968 |
|
|
context_die = lookup_decl_die (DECL_CONTEXT (decl));
|
19969 |
|
|
break;
|
19970 |
|
|
|
19971 |
|
|
case NAMESPACE_DECL:
|
19972 |
|
|
case IMPORTED_DECL:
|
19973 |
|
|
if (debug_info_level <= DINFO_LEVEL_TERSE)
|
19974 |
|
|
return;
|
19975 |
|
|
if (lookup_decl_die (decl) != NULL)
|
19976 |
|
|
return;
|
19977 |
|
|
break;
|
19978 |
|
|
|
19979 |
|
|
case TYPE_DECL:
|
19980 |
|
|
/* Don't emit stubs for types unless they are needed by other DIEs. */
|
19981 |
|
|
if (TYPE_DECL_SUPPRESS_DEBUG (decl))
|
19982 |
|
|
return;
|
19983 |
|
|
|
19984 |
|
|
/* Don't bother trying to generate any DIEs to represent any of the
|
19985 |
|
|
normal built-in types for the language we are compiling. */
|
19986 |
|
|
if (DECL_IS_BUILTIN (decl))
|
19987 |
|
|
{
|
19988 |
|
|
/* OK, we need to generate one for `bool' so GDB knows what type
|
19989 |
|
|
comparisons have. */
|
19990 |
|
|
if (is_cxx ()
|
19991 |
|
|
&& TREE_CODE (TREE_TYPE (decl)) == BOOLEAN_TYPE
|
19992 |
|
|
&& ! DECL_IGNORED_P (decl))
|
19993 |
|
|
modified_type_die (TREE_TYPE (decl), 0, 0, NULL);
|
19994 |
|
|
|
19995 |
|
|
return;
|
19996 |
|
|
}
|
19997 |
|
|
|
19998 |
|
|
/* If we are in terse mode, don't generate any DIEs for types. */
|
19999 |
|
|
if (debug_info_level <= DINFO_LEVEL_TERSE)
|
20000 |
|
|
return;
|
20001 |
|
|
|
20002 |
|
|
/* If we're a function-scope tag, initially use a parent of NULL;
|
20003 |
|
|
this will be fixed up in decls_for_scope. */
|
20004 |
|
|
if (decl_function_context (decl))
|
20005 |
|
|
context_die = NULL;
|
20006 |
|
|
|
20007 |
|
|
break;
|
20008 |
|
|
|
20009 |
|
|
default:
|
20010 |
|
|
return;
|
20011 |
|
|
}
|
20012 |
|
|
|
20013 |
|
|
gen_decl_die (decl, NULL, context_die);
|
20014 |
|
|
}
|
20015 |
|
|
|
20016 |
|
|
/* Write the debugging output for DECL. */
|
20017 |
|
|
|
20018 |
|
|
static void
|
20019 |
|
|
dwarf2out_function_decl (tree decl)
|
20020 |
|
|
{
|
20021 |
|
|
dwarf2out_decl (decl);
|
20022 |
|
|
|
20023 |
|
|
htab_empty (decl_loc_table);
|
20024 |
|
|
}
|
20025 |
|
|
|
20026 |
|
|
/* Output a marker (i.e. a label) for the beginning of the generated code for
|
20027 |
|
|
a lexical block. */
|
20028 |
|
|
|
20029 |
|
|
static void
|
20030 |
|
|
dwarf2out_begin_block (unsigned int line ATTRIBUTE_UNUSED,
|
20031 |
|
|
unsigned int blocknum)
|
20032 |
|
|
{
|
20033 |
|
|
switch_to_section (current_function_section ());
|
20034 |
|
|
ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_BEGIN_LABEL, blocknum);
|
20035 |
|
|
}
|
20036 |
|
|
|
20037 |
|
|
/* Output a marker (i.e. a label) for the end of the generated code for a
|
20038 |
|
|
lexical block. */
|
20039 |
|
|
|
20040 |
|
|
static void
|
20041 |
|
|
dwarf2out_end_block (unsigned int line ATTRIBUTE_UNUSED, unsigned int blocknum)
|
20042 |
|
|
{
|
20043 |
|
|
switch_to_section (current_function_section ());
|
20044 |
|
|
ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_END_LABEL, blocknum);
|
20045 |
|
|
}
|
20046 |
|
|
|
20047 |
|
|
/* Returns nonzero if it is appropriate not to emit any debugging
|
20048 |
|
|
information for BLOCK, because it doesn't contain any instructions.
|
20049 |
|
|
|
20050 |
|
|
Don't allow this for blocks with nested functions or local classes
|
20051 |
|
|
as we would end up with orphans, and in the presence of scheduling
|
20052 |
|
|
we may end up calling them anyway. */
|
20053 |
|
|
|
20054 |
|
|
static bool
|
20055 |
|
|
dwarf2out_ignore_block (const_tree block)
|
20056 |
|
|
{
|
20057 |
|
|
tree decl;
|
20058 |
|
|
unsigned int i;
|
20059 |
|
|
|
20060 |
|
|
for (decl = BLOCK_VARS (block); decl; decl = TREE_CHAIN (decl))
|
20061 |
|
|
if (TREE_CODE (decl) == FUNCTION_DECL
|
20062 |
|
|
|| (TREE_CODE (decl) == TYPE_DECL && TYPE_DECL_IS_STUB (decl)))
|
20063 |
|
|
return 0;
|
20064 |
|
|
for (i = 0; i < BLOCK_NUM_NONLOCALIZED_VARS (block); i++)
|
20065 |
|
|
{
|
20066 |
|
|
decl = BLOCK_NONLOCALIZED_VAR (block, i);
|
20067 |
|
|
if (TREE_CODE (decl) == FUNCTION_DECL
|
20068 |
|
|
|| (TREE_CODE (decl) == TYPE_DECL && TYPE_DECL_IS_STUB (decl)))
|
20069 |
|
|
return 0;
|
20070 |
|
|
}
|
20071 |
|
|
|
20072 |
|
|
return 1;
|
20073 |
|
|
}
|
20074 |
|
|
|
20075 |
|
|
/* Hash table routines for file_hash. */
|
20076 |
|
|
|
20077 |
|
|
static int
|
20078 |
|
|
file_table_eq (const void *p1_p, const void *p2_p)
|
20079 |
|
|
{
|
20080 |
|
|
const struct dwarf_file_data *const p1 =
|
20081 |
|
|
(const struct dwarf_file_data *) p1_p;
|
20082 |
|
|
const char *const p2 = (const char *) p2_p;
|
20083 |
|
|
return strcmp (p1->filename, p2) == 0;
|
20084 |
|
|
}
|
20085 |
|
|
|
20086 |
|
|
static hashval_t
|
20087 |
|
|
file_table_hash (const void *p_p)
|
20088 |
|
|
{
|
20089 |
|
|
const struct dwarf_file_data *const p = (const struct dwarf_file_data *) p_p;
|
20090 |
|
|
return htab_hash_string (p->filename);
|
20091 |
|
|
}
|
20092 |
|
|
|
20093 |
|
|
/* Lookup FILE_NAME (in the list of filenames that we know about here in
|
20094 |
|
|
dwarf2out.c) and return its "index". The index of each (known) filename is
|
20095 |
|
|
just a unique number which is associated with only that one filename. We
|
20096 |
|
|
need such numbers for the sake of generating labels (in the .debug_sfnames
|
20097 |
|
|
section) and references to those files numbers (in the .debug_srcinfo
|
20098 |
|
|
and.debug_macinfo sections). If the filename given as an argument is not
|
20099 |
|
|
found in our current list, add it to the list and assign it the next
|
20100 |
|
|
available unique index number. In order to speed up searches, we remember
|
20101 |
|
|
the index of the filename was looked up last. This handles the majority of
|
20102 |
|
|
all searches. */
|
20103 |
|
|
|
20104 |
|
|
static struct dwarf_file_data *
|
20105 |
|
|
lookup_filename (const char *file_name)
|
20106 |
|
|
{
|
20107 |
|
|
void ** slot;
|
20108 |
|
|
struct dwarf_file_data * created;
|
20109 |
|
|
|
20110 |
|
|
/* Check to see if the file name that was searched on the previous
|
20111 |
|
|
call matches this file name. If so, return the index. */
|
20112 |
|
|
if (file_table_last_lookup
|
20113 |
|
|
&& (file_name == file_table_last_lookup->filename
|
20114 |
|
|
|| strcmp (file_table_last_lookup->filename, file_name) == 0))
|
20115 |
|
|
return file_table_last_lookup;
|
20116 |
|
|
|
20117 |
|
|
/* Didn't match the previous lookup, search the table. */
|
20118 |
|
|
slot = htab_find_slot_with_hash (file_table, file_name,
|
20119 |
|
|
htab_hash_string (file_name), INSERT);
|
20120 |
|
|
if (*slot)
|
20121 |
|
|
return (struct dwarf_file_data *) *slot;
|
20122 |
|
|
|
20123 |
|
|
created = GGC_NEW (struct dwarf_file_data);
|
20124 |
|
|
created->filename = file_name;
|
20125 |
|
|
created->emitted_number = 0;
|
20126 |
|
|
*slot = created;
|
20127 |
|
|
return created;
|
20128 |
|
|
}
|
20129 |
|
|
|
20130 |
|
|
/* If the assembler will construct the file table, then translate the compiler
|
20131 |
|
|
internal file table number into the assembler file table number, and emit
|
20132 |
|
|
a .file directive if we haven't already emitted one yet. The file table
|
20133 |
|
|
numbers are different because we prune debug info for unused variables and
|
20134 |
|
|
types, which may include filenames. */
|
20135 |
|
|
|
20136 |
|
|
static int
|
20137 |
|
|
maybe_emit_file (struct dwarf_file_data * fd)
|
20138 |
|
|
{
|
20139 |
|
|
if (! fd->emitted_number)
|
20140 |
|
|
{
|
20141 |
|
|
if (last_emitted_file)
|
20142 |
|
|
fd->emitted_number = last_emitted_file->emitted_number + 1;
|
20143 |
|
|
else
|
20144 |
|
|
fd->emitted_number = 1;
|
20145 |
|
|
last_emitted_file = fd;
|
20146 |
|
|
|
20147 |
|
|
if (DWARF2_ASM_LINE_DEBUG_INFO)
|
20148 |
|
|
{
|
20149 |
|
|
fprintf (asm_out_file, "\t.file %u ", fd->emitted_number);
|
20150 |
|
|
output_quoted_string (asm_out_file,
|
20151 |
|
|
remap_debug_filename (fd->filename));
|
20152 |
|
|
fputc ('\n', asm_out_file);
|
20153 |
|
|
}
|
20154 |
|
|
}
|
20155 |
|
|
|
20156 |
|
|
return fd->emitted_number;
|
20157 |
|
|
}
|
20158 |
|
|
|
20159 |
|
|
/* Schedule generation of a DW_AT_const_value attribute to DIE.
|
20160 |
|
|
That generation should happen after function debug info has been
|
20161 |
|
|
generated. The value of the attribute is the constant value of ARG. */
|
20162 |
|
|
|
20163 |
|
|
static void
|
20164 |
|
|
append_entry_to_tmpl_value_parm_die_table (dw_die_ref die, tree arg)
|
20165 |
|
|
{
|
20166 |
|
|
die_arg_entry entry;
|
20167 |
|
|
|
20168 |
|
|
if (!die || !arg)
|
20169 |
|
|
return;
|
20170 |
|
|
|
20171 |
|
|
if (!tmpl_value_parm_die_table)
|
20172 |
|
|
tmpl_value_parm_die_table
|
20173 |
|
|
= VEC_alloc (die_arg_entry, gc, 32);
|
20174 |
|
|
|
20175 |
|
|
entry.die = die;
|
20176 |
|
|
entry.arg = arg;
|
20177 |
|
|
VEC_safe_push (die_arg_entry, gc,
|
20178 |
|
|
tmpl_value_parm_die_table,
|
20179 |
|
|
&entry);
|
20180 |
|
|
}
|
20181 |
|
|
|
20182 |
|
|
/* Add a DW_AT_const_value attribute to DIEs that were scheduled
|
20183 |
|
|
by append_entry_to_tmpl_value_parm_die_table. This function must
|
20184 |
|
|
be called after function DIEs have been generated. */
|
20185 |
|
|
|
20186 |
|
|
static void
|
20187 |
|
|
gen_remaining_tmpl_value_param_die_attribute (void)
|
20188 |
|
|
{
|
20189 |
|
|
if (tmpl_value_parm_die_table)
|
20190 |
|
|
{
|
20191 |
|
|
unsigned i;
|
20192 |
|
|
die_arg_entry *e;
|
20193 |
|
|
|
20194 |
|
|
for (i = 0;
|
20195 |
|
|
VEC_iterate (die_arg_entry, tmpl_value_parm_die_table, i, e);
|
20196 |
|
|
i++)
|
20197 |
|
|
tree_add_const_value_attribute (e->die, e->arg);
|
20198 |
|
|
}
|
20199 |
|
|
}
|
20200 |
|
|
|
20201 |
|
|
|
20202 |
|
|
/* Replace DW_AT_name for the decl with name. */
|
20203 |
|
|
|
20204 |
|
|
static void
|
20205 |
|
|
dwarf2out_set_name (tree decl, tree name)
|
20206 |
|
|
{
|
20207 |
|
|
dw_die_ref die;
|
20208 |
|
|
dw_attr_ref attr;
|
20209 |
|
|
const char *dname;
|
20210 |
|
|
|
20211 |
|
|
die = TYPE_SYMTAB_DIE (decl);
|
20212 |
|
|
if (!die)
|
20213 |
|
|
return;
|
20214 |
|
|
|
20215 |
|
|
dname = dwarf2_name (name, 0);
|
20216 |
|
|
if (!dname)
|
20217 |
|
|
return;
|
20218 |
|
|
|
20219 |
|
|
attr = get_AT (die, DW_AT_name);
|
20220 |
|
|
if (attr)
|
20221 |
|
|
{
|
20222 |
|
|
struct indirect_string_node *node;
|
20223 |
|
|
|
20224 |
|
|
node = find_AT_string (dname);
|
20225 |
|
|
/* replace the string. */
|
20226 |
|
|
attr->dw_attr_val.v.val_str = node;
|
20227 |
|
|
}
|
20228 |
|
|
|
20229 |
|
|
else
|
20230 |
|
|
add_name_attribute (die, dname);
|
20231 |
|
|
}
|
20232 |
|
|
|
20233 |
|
|
/* Called by the final INSN scan whenever we see a direct function call.
|
20234 |
|
|
Make an entry into the direct call table, recording the point of call
|
20235 |
|
|
and a reference to the target function's debug entry. */
|
20236 |
|
|
|
20237 |
|
|
static void
|
20238 |
|
|
dwarf2out_direct_call (tree targ)
|
20239 |
|
|
{
|
20240 |
|
|
dcall_entry e;
|
20241 |
|
|
tree origin = decl_ultimate_origin (targ);
|
20242 |
|
|
|
20243 |
|
|
/* If this is a clone, use the abstract origin as the target. */
|
20244 |
|
|
if (origin)
|
20245 |
|
|
targ = origin;
|
20246 |
|
|
|
20247 |
|
|
e.poc_label_num = poc_label_num++;
|
20248 |
|
|
e.poc_decl = current_function_decl;
|
20249 |
|
|
e.targ_die = force_decl_die (targ);
|
20250 |
|
|
VEC_safe_push (dcall_entry, gc, dcall_table, &e);
|
20251 |
|
|
|
20252 |
|
|
/* Drop a label at the return point to mark the point of call. */
|
20253 |
|
|
ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LPOC", e.poc_label_num);
|
20254 |
|
|
}
|
20255 |
|
|
|
20256 |
|
|
/* Returns a hash value for X (which really is a struct vcall_insn). */
|
20257 |
|
|
|
20258 |
|
|
static hashval_t
|
20259 |
|
|
vcall_insn_table_hash (const void *x)
|
20260 |
|
|
{
|
20261 |
|
|
return (hashval_t) ((const struct vcall_insn *) x)->insn_uid;
|
20262 |
|
|
}
|
20263 |
|
|
|
20264 |
|
|
/* Return nonzero if insn_uid of struct vcall_insn *X is the same as
|
20265 |
|
|
insnd_uid of *Y. */
|
20266 |
|
|
|
20267 |
|
|
static int
|
20268 |
|
|
vcall_insn_table_eq (const void *x, const void *y)
|
20269 |
|
|
{
|
20270 |
|
|
return (((const struct vcall_insn *) x)->insn_uid
|
20271 |
|
|
== ((const struct vcall_insn *) y)->insn_uid);
|
20272 |
|
|
}
|
20273 |
|
|
|
20274 |
|
|
/* Associate VTABLE_SLOT with INSN_UID in the VCALL_INSN_TABLE. */
|
20275 |
|
|
|
20276 |
|
|
static void
|
20277 |
|
|
store_vcall_insn (unsigned int vtable_slot, int insn_uid)
|
20278 |
|
|
{
|
20279 |
|
|
struct vcall_insn *item = GGC_NEW (struct vcall_insn);
|
20280 |
|
|
struct vcall_insn **slot;
|
20281 |
|
|
|
20282 |
|
|
gcc_assert (item);
|
20283 |
|
|
item->insn_uid = insn_uid;
|
20284 |
|
|
item->vtable_slot = vtable_slot;
|
20285 |
|
|
slot = (struct vcall_insn **)
|
20286 |
|
|
htab_find_slot_with_hash (vcall_insn_table, &item,
|
20287 |
|
|
(hashval_t) insn_uid, INSERT);
|
20288 |
|
|
*slot = item;
|
20289 |
|
|
}
|
20290 |
|
|
|
20291 |
|
|
/* Return the VTABLE_SLOT associated with INSN_UID. */
|
20292 |
|
|
|
20293 |
|
|
static unsigned int
|
20294 |
|
|
lookup_vcall_insn (unsigned int insn_uid)
|
20295 |
|
|
{
|
20296 |
|
|
struct vcall_insn item;
|
20297 |
|
|
struct vcall_insn *p;
|
20298 |
|
|
|
20299 |
|
|
item.insn_uid = insn_uid;
|
20300 |
|
|
item.vtable_slot = 0;
|
20301 |
|
|
p = (struct vcall_insn *) htab_find_with_hash (vcall_insn_table,
|
20302 |
|
|
(void *) &item,
|
20303 |
|
|
(hashval_t) insn_uid);
|
20304 |
|
|
if (p == NULL)
|
20305 |
|
|
return (unsigned int) -1;
|
20306 |
|
|
return p->vtable_slot;
|
20307 |
|
|
}
|
20308 |
|
|
|
20309 |
|
|
|
20310 |
|
|
/* Called when lowering indirect calls to RTL. We make a note of INSN_UID
|
20311 |
|
|
and the OBJ_TYPE_REF_TOKEN from ADDR. For C++ virtual calls, the token
|
20312 |
|
|
is the vtable slot index that we will need to put in the virtual call
|
20313 |
|
|
table later. */
|
20314 |
|
|
|
20315 |
|
|
static void
|
20316 |
|
|
dwarf2out_virtual_call_token (tree addr, int insn_uid)
|
20317 |
|
|
{
|
20318 |
|
|
if (is_cxx() && TREE_CODE (addr) == OBJ_TYPE_REF)
|
20319 |
|
|
{
|
20320 |
|
|
tree token = OBJ_TYPE_REF_TOKEN (addr);
|
20321 |
|
|
if (TREE_CODE (token) == INTEGER_CST)
|
20322 |
|
|
store_vcall_insn (TREE_INT_CST_LOW (token), insn_uid);
|
20323 |
|
|
}
|
20324 |
|
|
}
|
20325 |
|
|
|
20326 |
|
|
/* Called when scheduling RTL, when a CALL_INSN is split. Copies the
|
20327 |
|
|
OBJ_TYPE_REF_TOKEN previously associated with OLD_INSN and associates it
|
20328 |
|
|
with NEW_INSN. */
|
20329 |
|
|
|
20330 |
|
|
static void
|
20331 |
|
|
dwarf2out_copy_call_info (rtx old_insn, rtx new_insn)
|
20332 |
|
|
{
|
20333 |
|
|
unsigned int vtable_slot = lookup_vcall_insn (INSN_UID (old_insn));
|
20334 |
|
|
|
20335 |
|
|
if (vtable_slot != (unsigned int) -1)
|
20336 |
|
|
store_vcall_insn (vtable_slot, INSN_UID (new_insn));
|
20337 |
|
|
}
|
20338 |
|
|
|
20339 |
|
|
/* Called by the final INSN scan whenever we see a virtual function call.
|
20340 |
|
|
Make an entry into the virtual call table, recording the point of call
|
20341 |
|
|
and the slot index of the vtable entry used to call the virtual member
|
20342 |
|
|
function. The slot index was associated with the INSN_UID during the
|
20343 |
|
|
lowering to RTL. */
|
20344 |
|
|
|
20345 |
|
|
static void
|
20346 |
|
|
dwarf2out_virtual_call (int insn_uid)
|
20347 |
|
|
{
|
20348 |
|
|
unsigned int vtable_slot = lookup_vcall_insn (insn_uid);
|
20349 |
|
|
vcall_entry e;
|
20350 |
|
|
|
20351 |
|
|
if (vtable_slot == (unsigned int) -1)
|
20352 |
|
|
return;
|
20353 |
|
|
|
20354 |
|
|
e.poc_label_num = poc_label_num++;
|
20355 |
|
|
e.vtable_slot = vtable_slot;
|
20356 |
|
|
VEC_safe_push (vcall_entry, gc, vcall_table, &e);
|
20357 |
|
|
|
20358 |
|
|
/* Drop a label at the return point to mark the point of call. */
|
20359 |
|
|
ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LPOC", e.poc_label_num);
|
20360 |
|
|
}
|
20361 |
|
|
|
20362 |
|
|
/* Called by the final INSN scan whenever we see a var location. We
|
20363 |
|
|
use it to drop labels in the right places, and throw the location in
|
20364 |
|
|
our lookup table. */
|
20365 |
|
|
|
20366 |
|
|
static void
|
20367 |
|
|
dwarf2out_var_location (rtx loc_note)
|
20368 |
|
|
{
|
20369 |
|
|
char loclabel[MAX_ARTIFICIAL_LABEL_BYTES + 2];
|
20370 |
|
|
struct var_loc_node *newloc;
|
20371 |
|
|
rtx next_real;
|
20372 |
|
|
static const char *last_label;
|
20373 |
|
|
static const char *last_postcall_label;
|
20374 |
|
|
static bool last_in_cold_section_p;
|
20375 |
|
|
tree decl;
|
20376 |
|
|
|
20377 |
|
|
if (!DECL_P (NOTE_VAR_LOCATION_DECL (loc_note)))
|
20378 |
|
|
return;
|
20379 |
|
|
|
20380 |
|
|
next_real = next_real_insn (loc_note);
|
20381 |
|
|
/* If there are no instructions which would be affected by this note,
|
20382 |
|
|
don't do anything. */
|
20383 |
|
|
if (next_real == NULL_RTX)
|
20384 |
|
|
return;
|
20385 |
|
|
|
20386 |
|
|
decl = NOTE_VAR_LOCATION_DECL (loc_note);
|
20387 |
|
|
newloc = add_var_loc_to_decl (decl, loc_note);
|
20388 |
|
|
if (newloc == NULL)
|
20389 |
|
|
return;
|
20390 |
|
|
|
20391 |
|
|
/* If there were no real insns between note we processed last time
|
20392 |
|
|
and this note, use the label we emitted last time. */
|
20393 |
|
|
if (last_var_location_insn == NULL_RTX
|
20394 |
|
|
|| last_var_location_insn != next_real
|
20395 |
|
|
|| last_in_cold_section_p != in_cold_section_p)
|
20396 |
|
|
{
|
20397 |
|
|
ASM_GENERATE_INTERNAL_LABEL (loclabel, "LVL", loclabel_num);
|
20398 |
|
|
ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LVL", loclabel_num);
|
20399 |
|
|
loclabel_num++;
|
20400 |
|
|
last_label = ggc_strdup (loclabel);
|
20401 |
|
|
last_postcall_label = NULL;
|
20402 |
|
|
}
|
20403 |
|
|
newloc->var_loc_note = loc_note;
|
20404 |
|
|
newloc->next = NULL;
|
20405 |
|
|
|
20406 |
|
|
if (!NOTE_DURING_CALL_P (loc_note))
|
20407 |
|
|
newloc->label = last_label;
|
20408 |
|
|
else
|
20409 |
|
|
{
|
20410 |
|
|
if (!last_postcall_label)
|
20411 |
|
|
{
|
20412 |
|
|
sprintf (loclabel, "%s-1", last_label);
|
20413 |
|
|
last_postcall_label = ggc_strdup (loclabel);
|
20414 |
|
|
}
|
20415 |
|
|
newloc->label = last_postcall_label;
|
20416 |
|
|
}
|
20417 |
|
|
|
20418 |
|
|
last_var_location_insn = next_real;
|
20419 |
|
|
last_in_cold_section_p = in_cold_section_p;
|
20420 |
|
|
}
|
20421 |
|
|
|
20422 |
|
|
/* We need to reset the locations at the beginning of each
|
20423 |
|
|
function. We can't do this in the end_function hook, because the
|
20424 |
|
|
declarations that use the locations won't have been output when
|
20425 |
|
|
that hook is called. Also compute have_multiple_function_sections here. */
|
20426 |
|
|
|
20427 |
|
|
static void
|
20428 |
|
|
dwarf2out_begin_function (tree fun)
|
20429 |
|
|
{
|
20430 |
|
|
if (function_section (fun) != text_section)
|
20431 |
|
|
have_multiple_function_sections = true;
|
20432 |
|
|
|
20433 |
|
|
dwarf2out_note_section_used ();
|
20434 |
|
|
}
|
20435 |
|
|
|
20436 |
|
|
/* Output a label to mark the beginning of a source code line entry
|
20437 |
|
|
and record information relating to this source line, in
|
20438 |
|
|
'line_info_table' for later output of the .debug_line section. */
|
20439 |
|
|
|
20440 |
|
|
static void
|
20441 |
|
|
dwarf2out_source_line (unsigned int line, const char *filename,
|
20442 |
|
|
int discriminator, bool is_stmt)
|
20443 |
|
|
{
|
20444 |
|
|
static bool last_is_stmt = true;
|
20445 |
|
|
|
20446 |
|
|
if (debug_info_level >= DINFO_LEVEL_NORMAL
|
20447 |
|
|
&& line != 0)
|
20448 |
|
|
{
|
20449 |
|
|
int file_num = maybe_emit_file (lookup_filename (filename));
|
20450 |
|
|
|
20451 |
|
|
switch_to_section (current_function_section ());
|
20452 |
|
|
|
20453 |
|
|
/* If requested, emit something human-readable. */
|
20454 |
|
|
if (flag_debug_asm)
|
20455 |
|
|
fprintf (asm_out_file, "\t%s %s:%d\n", ASM_COMMENT_START,
|
20456 |
|
|
filename, line);
|
20457 |
|
|
|
20458 |
|
|
if (DWARF2_ASM_LINE_DEBUG_INFO)
|
20459 |
|
|
{
|
20460 |
|
|
/* Emit the .loc directive understood by GNU as. */
|
20461 |
|
|
fprintf (asm_out_file, "\t.loc %d %d 0", file_num, line);
|
20462 |
|
|
if (is_stmt != last_is_stmt)
|
20463 |
|
|
{
|
20464 |
|
|
fprintf (asm_out_file, " is_stmt %d", is_stmt ? 1 : 0);
|
20465 |
|
|
last_is_stmt = is_stmt;
|
20466 |
|
|
}
|
20467 |
|
|
if (SUPPORTS_DISCRIMINATOR && discriminator != 0)
|
20468 |
|
|
fprintf (asm_out_file, " discriminator %d", discriminator);
|
20469 |
|
|
fputc ('\n', asm_out_file);
|
20470 |
|
|
|
20471 |
|
|
/* Indicate that line number info exists. */
|
20472 |
|
|
line_info_table_in_use++;
|
20473 |
|
|
}
|
20474 |
|
|
else if (function_section (current_function_decl) != text_section)
|
20475 |
|
|
{
|
20476 |
|
|
dw_separate_line_info_ref line_info;
|
20477 |
|
|
targetm.asm_out.internal_label (asm_out_file,
|
20478 |
|
|
SEPARATE_LINE_CODE_LABEL,
|
20479 |
|
|
separate_line_info_table_in_use);
|
20480 |
|
|
|
20481 |
|
|
/* Expand the line info table if necessary. */
|
20482 |
|
|
if (separate_line_info_table_in_use
|
20483 |
|
|
== separate_line_info_table_allocated)
|
20484 |
|
|
{
|
20485 |
|
|
separate_line_info_table_allocated += LINE_INFO_TABLE_INCREMENT;
|
20486 |
|
|
separate_line_info_table
|
20487 |
|
|
= GGC_RESIZEVEC (dw_separate_line_info_entry,
|
20488 |
|
|
separate_line_info_table,
|
20489 |
|
|
separate_line_info_table_allocated);
|
20490 |
|
|
memset (separate_line_info_table
|
20491 |
|
|
+ separate_line_info_table_in_use,
|
20492 |
|
|
0,
|
20493 |
|
|
(LINE_INFO_TABLE_INCREMENT
|
20494 |
|
|
* sizeof (dw_separate_line_info_entry)));
|
20495 |
|
|
}
|
20496 |
|
|
|
20497 |
|
|
/* Add the new entry at the end of the line_info_table. */
|
20498 |
|
|
line_info
|
20499 |
|
|
= &separate_line_info_table[separate_line_info_table_in_use++];
|
20500 |
|
|
line_info->dw_file_num = file_num;
|
20501 |
|
|
line_info->dw_line_num = line;
|
20502 |
|
|
line_info->function = current_function_funcdef_no;
|
20503 |
|
|
}
|
20504 |
|
|
else
|
20505 |
|
|
{
|
20506 |
|
|
dw_line_info_ref line_info;
|
20507 |
|
|
|
20508 |
|
|
targetm.asm_out.internal_label (asm_out_file, LINE_CODE_LABEL,
|
20509 |
|
|
line_info_table_in_use);
|
20510 |
|
|
|
20511 |
|
|
/* Expand the line info table if necessary. */
|
20512 |
|
|
if (line_info_table_in_use == line_info_table_allocated)
|
20513 |
|
|
{
|
20514 |
|
|
line_info_table_allocated += LINE_INFO_TABLE_INCREMENT;
|
20515 |
|
|
line_info_table
|
20516 |
|
|
= GGC_RESIZEVEC (dw_line_info_entry, line_info_table,
|
20517 |
|
|
line_info_table_allocated);
|
20518 |
|
|
memset (line_info_table + line_info_table_in_use, 0,
|
20519 |
|
|
LINE_INFO_TABLE_INCREMENT * sizeof (dw_line_info_entry));
|
20520 |
|
|
}
|
20521 |
|
|
|
20522 |
|
|
/* Add the new entry at the end of the line_info_table. */
|
20523 |
|
|
line_info = &line_info_table[line_info_table_in_use++];
|
20524 |
|
|
line_info->dw_file_num = file_num;
|
20525 |
|
|
line_info->dw_line_num = line;
|
20526 |
|
|
}
|
20527 |
|
|
}
|
20528 |
|
|
}
|
20529 |
|
|
|
20530 |
|
|
/* Record the beginning of a new source file. */
|
20531 |
|
|
|
20532 |
|
|
static void
|
20533 |
|
|
dwarf2out_start_source_file (unsigned int lineno, const char *filename)
|
20534 |
|
|
{
|
20535 |
|
|
if (flag_eliminate_dwarf2_dups && dwarf_version < 4)
|
20536 |
|
|
{
|
20537 |
|
|
/* Record the beginning of the file for break_out_includes. */
|
20538 |
|
|
dw_die_ref bincl_die;
|
20539 |
|
|
|
20540 |
|
|
bincl_die = new_die (DW_TAG_GNU_BINCL, comp_unit_die, NULL);
|
20541 |
|
|
add_AT_string (bincl_die, DW_AT_name, remap_debug_filename (filename));
|
20542 |
|
|
}
|
20543 |
|
|
|
20544 |
|
|
if (debug_info_level >= DINFO_LEVEL_VERBOSE)
|
20545 |
|
|
{
|
20546 |
|
|
int file_num = maybe_emit_file (lookup_filename (filename));
|
20547 |
|
|
|
20548 |
|
|
switch_to_section (debug_macinfo_section);
|
20549 |
|
|
dw2_asm_output_data (1, DW_MACINFO_start_file, "Start new file");
|
20550 |
|
|
dw2_asm_output_data_uleb128 (lineno, "Included from line number %d",
|
20551 |
|
|
lineno);
|
20552 |
|
|
|
20553 |
|
|
dw2_asm_output_data_uleb128 (file_num, "file %s", filename);
|
20554 |
|
|
}
|
20555 |
|
|
}
|
20556 |
|
|
|
20557 |
|
|
/* Record the end of a source file. */
|
20558 |
|
|
|
20559 |
|
|
static void
|
20560 |
|
|
dwarf2out_end_source_file (unsigned int lineno ATTRIBUTE_UNUSED)
|
20561 |
|
|
{
|
20562 |
|
|
if (flag_eliminate_dwarf2_dups && dwarf_version < 4)
|
20563 |
|
|
/* Record the end of the file for break_out_includes. */
|
20564 |
|
|
new_die (DW_TAG_GNU_EINCL, comp_unit_die, NULL);
|
20565 |
|
|
|
20566 |
|
|
if (debug_info_level >= DINFO_LEVEL_VERBOSE)
|
20567 |
|
|
{
|
20568 |
|
|
switch_to_section (debug_macinfo_section);
|
20569 |
|
|
dw2_asm_output_data (1, DW_MACINFO_end_file, "End file");
|
20570 |
|
|
}
|
20571 |
|
|
}
|
20572 |
|
|
|
20573 |
|
|
/* Called from debug_define in toplev.c. The `buffer' parameter contains
|
20574 |
|
|
the tail part of the directive line, i.e. the part which is past the
|
20575 |
|
|
initial whitespace, #, whitespace, directive-name, whitespace part. */
|
20576 |
|
|
|
20577 |
|
|
static void
|
20578 |
|
|
dwarf2out_define (unsigned int lineno ATTRIBUTE_UNUSED,
|
20579 |
|
|
const char *buffer ATTRIBUTE_UNUSED)
|
20580 |
|
|
{
|
20581 |
|
|
if (debug_info_level >= DINFO_LEVEL_VERBOSE)
|
20582 |
|
|
{
|
20583 |
|
|
switch_to_section (debug_macinfo_section);
|
20584 |
|
|
dw2_asm_output_data (1, DW_MACINFO_define, "Define macro");
|
20585 |
|
|
dw2_asm_output_data_uleb128 (lineno, "At line number %d", lineno);
|
20586 |
|
|
dw2_asm_output_nstring (buffer, -1, "The macro");
|
20587 |
|
|
}
|
20588 |
|
|
}
|
20589 |
|
|
|
20590 |
|
|
/* Called from debug_undef in toplev.c. The `buffer' parameter contains
|
20591 |
|
|
the tail part of the directive line, i.e. the part which is past the
|
20592 |
|
|
initial whitespace, #, whitespace, directive-name, whitespace part. */
|
20593 |
|
|
|
20594 |
|
|
static void
|
20595 |
|
|
dwarf2out_undef (unsigned int lineno ATTRIBUTE_UNUSED,
|
20596 |
|
|
const char *buffer ATTRIBUTE_UNUSED)
|
20597 |
|
|
{
|
20598 |
|
|
if (debug_info_level >= DINFO_LEVEL_VERBOSE)
|
20599 |
|
|
{
|
20600 |
|
|
switch_to_section (debug_macinfo_section);
|
20601 |
|
|
dw2_asm_output_data (1, DW_MACINFO_undef, "Undefine macro");
|
20602 |
|
|
dw2_asm_output_data_uleb128 (lineno, "At line number %d", lineno);
|
20603 |
|
|
dw2_asm_output_nstring (buffer, -1, "The macro");
|
20604 |
|
|
}
|
20605 |
|
|
}
|
20606 |
|
|
|
20607 |
|
|
/* Set up for Dwarf output at the start of compilation. */
|
20608 |
|
|
|
20609 |
|
|
static void
|
20610 |
|
|
dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
|
20611 |
|
|
{
|
20612 |
|
|
/* Allocate the file_table. */
|
20613 |
|
|
file_table = htab_create_ggc (50, file_table_hash,
|
20614 |
|
|
file_table_eq, NULL);
|
20615 |
|
|
|
20616 |
|
|
/* Allocate the decl_die_table. */
|
20617 |
|
|
decl_die_table = htab_create_ggc (10, decl_die_table_hash,
|
20618 |
|
|
decl_die_table_eq, NULL);
|
20619 |
|
|
|
20620 |
|
|
/* Allocate the decl_loc_table. */
|
20621 |
|
|
decl_loc_table = htab_create_ggc (10, decl_loc_table_hash,
|
20622 |
|
|
decl_loc_table_eq, NULL);
|
20623 |
|
|
|
20624 |
|
|
/* Allocate the initial hunk of the decl_scope_table. */
|
20625 |
|
|
decl_scope_table = VEC_alloc (tree, gc, 256);
|
20626 |
|
|
|
20627 |
|
|
/* Allocate the initial hunk of the abbrev_die_table. */
|
20628 |
|
|
abbrev_die_table = GGC_CNEWVEC (dw_die_ref, ABBREV_DIE_TABLE_INCREMENT);
|
20629 |
|
|
abbrev_die_table_allocated = ABBREV_DIE_TABLE_INCREMENT;
|
20630 |
|
|
/* Zero-th entry is allocated, but unused. */
|
20631 |
|
|
abbrev_die_table_in_use = 1;
|
20632 |
|
|
|
20633 |
|
|
/* Allocate the initial hunk of the line_info_table. */
|
20634 |
|
|
line_info_table = GGC_CNEWVEC (dw_line_info_entry, LINE_INFO_TABLE_INCREMENT);
|
20635 |
|
|
line_info_table_allocated = LINE_INFO_TABLE_INCREMENT;
|
20636 |
|
|
|
20637 |
|
|
/* Zero-th entry is allocated, but unused. */
|
20638 |
|
|
line_info_table_in_use = 1;
|
20639 |
|
|
|
20640 |
|
|
/* Allocate the pubtypes and pubnames vectors. */
|
20641 |
|
|
pubname_table = VEC_alloc (pubname_entry, gc, 32);
|
20642 |
|
|
pubtype_table = VEC_alloc (pubname_entry, gc, 32);
|
20643 |
|
|
|
20644 |
|
|
/* Allocate the table that maps insn UIDs to vtable slot indexes. */
|
20645 |
|
|
vcall_insn_table = htab_create_ggc (10, vcall_insn_table_hash,
|
20646 |
|
|
vcall_insn_table_eq, NULL);
|
20647 |
|
|
|
20648 |
|
|
/* Generate the initial DIE for the .debug section. Note that the (string)
|
20649 |
|
|
value given in the DW_AT_name attribute of the DW_TAG_compile_unit DIE
|
20650 |
|
|
will (typically) be a relative pathname and that this pathname should be
|
20651 |
|
|
taken as being relative to the directory from which the compiler was
|
20652 |
|
|
invoked when the given (base) source file was compiled. We will fill
|
20653 |
|
|
in this value in dwarf2out_finish. */
|
20654 |
|
|
comp_unit_die = gen_compile_unit_die (NULL);
|
20655 |
|
|
|
20656 |
|
|
incomplete_types = VEC_alloc (tree, gc, 64);
|
20657 |
|
|
|
20658 |
|
|
used_rtx_array = VEC_alloc (rtx, gc, 32);
|
20659 |
|
|
|
20660 |
|
|
debug_info_section = get_section (DEBUG_INFO_SECTION,
|
20661 |
|
|
SECTION_DEBUG, NULL);
|
20662 |
|
|
debug_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
|
20663 |
|
|
SECTION_DEBUG, NULL);
|
20664 |
|
|
debug_aranges_section = get_section (DEBUG_ARANGES_SECTION,
|
20665 |
|
|
SECTION_DEBUG, NULL);
|
20666 |
|
|
debug_macinfo_section = get_section (DEBUG_MACINFO_SECTION,
|
20667 |
|
|
SECTION_DEBUG, NULL);
|
20668 |
|
|
debug_line_section = get_section (DEBUG_LINE_SECTION,
|
20669 |
|
|
SECTION_DEBUG, NULL);
|
20670 |
|
|
debug_loc_section = get_section (DEBUG_LOC_SECTION,
|
20671 |
|
|
SECTION_DEBUG, NULL);
|
20672 |
|
|
debug_pubnames_section = get_section (DEBUG_PUBNAMES_SECTION,
|
20673 |
|
|
SECTION_DEBUG, NULL);
|
20674 |
|
|
debug_pubtypes_section = get_section (DEBUG_PUBTYPES_SECTION,
|
20675 |
|
|
SECTION_DEBUG, NULL);
|
20676 |
|
|
debug_dcall_section = get_section (DEBUG_DCALL_SECTION,
|
20677 |
|
|
SECTION_DEBUG, NULL);
|
20678 |
|
|
debug_vcall_section = get_section (DEBUG_VCALL_SECTION,
|
20679 |
|
|
SECTION_DEBUG, NULL);
|
20680 |
|
|
debug_str_section = get_section (DEBUG_STR_SECTION,
|
20681 |
|
|
DEBUG_STR_SECTION_FLAGS, NULL);
|
20682 |
|
|
debug_ranges_section = get_section (DEBUG_RANGES_SECTION,
|
20683 |
|
|
SECTION_DEBUG, NULL);
|
20684 |
|
|
debug_frame_section = get_section (DEBUG_FRAME_SECTION,
|
20685 |
|
|
SECTION_DEBUG, NULL);
|
20686 |
|
|
|
20687 |
|
|
ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
|
20688 |
|
|
ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label,
|
20689 |
|
|
DEBUG_ABBREV_SECTION_LABEL, 0);
|
20690 |
|
|
ASM_GENERATE_INTERNAL_LABEL (text_section_label, TEXT_SECTION_LABEL, 0);
|
20691 |
|
|
ASM_GENERATE_INTERNAL_LABEL (cold_text_section_label,
|
20692 |
|
|
COLD_TEXT_SECTION_LABEL, 0);
|
20693 |
|
|
ASM_GENERATE_INTERNAL_LABEL (cold_end_label, COLD_END_LABEL, 0);
|
20694 |
|
|
|
20695 |
|
|
ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label,
|
20696 |
|
|
DEBUG_INFO_SECTION_LABEL, 0);
|
20697 |
|
|
ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label,
|
20698 |
|
|
DEBUG_LINE_SECTION_LABEL, 0);
|
20699 |
|
|
ASM_GENERATE_INTERNAL_LABEL (ranges_section_label,
|
20700 |
|
|
DEBUG_RANGES_SECTION_LABEL, 0);
|
20701 |
|
|
switch_to_section (debug_abbrev_section);
|
20702 |
|
|
ASM_OUTPUT_LABEL (asm_out_file, abbrev_section_label);
|
20703 |
|
|
switch_to_section (debug_info_section);
|
20704 |
|
|
ASM_OUTPUT_LABEL (asm_out_file, debug_info_section_label);
|
20705 |
|
|
switch_to_section (debug_line_section);
|
20706 |
|
|
ASM_OUTPUT_LABEL (asm_out_file, debug_line_section_label);
|
20707 |
|
|
|
20708 |
|
|
if (debug_info_level >= DINFO_LEVEL_VERBOSE)
|
20709 |
|
|
{
|
20710 |
|
|
switch_to_section (debug_macinfo_section);
|
20711 |
|
|
ASM_GENERATE_INTERNAL_LABEL (macinfo_section_label,
|
20712 |
|
|
DEBUG_MACINFO_SECTION_LABEL, 0);
|
20713 |
|
|
ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label);
|
20714 |
|
|
}
|
20715 |
|
|
|
20716 |
|
|
switch_to_section (text_section);
|
20717 |
|
|
ASM_OUTPUT_LABEL (asm_out_file, text_section_label);
|
20718 |
|
|
if (flag_reorder_blocks_and_partition)
|
20719 |
|
|
{
|
20720 |
|
|
cold_text_section = unlikely_text_section ();
|
20721 |
|
|
switch_to_section (cold_text_section);
|
20722 |
|
|
ASM_OUTPUT_LABEL (asm_out_file, cold_text_section_label);
|
20723 |
|
|
}
|
20724 |
|
|
|
20725 |
|
|
}
|
20726 |
|
|
|
20727 |
|
|
/* Called before cgraph_optimize starts outputtting functions, variables
|
20728 |
|
|
and toplevel asms into assembly. */
|
20729 |
|
|
|
20730 |
|
|
static void
|
20731 |
|
|
dwarf2out_assembly_start (void)
|
20732 |
|
|
{
|
20733 |
|
|
if (HAVE_GAS_CFI_SECTIONS_DIRECTIVE && dwarf2out_do_cfi_asm ())
|
20734 |
|
|
{
|
20735 |
|
|
#ifndef TARGET_UNWIND_INFO
|
20736 |
|
|
if (USING_SJLJ_EXCEPTIONS || (!flag_unwind_tables && !flag_exceptions))
|
20737 |
|
|
#endif
|
20738 |
|
|
fprintf (asm_out_file, "\t.cfi_sections\t.debug_frame\n");
|
20739 |
|
|
}
|
20740 |
|
|
}
|
20741 |
|
|
|
20742 |
|
|
/* A helper function for dwarf2out_finish called through
|
20743 |
|
|
htab_traverse. Emit one queued .debug_str string. */
|
20744 |
|
|
|
20745 |
|
|
static int
|
20746 |
|
|
output_indirect_string (void **h, void *v ATTRIBUTE_UNUSED)
|
20747 |
|
|
{
|
20748 |
|
|
struct indirect_string_node *node = (struct indirect_string_node *) *h;
|
20749 |
|
|
|
20750 |
|
|
if (node->label && node->refcount)
|
20751 |
|
|
{
|
20752 |
|
|
switch_to_section (debug_str_section);
|
20753 |
|
|
ASM_OUTPUT_LABEL (asm_out_file, node->label);
|
20754 |
|
|
assemble_string (node->str, strlen (node->str) + 1);
|
20755 |
|
|
}
|
20756 |
|
|
|
20757 |
|
|
return 1;
|
20758 |
|
|
}
|
20759 |
|
|
|
20760 |
|
|
#if ENABLE_ASSERT_CHECKING
|
20761 |
|
|
/* Verify that all marks are clear. */
|
20762 |
|
|
|
20763 |
|
|
static void
|
20764 |
|
|
verify_marks_clear (dw_die_ref die)
|
20765 |
|
|
{
|
20766 |
|
|
dw_die_ref c;
|
20767 |
|
|
|
20768 |
|
|
gcc_assert (! die->die_mark);
|
20769 |
|
|
FOR_EACH_CHILD (die, c, verify_marks_clear (c));
|
20770 |
|
|
}
|
20771 |
|
|
#endif /* ENABLE_ASSERT_CHECKING */
|
20772 |
|
|
|
20773 |
|
|
/* Clear the marks for a die and its children.
|
20774 |
|
|
Be cool if the mark isn't set. */
|
20775 |
|
|
|
20776 |
|
|
static void
|
20777 |
|
|
prune_unmark_dies (dw_die_ref die)
|
20778 |
|
|
{
|
20779 |
|
|
dw_die_ref c;
|
20780 |
|
|
|
20781 |
|
|
if (die->die_mark)
|
20782 |
|
|
die->die_mark = 0;
|
20783 |
|
|
FOR_EACH_CHILD (die, c, prune_unmark_dies (c));
|
20784 |
|
|
}
|
20785 |
|
|
|
20786 |
|
|
/* Given DIE that we're marking as used, find any other dies
|
20787 |
|
|
it references as attributes and mark them as used. */
|
20788 |
|
|
|
20789 |
|
|
static void
|
20790 |
|
|
prune_unused_types_walk_attribs (dw_die_ref die)
|
20791 |
|
|
{
|
20792 |
|
|
dw_attr_ref a;
|
20793 |
|
|
unsigned ix;
|
20794 |
|
|
|
20795 |
|
|
for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
|
20796 |
|
|
{
|
20797 |
|
|
if (a->dw_attr_val.val_class == dw_val_class_die_ref)
|
20798 |
|
|
{
|
20799 |
|
|
/* A reference to another DIE.
|
20800 |
|
|
Make sure that it will get emitted.
|
20801 |
|
|
If it was broken out into a comdat group, don't follow it. */
|
20802 |
|
|
if (dwarf_version < 4
|
20803 |
|
|
|| a->dw_attr == DW_AT_specification
|
20804 |
|
|
|| a->dw_attr_val.v.val_die_ref.die->die_id.die_type_node == NULL)
|
20805 |
|
|
prune_unused_types_mark (a->dw_attr_val.v.val_die_ref.die, 1);
|
20806 |
|
|
}
|
20807 |
|
|
/* Set the string's refcount to 0 so that prune_unused_types_mark
|
20808 |
|
|
accounts properly for it. */
|
20809 |
|
|
if (AT_class (a) == dw_val_class_str)
|
20810 |
|
|
a->dw_attr_val.v.val_str->refcount = 0;
|
20811 |
|
|
}
|
20812 |
|
|
}
|
20813 |
|
|
|
20814 |
|
|
|
20815 |
|
|
/* Mark DIE as being used. If DOKIDS is true, then walk down
|
20816 |
|
|
to DIE's children. */
|
20817 |
|
|
|
20818 |
|
|
static void
|
20819 |
|
|
prune_unused_types_mark (dw_die_ref die, int dokids)
|
20820 |
|
|
{
|
20821 |
|
|
dw_die_ref c;
|
20822 |
|
|
|
20823 |
|
|
if (die->die_mark == 0)
|
20824 |
|
|
{
|
20825 |
|
|
/* We haven't done this node yet. Mark it as used. */
|
20826 |
|
|
die->die_mark = 1;
|
20827 |
|
|
|
20828 |
|
|
/* We also have to mark its parents as used.
|
20829 |
|
|
(But we don't want to mark our parents' kids due to this.) */
|
20830 |
|
|
if (die->die_parent)
|
20831 |
|
|
prune_unused_types_mark (die->die_parent, 0);
|
20832 |
|
|
|
20833 |
|
|
/* Mark any referenced nodes. */
|
20834 |
|
|
prune_unused_types_walk_attribs (die);
|
20835 |
|
|
|
20836 |
|
|
/* If this node is a specification,
|
20837 |
|
|
also mark the definition, if it exists. */
|
20838 |
|
|
if (get_AT_flag (die, DW_AT_declaration) && die->die_definition)
|
20839 |
|
|
prune_unused_types_mark (die->die_definition, 1);
|
20840 |
|
|
}
|
20841 |
|
|
|
20842 |
|
|
if (dokids && die->die_mark != 2)
|
20843 |
|
|
{
|
20844 |
|
|
/* We need to walk the children, but haven't done so yet.
|
20845 |
|
|
Remember that we've walked the kids. */
|
20846 |
|
|
die->die_mark = 2;
|
20847 |
|
|
|
20848 |
|
|
/* If this is an array type, we need to make sure our
|
20849 |
|
|
kids get marked, even if they're types. If we're
|
20850 |
|
|
breaking out types into comdat sections, do this
|
20851 |
|
|
for all type definitions. */
|
20852 |
|
|
if (die->die_tag == DW_TAG_array_type
|
20853 |
|
|
|| (dwarf_version >= 4
|
20854 |
|
|
&& is_type_die (die) && ! is_declaration_die (die)))
|
20855 |
|
|
FOR_EACH_CHILD (die, c, prune_unused_types_mark (c, 1));
|
20856 |
|
|
else
|
20857 |
|
|
FOR_EACH_CHILD (die, c, prune_unused_types_walk (c));
|
20858 |
|
|
}
|
20859 |
|
|
}
|
20860 |
|
|
|
20861 |
|
|
/* For local classes, look if any static member functions were emitted
|
20862 |
|
|
and if so, mark them. */
|
20863 |
|
|
|
20864 |
|
|
static void
|
20865 |
|
|
prune_unused_types_walk_local_classes (dw_die_ref die)
|
20866 |
|
|
{
|
20867 |
|
|
dw_die_ref c;
|
20868 |
|
|
|
20869 |
|
|
if (die->die_mark == 2)
|
20870 |
|
|
return;
|
20871 |
|
|
|
20872 |
|
|
switch (die->die_tag)
|
20873 |
|
|
{
|
20874 |
|
|
case DW_TAG_structure_type:
|
20875 |
|
|
case DW_TAG_union_type:
|
20876 |
|
|
case DW_TAG_class_type:
|
20877 |
|
|
break;
|
20878 |
|
|
|
20879 |
|
|
case DW_TAG_subprogram:
|
20880 |
|
|
if (!get_AT_flag (die, DW_AT_declaration)
|
20881 |
|
|
|| die->die_definition != NULL)
|
20882 |
|
|
prune_unused_types_mark (die, 1);
|
20883 |
|
|
return;
|
20884 |
|
|
|
20885 |
|
|
default:
|
20886 |
|
|
return;
|
20887 |
|
|
}
|
20888 |
|
|
|
20889 |
|
|
/* Mark children. */
|
20890 |
|
|
FOR_EACH_CHILD (die, c, prune_unused_types_walk_local_classes (c));
|
20891 |
|
|
}
|
20892 |
|
|
|
20893 |
|
|
/* Walk the tree DIE and mark types that we actually use. */
|
20894 |
|
|
|
20895 |
|
|
static void
|
20896 |
|
|
prune_unused_types_walk (dw_die_ref die)
|
20897 |
|
|
{
|
20898 |
|
|
dw_die_ref c;
|
20899 |
|
|
|
20900 |
|
|
/* Don't do anything if this node is already marked and
|
20901 |
|
|
children have been marked as well. */
|
20902 |
|
|
if (die->die_mark == 2)
|
20903 |
|
|
return;
|
20904 |
|
|
|
20905 |
|
|
switch (die->die_tag)
|
20906 |
|
|
{
|
20907 |
|
|
case DW_TAG_structure_type:
|
20908 |
|
|
case DW_TAG_union_type:
|
20909 |
|
|
case DW_TAG_class_type:
|
20910 |
|
|
if (die->die_perennial_p)
|
20911 |
|
|
break;
|
20912 |
|
|
|
20913 |
|
|
for (c = die->die_parent; c; c = c->die_parent)
|
20914 |
|
|
if (c->die_tag == DW_TAG_subprogram)
|
20915 |
|
|
break;
|
20916 |
|
|
|
20917 |
|
|
/* Finding used static member functions inside of classes
|
20918 |
|
|
is needed just for local classes, because for other classes
|
20919 |
|
|
static member function DIEs with DW_AT_specification
|
20920 |
|
|
are emitted outside of the DW_TAG_*_type. If we ever change
|
20921 |
|
|
it, we'd need to call this even for non-local classes. */
|
20922 |
|
|
if (c)
|
20923 |
|
|
prune_unused_types_walk_local_classes (die);
|
20924 |
|
|
|
20925 |
|
|
/* It's a type node --- don't mark it. */
|
20926 |
|
|
return;
|
20927 |
|
|
|
20928 |
|
|
case DW_TAG_const_type:
|
20929 |
|
|
case DW_TAG_packed_type:
|
20930 |
|
|
case DW_TAG_pointer_type:
|
20931 |
|
|
case DW_TAG_reference_type:
|
20932 |
|
|
case DW_TAG_volatile_type:
|
20933 |
|
|
case DW_TAG_typedef:
|
20934 |
|
|
case DW_TAG_array_type:
|
20935 |
|
|
case DW_TAG_interface_type:
|
20936 |
|
|
case DW_TAG_friend:
|
20937 |
|
|
case DW_TAG_variant_part:
|
20938 |
|
|
case DW_TAG_enumeration_type:
|
20939 |
|
|
case DW_TAG_subroutine_type:
|
20940 |
|
|
case DW_TAG_string_type:
|
20941 |
|
|
case DW_TAG_set_type:
|
20942 |
|
|
case DW_TAG_subrange_type:
|
20943 |
|
|
case DW_TAG_ptr_to_member_type:
|
20944 |
|
|
case DW_TAG_file_type:
|
20945 |
|
|
if (die->die_perennial_p)
|
20946 |
|
|
break;
|
20947 |
|
|
|
20948 |
|
|
/* It's a type node --- don't mark it. */
|
20949 |
|
|
return;
|
20950 |
|
|
|
20951 |
|
|
default:
|
20952 |
|
|
/* Mark everything else. */
|
20953 |
|
|
break;
|
20954 |
|
|
}
|
20955 |
|
|
|
20956 |
|
|
if (die->die_mark == 0)
|
20957 |
|
|
{
|
20958 |
|
|
die->die_mark = 1;
|
20959 |
|
|
|
20960 |
|
|
/* Now, mark any dies referenced from here. */
|
20961 |
|
|
prune_unused_types_walk_attribs (die);
|
20962 |
|
|
}
|
20963 |
|
|
|
20964 |
|
|
die->die_mark = 2;
|
20965 |
|
|
|
20966 |
|
|
/* Mark children. */
|
20967 |
|
|
FOR_EACH_CHILD (die, c, prune_unused_types_walk (c));
|
20968 |
|
|
}
|
20969 |
|
|
|
20970 |
|
|
/* Increment the string counts on strings referred to from DIE's
|
20971 |
|
|
attributes. */
|
20972 |
|
|
|
20973 |
|
|
static void
|
20974 |
|
|
prune_unused_types_update_strings (dw_die_ref die)
|
20975 |
|
|
{
|
20976 |
|
|
dw_attr_ref a;
|
20977 |
|
|
unsigned ix;
|
20978 |
|
|
|
20979 |
|
|
for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
|
20980 |
|
|
if (AT_class (a) == dw_val_class_str)
|
20981 |
|
|
{
|
20982 |
|
|
struct indirect_string_node *s = a->dw_attr_val.v.val_str;
|
20983 |
|
|
s->refcount++;
|
20984 |
|
|
/* Avoid unnecessarily putting strings that are used less than
|
20985 |
|
|
twice in the hash table. */
|
20986 |
|
|
if (s->refcount
|
20987 |
|
|
== ((DEBUG_STR_SECTION_FLAGS & SECTION_MERGE) ? 1 : 2))
|
20988 |
|
|
{
|
20989 |
|
|
void ** slot;
|
20990 |
|
|
slot = htab_find_slot_with_hash (debug_str_hash, s->str,
|
20991 |
|
|
htab_hash_string (s->str),
|
20992 |
|
|
INSERT);
|
20993 |
|
|
gcc_assert (*slot == NULL);
|
20994 |
|
|
*slot = s;
|
20995 |
|
|
}
|
20996 |
|
|
}
|
20997 |
|
|
}
|
20998 |
|
|
|
20999 |
|
|
/* Remove from the tree DIE any dies that aren't marked. */
|
21000 |
|
|
|
21001 |
|
|
static void
|
21002 |
|
|
prune_unused_types_prune (dw_die_ref die)
|
21003 |
|
|
{
|
21004 |
|
|
dw_die_ref c;
|
21005 |
|
|
|
21006 |
|
|
gcc_assert (die->die_mark);
|
21007 |
|
|
prune_unused_types_update_strings (die);
|
21008 |
|
|
|
21009 |
|
|
if (! die->die_child)
|
21010 |
|
|
return;
|
21011 |
|
|
|
21012 |
|
|
c = die->die_child;
|
21013 |
|
|
do {
|
21014 |
|
|
dw_die_ref prev = c;
|
21015 |
|
|
for (c = c->die_sib; ! c->die_mark; c = c->die_sib)
|
21016 |
|
|
if (c == die->die_child)
|
21017 |
|
|
{
|
21018 |
|
|
/* No marked children between 'prev' and the end of the list. */
|
21019 |
|
|
if (prev == c)
|
21020 |
|
|
/* No marked children at all. */
|
21021 |
|
|
die->die_child = NULL;
|
21022 |
|
|
else
|
21023 |
|
|
{
|
21024 |
|
|
prev->die_sib = c->die_sib;
|
21025 |
|
|
die->die_child = prev;
|
21026 |
|
|
}
|
21027 |
|
|
return;
|
21028 |
|
|
}
|
21029 |
|
|
|
21030 |
|
|
if (c != prev->die_sib)
|
21031 |
|
|
prev->die_sib = c;
|
21032 |
|
|
prune_unused_types_prune (c);
|
21033 |
|
|
} while (c != die->die_child);
|
21034 |
|
|
}
|
21035 |
|
|
|
21036 |
|
|
/* A helper function for dwarf2out_finish called through
|
21037 |
|
|
htab_traverse. Clear .debug_str strings that we haven't already
|
21038 |
|
|
decided to emit. */
|
21039 |
|
|
|
21040 |
|
|
static int
|
21041 |
|
|
prune_indirect_string (void **h, void *v ATTRIBUTE_UNUSED)
|
21042 |
|
|
{
|
21043 |
|
|
struct indirect_string_node *node = (struct indirect_string_node *) *h;
|
21044 |
|
|
|
21045 |
|
|
if (!node->label || !node->refcount)
|
21046 |
|
|
htab_clear_slot (debug_str_hash, h);
|
21047 |
|
|
|
21048 |
|
|
return 1;
|
21049 |
|
|
}
|
21050 |
|
|
|
21051 |
|
|
/* Remove dies representing declarations that we never use. */
|
21052 |
|
|
|
21053 |
|
|
static void
|
21054 |
|
|
prune_unused_types (void)
|
21055 |
|
|
{
|
21056 |
|
|
unsigned int i;
|
21057 |
|
|
limbo_die_node *node;
|
21058 |
|
|
comdat_type_node *ctnode;
|
21059 |
|
|
pubname_ref pub;
|
21060 |
|
|
dcall_entry *dcall;
|
21061 |
|
|
|
21062 |
|
|
#if ENABLE_ASSERT_CHECKING
|
21063 |
|
|
/* All the marks should already be clear. */
|
21064 |
|
|
verify_marks_clear (comp_unit_die);
|
21065 |
|
|
for (node = limbo_die_list; node; node = node->next)
|
21066 |
|
|
verify_marks_clear (node->die);
|
21067 |
|
|
for (ctnode = comdat_type_list; ctnode; ctnode = ctnode->next)
|
21068 |
|
|
verify_marks_clear (ctnode->root_die);
|
21069 |
|
|
#endif /* ENABLE_ASSERT_CHECKING */
|
21070 |
|
|
|
21071 |
|
|
/* Mark types that are used in global variables. */
|
21072 |
|
|
premark_types_used_by_global_vars ();
|
21073 |
|
|
|
21074 |
|
|
/* Set the mark on nodes that are actually used. */
|
21075 |
|
|
prune_unused_types_walk (comp_unit_die);
|
21076 |
|
|
for (node = limbo_die_list; node; node = node->next)
|
21077 |
|
|
prune_unused_types_walk (node->die);
|
21078 |
|
|
for (ctnode = comdat_type_list; ctnode; ctnode = ctnode->next)
|
21079 |
|
|
{
|
21080 |
|
|
prune_unused_types_walk (ctnode->root_die);
|
21081 |
|
|
prune_unused_types_mark (ctnode->type_die, 1);
|
21082 |
|
|
}
|
21083 |
|
|
|
21084 |
|
|
/* Also set the mark on nodes referenced from the
|
21085 |
|
|
pubname_table or arange_table. */
|
21086 |
|
|
for (i = 0; VEC_iterate (pubname_entry, pubname_table, i, pub); i++)
|
21087 |
|
|
prune_unused_types_mark (pub->die, 1);
|
21088 |
|
|
for (i = 0; i < arange_table_in_use; i++)
|
21089 |
|
|
prune_unused_types_mark (arange_table[i], 1);
|
21090 |
|
|
|
21091 |
|
|
/* Mark nodes referenced from the direct call table. */
|
21092 |
|
|
for (i = 0; VEC_iterate (dcall_entry, dcall_table, i, dcall); i++)
|
21093 |
|
|
prune_unused_types_mark (dcall->targ_die, 1);
|
21094 |
|
|
|
21095 |
|
|
/* Get rid of nodes that aren't marked; and update the string counts. */
|
21096 |
|
|
if (debug_str_hash && debug_str_hash_forced)
|
21097 |
|
|
htab_traverse (debug_str_hash, prune_indirect_string, NULL);
|
21098 |
|
|
else if (debug_str_hash)
|
21099 |
|
|
htab_empty (debug_str_hash);
|
21100 |
|
|
prune_unused_types_prune (comp_unit_die);
|
21101 |
|
|
for (node = limbo_die_list; node; node = node->next)
|
21102 |
|
|
prune_unused_types_prune (node->die);
|
21103 |
|
|
for (ctnode = comdat_type_list; ctnode; ctnode = ctnode->next)
|
21104 |
|
|
prune_unused_types_prune (ctnode->root_die);
|
21105 |
|
|
|
21106 |
|
|
/* Leave the marks clear. */
|
21107 |
|
|
prune_unmark_dies (comp_unit_die);
|
21108 |
|
|
for (node = limbo_die_list; node; node = node->next)
|
21109 |
|
|
prune_unmark_dies (node->die);
|
21110 |
|
|
for (ctnode = comdat_type_list; ctnode; ctnode = ctnode->next)
|
21111 |
|
|
prune_unmark_dies (ctnode->root_die);
|
21112 |
|
|
}
|
21113 |
|
|
|
21114 |
|
|
/* Set the parameter to true if there are any relative pathnames in
|
21115 |
|
|
the file table. */
|
21116 |
|
|
static int
|
21117 |
|
|
file_table_relative_p (void ** slot, void *param)
|
21118 |
|
|
{
|
21119 |
|
|
bool *p = (bool *) param;
|
21120 |
|
|
struct dwarf_file_data *d = (struct dwarf_file_data *) *slot;
|
21121 |
|
|
if (!IS_ABSOLUTE_PATH (d->filename))
|
21122 |
|
|
{
|
21123 |
|
|
*p = true;
|
21124 |
|
|
return 0;
|
21125 |
|
|
}
|
21126 |
|
|
return 1;
|
21127 |
|
|
}
|
21128 |
|
|
|
21129 |
|
|
/* Routines to manipulate hash table of comdat type units. */
|
21130 |
|
|
|
21131 |
|
|
static hashval_t
|
21132 |
|
|
htab_ct_hash (const void *of)
|
21133 |
|
|
{
|
21134 |
|
|
hashval_t h;
|
21135 |
|
|
const comdat_type_node *const type_node = (const comdat_type_node *) of;
|
21136 |
|
|
|
21137 |
|
|
memcpy (&h, type_node->signature, sizeof (h));
|
21138 |
|
|
return h;
|
21139 |
|
|
}
|
21140 |
|
|
|
21141 |
|
|
static int
|
21142 |
|
|
htab_ct_eq (const void *of1, const void *of2)
|
21143 |
|
|
{
|
21144 |
|
|
const comdat_type_node *const type_node_1 = (const comdat_type_node *) of1;
|
21145 |
|
|
const comdat_type_node *const type_node_2 = (const comdat_type_node *) of2;
|
21146 |
|
|
|
21147 |
|
|
return (! memcmp (type_node_1->signature, type_node_2->signature,
|
21148 |
|
|
DWARF_TYPE_SIGNATURE_SIZE));
|
21149 |
|
|
}
|
21150 |
|
|
|
21151 |
|
|
/* Move a DW_AT_MIPS_linkage_name attribute just added to dw_die_ref
|
21152 |
|
|
to the location it would have been added, should we know its
|
21153 |
|
|
DECL_ASSEMBLER_NAME when we added other attributes. This will
|
21154 |
|
|
probably improve compactness of debug info, removing equivalent
|
21155 |
|
|
abbrevs, and hide any differences caused by deferring the
|
21156 |
|
|
computation of the assembler name, triggered by e.g. PCH. */
|
21157 |
|
|
|
21158 |
|
|
static inline void
|
21159 |
|
|
move_linkage_attr (dw_die_ref die)
|
21160 |
|
|
{
|
21161 |
|
|
unsigned ix = VEC_length (dw_attr_node, die->die_attr);
|
21162 |
|
|
dw_attr_node linkage = *VEC_index (dw_attr_node, die->die_attr, ix - 1);
|
21163 |
|
|
|
21164 |
|
|
gcc_assert (linkage.dw_attr == DW_AT_MIPS_linkage_name);
|
21165 |
|
|
|
21166 |
|
|
while (--ix > 0)
|
21167 |
|
|
{
|
21168 |
|
|
dw_attr_node *prev = VEC_index (dw_attr_node, die->die_attr, ix - 1);
|
21169 |
|
|
|
21170 |
|
|
if (prev->dw_attr == DW_AT_decl_line || prev->dw_attr == DW_AT_name)
|
21171 |
|
|
break;
|
21172 |
|
|
}
|
21173 |
|
|
|
21174 |
|
|
if (ix != VEC_length (dw_attr_node, die->die_attr) - 1)
|
21175 |
|
|
{
|
21176 |
|
|
VEC_pop (dw_attr_node, die->die_attr);
|
21177 |
|
|
VEC_quick_insert (dw_attr_node, die->die_attr, ix, &linkage);
|
21178 |
|
|
}
|
21179 |
|
|
}
|
21180 |
|
|
|
21181 |
|
|
/* Helper function for resolve_addr, attempt to resolve
|
21182 |
|
|
one CONST_STRING, return non-zero if not successful. Similarly verify that
|
21183 |
|
|
SYMBOL_REFs refer to variables emitted in the current CU. */
|
21184 |
|
|
|
21185 |
|
|
static int
|
21186 |
|
|
resolve_one_addr (rtx *addr, void *data ATTRIBUTE_UNUSED)
|
21187 |
|
|
{
|
21188 |
|
|
rtx rtl = *addr;
|
21189 |
|
|
|
21190 |
|
|
if (GET_CODE (rtl) == CONST_STRING)
|
21191 |
|
|
{
|
21192 |
|
|
size_t len = strlen (XSTR (rtl, 0)) + 1;
|
21193 |
|
|
tree t = build_string (len, XSTR (rtl, 0));
|
21194 |
|
|
tree tlen = build_int_cst (NULL_TREE, len - 1);
|
21195 |
|
|
TREE_TYPE (t)
|
21196 |
|
|
= build_array_type (char_type_node, build_index_type (tlen));
|
21197 |
|
|
rtl = lookup_constant_def (t);
|
21198 |
|
|
if (!rtl || !MEM_P (rtl))
|
21199 |
|
|
return 1;
|
21200 |
|
|
rtl = XEXP (rtl, 0);
|
21201 |
|
|
VEC_safe_push (rtx, gc, used_rtx_array, rtl);
|
21202 |
|
|
*addr = rtl;
|
21203 |
|
|
return 0;
|
21204 |
|
|
}
|
21205 |
|
|
|
21206 |
|
|
if (GET_CODE (rtl) == SYMBOL_REF
|
21207 |
|
|
&& SYMBOL_REF_DECL (rtl)
|
21208 |
|
|
&& TREE_CODE (SYMBOL_REF_DECL (rtl)) == VAR_DECL
|
21209 |
|
|
&& !TREE_ASM_WRITTEN (SYMBOL_REF_DECL (rtl)))
|
21210 |
|
|
return 1;
|
21211 |
|
|
|
21212 |
|
|
if (GET_CODE (rtl) == CONST
|
21213 |
|
|
&& for_each_rtx (&XEXP (rtl, 0), resolve_one_addr, NULL))
|
21214 |
|
|
return 1;
|
21215 |
|
|
|
21216 |
|
|
return 0;
|
21217 |
|
|
}
|
21218 |
|
|
|
21219 |
|
|
/* Helper function for resolve_addr, handle one location
|
21220 |
|
|
expression, return false if at least one CONST_STRING or SYMBOL_REF in
|
21221 |
|
|
the location list couldn't be resolved. */
|
21222 |
|
|
|
21223 |
|
|
static bool
|
21224 |
|
|
resolve_addr_in_expr (dw_loc_descr_ref loc)
|
21225 |
|
|
{
|
21226 |
|
|
for (; loc; loc = loc->dw_loc_next)
|
21227 |
|
|
if ((loc->dw_loc_opc == DW_OP_addr
|
21228 |
|
|
&& resolve_one_addr (&loc->dw_loc_oprnd1.v.val_addr, NULL))
|
21229 |
|
|
|| (loc->dw_loc_opc == DW_OP_implicit_value
|
21230 |
|
|
&& loc->dw_loc_oprnd2.val_class == dw_val_class_addr
|
21231 |
|
|
&& resolve_one_addr (&loc->dw_loc_oprnd2.v.val_addr, NULL)))
|
21232 |
|
|
return false;
|
21233 |
|
|
return true;
|
21234 |
|
|
}
|
21235 |
|
|
|
21236 |
|
|
/* Resolve DW_OP_addr and DW_AT_const_value CONST_STRING arguments to
|
21237 |
|
|
an address in .rodata section if the string literal is emitted there,
|
21238 |
|
|
or remove the containing location list or replace DW_AT_const_value
|
21239 |
|
|
with DW_AT_location and empty location expression, if it isn't found
|
21240 |
|
|
in .rodata. Similarly for SYMBOL_REFs, keep only those that refer
|
21241 |
|
|
to something that has been emitted in the current CU. */
|
21242 |
|
|
|
21243 |
|
|
static void
|
21244 |
|
|
resolve_addr (dw_die_ref die)
|
21245 |
|
|
{
|
21246 |
|
|
dw_die_ref c;
|
21247 |
|
|
dw_attr_ref a;
|
21248 |
|
|
dw_loc_list_ref *curr;
|
21249 |
|
|
unsigned ix;
|
21250 |
|
|
|
21251 |
|
|
for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++)
|
21252 |
|
|
switch (AT_class (a))
|
21253 |
|
|
{
|
21254 |
|
|
case dw_val_class_loc_list:
|
21255 |
|
|
curr = AT_loc_list_ptr (a);
|
21256 |
|
|
while (*curr)
|
21257 |
|
|
{
|
21258 |
|
|
if (!resolve_addr_in_expr ((*curr)->expr))
|
21259 |
|
|
{
|
21260 |
|
|
dw_loc_list_ref next = (*curr)->dw_loc_next;
|
21261 |
|
|
if (next && (*curr)->ll_symbol)
|
21262 |
|
|
{
|
21263 |
|
|
gcc_assert (!next->ll_symbol);
|
21264 |
|
|
next->ll_symbol = (*curr)->ll_symbol;
|
21265 |
|
|
}
|
21266 |
|
|
*curr = next;
|
21267 |
|
|
}
|
21268 |
|
|
else
|
21269 |
|
|
curr = &(*curr)->dw_loc_next;
|
21270 |
|
|
}
|
21271 |
|
|
if (!AT_loc_list (a))
|
21272 |
|
|
{
|
21273 |
|
|
remove_AT (die, a->dw_attr);
|
21274 |
|
|
ix--;
|
21275 |
|
|
}
|
21276 |
|
|
break;
|
21277 |
|
|
case dw_val_class_loc:
|
21278 |
|
|
if (!resolve_addr_in_expr (AT_loc (a)))
|
21279 |
|
|
{
|
21280 |
|
|
remove_AT (die, a->dw_attr);
|
21281 |
|
|
ix--;
|
21282 |
|
|
}
|
21283 |
|
|
break;
|
21284 |
|
|
case dw_val_class_addr:
|
21285 |
|
|
if (a->dw_attr == DW_AT_const_value
|
21286 |
|
|
&& resolve_one_addr (&a->dw_attr_val.v.val_addr, NULL))
|
21287 |
|
|
{
|
21288 |
|
|
remove_AT (die, a->dw_attr);
|
21289 |
|
|
ix--;
|
21290 |
|
|
}
|
21291 |
|
|
break;
|
21292 |
|
|
default:
|
21293 |
|
|
break;
|
21294 |
|
|
}
|
21295 |
|
|
|
21296 |
|
|
FOR_EACH_CHILD (die, c, resolve_addr (c));
|
21297 |
|
|
}
|
21298 |
|
|
|
21299 |
|
|
/* Output stuff that dwarf requires at the end of every file,
|
21300 |
|
|
and generate the DWARF-2 debugging info. */
|
21301 |
|
|
|
21302 |
|
|
static void
|
21303 |
|
|
dwarf2out_finish (const char *filename)
|
21304 |
|
|
{
|
21305 |
|
|
limbo_die_node *node, *next_node;
|
21306 |
|
|
comdat_type_node *ctnode;
|
21307 |
|
|
htab_t comdat_type_table;
|
21308 |
|
|
dw_die_ref die = 0;
|
21309 |
|
|
unsigned int i;
|
21310 |
|
|
|
21311 |
|
|
gen_remaining_tmpl_value_param_die_attribute ();
|
21312 |
|
|
|
21313 |
|
|
/* Add the name for the main input file now. We delayed this from
|
21314 |
|
|
dwarf2out_init to avoid complications with PCH. */
|
21315 |
|
|
add_name_attribute (comp_unit_die, remap_debug_filename (filename));
|
21316 |
|
|
if (!IS_ABSOLUTE_PATH (filename))
|
21317 |
|
|
add_comp_dir_attribute (comp_unit_die);
|
21318 |
|
|
else if (get_AT (comp_unit_die, DW_AT_comp_dir) == NULL)
|
21319 |
|
|
{
|
21320 |
|
|
bool p = false;
|
21321 |
|
|
htab_traverse (file_table, file_table_relative_p, &p);
|
21322 |
|
|
if (p)
|
21323 |
|
|
add_comp_dir_attribute (comp_unit_die);
|
21324 |
|
|
}
|
21325 |
|
|
|
21326 |
|
|
for (i = 0; i < VEC_length (deferred_locations, deferred_locations_list); i++)
|
21327 |
|
|
{
|
21328 |
|
|
add_location_or_const_value_attribute (
|
21329 |
|
|
VEC_index (deferred_locations, deferred_locations_list, i)->die,
|
21330 |
|
|
VEC_index (deferred_locations, deferred_locations_list, i)->variable,
|
21331 |
|
|
DW_AT_location);
|
21332 |
|
|
}
|
21333 |
|
|
|
21334 |
|
|
/* Traverse the limbo die list, and add parent/child links. The only
|
21335 |
|
|
dies without parents that should be here are concrete instances of
|
21336 |
|
|
inline functions, and the comp_unit_die. We can ignore the comp_unit_die.
|
21337 |
|
|
For concrete instances, we can get the parent die from the abstract
|
21338 |
|
|
instance. */
|
21339 |
|
|
for (node = limbo_die_list; node; node = next_node)
|
21340 |
|
|
{
|
21341 |
|
|
next_node = node->next;
|
21342 |
|
|
die = node->die;
|
21343 |
|
|
|
21344 |
|
|
if (die->die_parent == NULL)
|
21345 |
|
|
{
|
21346 |
|
|
dw_die_ref origin = get_AT_ref (die, DW_AT_abstract_origin);
|
21347 |
|
|
|
21348 |
|
|
if (origin)
|
21349 |
|
|
add_child_die (origin->die_parent, die);
|
21350 |
|
|
else if (die == comp_unit_die)
|
21351 |
|
|
;
|
21352 |
|
|
else if (errorcount > 0 || sorrycount > 0)
|
21353 |
|
|
/* It's OK to be confused by errors in the input. */
|
21354 |
|
|
add_child_die (comp_unit_die, die);
|
21355 |
|
|
else
|
21356 |
|
|
{
|
21357 |
|
|
/* In certain situations, the lexical block containing a
|
21358 |
|
|
nested function can be optimized away, which results
|
21359 |
|
|
in the nested function die being orphaned. Likewise
|
21360 |
|
|
with the return type of that nested function. Force
|
21361 |
|
|
this to be a child of the containing function.
|
21362 |
|
|
|
21363 |
|
|
It may happen that even the containing function got fully
|
21364 |
|
|
inlined and optimized out. In that case we are lost and
|
21365 |
|
|
assign the empty child. This should not be big issue as
|
21366 |
|
|
the function is likely unreachable too. */
|
21367 |
|
|
tree context = NULL_TREE;
|
21368 |
|
|
|
21369 |
|
|
gcc_assert (node->created_for);
|
21370 |
|
|
|
21371 |
|
|
if (DECL_P (node->created_for))
|
21372 |
|
|
context = DECL_CONTEXT (node->created_for);
|
21373 |
|
|
else if (TYPE_P (node->created_for))
|
21374 |
|
|
context = TYPE_CONTEXT (node->created_for);
|
21375 |
|
|
|
21376 |
|
|
gcc_assert (context
|
21377 |
|
|
&& (TREE_CODE (context) == FUNCTION_DECL
|
21378 |
|
|
|| TREE_CODE (context) == NAMESPACE_DECL));
|
21379 |
|
|
|
21380 |
|
|
origin = lookup_decl_die (context);
|
21381 |
|
|
if (origin)
|
21382 |
|
|
add_child_die (origin, die);
|
21383 |
|
|
else
|
21384 |
|
|
add_child_die (comp_unit_die, die);
|
21385 |
|
|
}
|
21386 |
|
|
}
|
21387 |
|
|
}
|
21388 |
|
|
|
21389 |
|
|
limbo_die_list = NULL;
|
21390 |
|
|
|
21391 |
|
|
resolve_addr (comp_unit_die);
|
21392 |
|
|
|
21393 |
|
|
for (node = deferred_asm_name; node; node = node->next)
|
21394 |
|
|
{
|
21395 |
|
|
tree decl = node->created_for;
|
21396 |
|
|
if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl))
|
21397 |
|
|
{
|
21398 |
|
|
add_AT_string (node->die, DW_AT_MIPS_linkage_name,
|
21399 |
|
|
IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
|
21400 |
|
|
move_linkage_attr (node->die);
|
21401 |
|
|
}
|
21402 |
|
|
}
|
21403 |
|
|
|
21404 |
|
|
deferred_asm_name = NULL;
|
21405 |
|
|
|
21406 |
|
|
/* Walk through the list of incomplete types again, trying once more to
|
21407 |
|
|
emit full debugging info for them. */
|
21408 |
|
|
retry_incomplete_types ();
|
21409 |
|
|
|
21410 |
|
|
if (flag_eliminate_unused_debug_types)
|
21411 |
|
|
prune_unused_types ();
|
21412 |
|
|
|
21413 |
|
|
/* Generate separate CUs for each of the include files we've seen.
|
21414 |
|
|
They will go into limbo_die_list. */
|
21415 |
|
|
if (flag_eliminate_dwarf2_dups && dwarf_version < 4)
|
21416 |
|
|
break_out_includes (comp_unit_die);
|
21417 |
|
|
|
21418 |
|
|
/* Generate separate COMDAT sections for type DIEs. */
|
21419 |
|
|
if (dwarf_version >= 4)
|
21420 |
|
|
{
|
21421 |
|
|
break_out_comdat_types (comp_unit_die);
|
21422 |
|
|
|
21423 |
|
|
/* Each new type_unit DIE was added to the limbo die list when created.
|
21424 |
|
|
Since these have all been added to comdat_type_list, clear the
|
21425 |
|
|
limbo die list. */
|
21426 |
|
|
limbo_die_list = NULL;
|
21427 |
|
|
|
21428 |
|
|
/* For each new comdat type unit, copy declarations for incomplete
|
21429 |
|
|
types to make the new unit self-contained (i.e., no direct
|
21430 |
|
|
references to the main compile unit). */
|
21431 |
|
|
for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next)
|
21432 |
|
|
copy_decls_for_unworthy_types (ctnode->root_die);
|
21433 |
|
|
copy_decls_for_unworthy_types (comp_unit_die);
|
21434 |
|
|
|
21435 |
|
|
/* In the process of copying declarations from one unit to another,
|
21436 |
|
|
we may have left some declarations behind that are no longer
|
21437 |
|
|
referenced. Prune them. */
|
21438 |
|
|
prune_unused_types ();
|
21439 |
|
|
}
|
21440 |
|
|
|
21441 |
|
|
/* Traverse the DIE's and add add sibling attributes to those DIE's
|
21442 |
|
|
that have children. */
|
21443 |
|
|
add_sibling_attributes (comp_unit_die);
|
21444 |
|
|
for (node = limbo_die_list; node; node = node->next)
|
21445 |
|
|
add_sibling_attributes (node->die);
|
21446 |
|
|
for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next)
|
21447 |
|
|
add_sibling_attributes (ctnode->root_die);
|
21448 |
|
|
|
21449 |
|
|
/* Output a terminator label for the .text section. */
|
21450 |
|
|
switch_to_section (text_section);
|
21451 |
|
|
targetm.asm_out.internal_label (asm_out_file, TEXT_END_LABEL, 0);
|
21452 |
|
|
if (flag_reorder_blocks_and_partition)
|
21453 |
|
|
{
|
21454 |
|
|
switch_to_section (unlikely_text_section ());
|
21455 |
|
|
targetm.asm_out.internal_label (asm_out_file, COLD_END_LABEL, 0);
|
21456 |
|
|
}
|
21457 |
|
|
|
21458 |
|
|
/* We can only use the low/high_pc attributes if all of the code was
|
21459 |
|
|
in .text. */
|
21460 |
|
|
if (!have_multiple_function_sections
|
21461 |
|
|
|| !(dwarf_version >= 3 || !dwarf_strict))
|
21462 |
|
|
{
|
21463 |
|
|
add_AT_lbl_id (comp_unit_die, DW_AT_low_pc, text_section_label);
|
21464 |
|
|
add_AT_lbl_id (comp_unit_die, DW_AT_high_pc, text_end_label);
|
21465 |
|
|
}
|
21466 |
|
|
|
21467 |
|
|
else
|
21468 |
|
|
{
|
21469 |
|
|
unsigned fde_idx = 0;
|
21470 |
|
|
bool range_list_added = false;
|
21471 |
|
|
|
21472 |
|
|
/* We need to give .debug_loc and .debug_ranges an appropriate
|
21473 |
|
|
"base address". Use zero so that these addresses become
|
21474 |
|
|
absolute. Historically, we've emitted the unexpected
|
21475 |
|
|
DW_AT_entry_pc instead of DW_AT_low_pc for this purpose.
|
21476 |
|
|
Emit both to give time for other tools to adapt. */
|
21477 |
|
|
add_AT_addr (comp_unit_die, DW_AT_low_pc, const0_rtx);
|
21478 |
|
|
add_AT_addr (comp_unit_die, DW_AT_entry_pc, const0_rtx);
|
21479 |
|
|
|
21480 |
|
|
if (text_section_used)
|
21481 |
|
|
add_ranges_by_labels (comp_unit_die, text_section_label,
|
21482 |
|
|
text_end_label, &range_list_added);
|
21483 |
|
|
if (flag_reorder_blocks_and_partition && cold_text_section_used)
|
21484 |
|
|
add_ranges_by_labels (comp_unit_die, cold_text_section_label,
|
21485 |
|
|
cold_end_label, &range_list_added);
|
21486 |
|
|
|
21487 |
|
|
for (fde_idx = 0; fde_idx < fde_table_in_use; fde_idx++)
|
21488 |
|
|
{
|
21489 |
|
|
dw_fde_ref fde = &fde_table[fde_idx];
|
21490 |
|
|
|
21491 |
|
|
if (fde->dw_fde_switched_sections)
|
21492 |
|
|
{
|
21493 |
|
|
if (!fde->in_std_section)
|
21494 |
|
|
add_ranges_by_labels (comp_unit_die,
|
21495 |
|
|
fde->dw_fde_hot_section_label,
|
21496 |
|
|
fde->dw_fde_hot_section_end_label,
|
21497 |
|
|
&range_list_added);
|
21498 |
|
|
if (!fde->cold_in_std_section)
|
21499 |
|
|
add_ranges_by_labels (comp_unit_die,
|
21500 |
|
|
fde->dw_fde_unlikely_section_label,
|
21501 |
|
|
fde->dw_fde_unlikely_section_end_label,
|
21502 |
|
|
&range_list_added);
|
21503 |
|
|
}
|
21504 |
|
|
else if (!fde->in_std_section)
|
21505 |
|
|
add_ranges_by_labels (comp_unit_die, fde->dw_fde_begin,
|
21506 |
|
|
fde->dw_fde_end, &range_list_added);
|
21507 |
|
|
}
|
21508 |
|
|
|
21509 |
|
|
if (range_list_added)
|
21510 |
|
|
add_ranges (NULL);
|
21511 |
|
|
}
|
21512 |
|
|
|
21513 |
|
|
/* Output location list section if necessary. */
|
21514 |
|
|
if (have_location_lists)
|
21515 |
|
|
{
|
21516 |
|
|
/* Output the location lists info. */
|
21517 |
|
|
switch_to_section (debug_loc_section);
|
21518 |
|
|
ASM_GENERATE_INTERNAL_LABEL (loc_section_label,
|
21519 |
|
|
DEBUG_LOC_SECTION_LABEL, 0);
|
21520 |
|
|
ASM_OUTPUT_LABEL (asm_out_file, loc_section_label);
|
21521 |
|
|
output_location_lists (die);
|
21522 |
|
|
}
|
21523 |
|
|
|
21524 |
|
|
if (debug_info_level >= DINFO_LEVEL_NORMAL)
|
21525 |
|
|
add_AT_lineptr (comp_unit_die, DW_AT_stmt_list,
|
21526 |
|
|
debug_line_section_label);
|
21527 |
|
|
|
21528 |
|
|
if (debug_info_level >= DINFO_LEVEL_VERBOSE)
|
21529 |
|
|
add_AT_macptr (comp_unit_die, DW_AT_macro_info, macinfo_section_label);
|
21530 |
|
|
|
21531 |
|
|
/* Output all of the compilation units. We put the main one last so that
|
21532 |
|
|
the offsets are available to output_pubnames. */
|
21533 |
|
|
for (node = limbo_die_list; node; node = node->next)
|
21534 |
|
|
output_comp_unit (node->die, 0);
|
21535 |
|
|
|
21536 |
|
|
comdat_type_table = htab_create (100, htab_ct_hash, htab_ct_eq, NULL);
|
21537 |
|
|
for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next)
|
21538 |
|
|
{
|
21539 |
|
|
void **slot = htab_find_slot (comdat_type_table, ctnode, INSERT);
|
21540 |
|
|
|
21541 |
|
|
/* Don't output duplicate types. */
|
21542 |
|
|
if (*slot != HTAB_EMPTY_ENTRY)
|
21543 |
|
|
continue;
|
21544 |
|
|
|
21545 |
|
|
/* Add a pointer to the line table for the main compilation unit
|
21546 |
|
|
so that the debugger can make sense of DW_AT_decl_file
|
21547 |
|
|
attributes. */
|
21548 |
|
|
if (debug_info_level >= DINFO_LEVEL_NORMAL)
|
21549 |
|
|
add_AT_lineptr (ctnode->root_die, DW_AT_stmt_list,
|
21550 |
|
|
debug_line_section_label);
|
21551 |
|
|
|
21552 |
|
|
output_comdat_type_unit (ctnode);
|
21553 |
|
|
*slot = ctnode;
|
21554 |
|
|
}
|
21555 |
|
|
htab_delete (comdat_type_table);
|
21556 |
|
|
|
21557 |
|
|
/* Output the main compilation unit if non-empty or if .debug_macinfo
|
21558 |
|
|
has been emitted. */
|
21559 |
|
|
output_comp_unit (comp_unit_die, debug_info_level >= DINFO_LEVEL_VERBOSE);
|
21560 |
|
|
|
21561 |
|
|
/* Output the abbreviation table. */
|
21562 |
|
|
switch_to_section (debug_abbrev_section);
|
21563 |
|
|
output_abbrev_section ();
|
21564 |
|
|
|
21565 |
|
|
/* Output public names table if necessary. */
|
21566 |
|
|
if (!VEC_empty (pubname_entry, pubname_table))
|
21567 |
|
|
{
|
21568 |
|
|
switch_to_section (debug_pubnames_section);
|
21569 |
|
|
output_pubnames (pubname_table);
|
21570 |
|
|
}
|
21571 |
|
|
|
21572 |
|
|
/* Output public types table if necessary. */
|
21573 |
|
|
/* ??? Only defined by DWARF3, but emitted by Darwin for DWARF2.
|
21574 |
|
|
It shouldn't hurt to emit it always, since pure DWARF2 consumers
|
21575 |
|
|
simply won't look for the section. */
|
21576 |
|
|
if (!VEC_empty (pubname_entry, pubtype_table))
|
21577 |
|
|
{
|
21578 |
|
|
switch_to_section (debug_pubtypes_section);
|
21579 |
|
|
output_pubnames (pubtype_table);
|
21580 |
|
|
}
|
21581 |
|
|
|
21582 |
|
|
/* Output direct and virtual call tables if necessary. */
|
21583 |
|
|
if (!VEC_empty (dcall_entry, dcall_table))
|
21584 |
|
|
{
|
21585 |
|
|
switch_to_section (debug_dcall_section);
|
21586 |
|
|
output_dcall_table ();
|
21587 |
|
|
}
|
21588 |
|
|
if (!VEC_empty (vcall_entry, vcall_table))
|
21589 |
|
|
{
|
21590 |
|
|
switch_to_section (debug_vcall_section);
|
21591 |
|
|
output_vcall_table ();
|
21592 |
|
|
}
|
21593 |
|
|
|
21594 |
|
|
/* Output the address range information. We only put functions in the arange
|
21595 |
|
|
table, so don't write it out if we don't have any. */
|
21596 |
|
|
if (fde_table_in_use)
|
21597 |
|
|
{
|
21598 |
|
|
switch_to_section (debug_aranges_section);
|
21599 |
|
|
output_aranges ();
|
21600 |
|
|
}
|
21601 |
|
|
|
21602 |
|
|
/* Output ranges section if necessary. */
|
21603 |
|
|
if (ranges_table_in_use)
|
21604 |
|
|
{
|
21605 |
|
|
switch_to_section (debug_ranges_section);
|
21606 |
|
|
ASM_OUTPUT_LABEL (asm_out_file, ranges_section_label);
|
21607 |
|
|
output_ranges ();
|
21608 |
|
|
}
|
21609 |
|
|
|
21610 |
|
|
/* Output the source line correspondence table. We must do this
|
21611 |
|
|
even if there is no line information. Otherwise, on an empty
|
21612 |
|
|
translation unit, we will generate a present, but empty,
|
21613 |
|
|
.debug_info section. IRIX 6.5 `nm' will then complain when
|
21614 |
|
|
examining the file. This is done late so that any filenames
|
21615 |
|
|
used by the debug_info section are marked as 'used'. */
|
21616 |
|
|
if (! DWARF2_ASM_LINE_DEBUG_INFO)
|
21617 |
|
|
{
|
21618 |
|
|
switch_to_section (debug_line_section);
|
21619 |
|
|
output_line_info ();
|
21620 |
|
|
}
|
21621 |
|
|
|
21622 |
|
|
/* Have to end the macro section. */
|
21623 |
|
|
if (debug_info_level >= DINFO_LEVEL_VERBOSE)
|
21624 |
|
|
{
|
21625 |
|
|
switch_to_section (debug_macinfo_section);
|
21626 |
|
|
dw2_asm_output_data (1, 0, "End compilation unit");
|
21627 |
|
|
}
|
21628 |
|
|
|
21629 |
|
|
/* If we emitted any DW_FORM_strp form attribute, output the string
|
21630 |
|
|
table too. */
|
21631 |
|
|
if (debug_str_hash)
|
21632 |
|
|
htab_traverse (debug_str_hash, output_indirect_string, NULL);
|
21633 |
|
|
}
|
21634 |
|
|
#else
|
21635 |
|
|
|
21636 |
|
|
/* This should never be used, but its address is needed for comparisons. */
|
21637 |
|
|
const struct gcc_debug_hooks dwarf2_debug_hooks =
|
21638 |
|
|
{
|
21639 |
|
|
0, /* init */
|
21640 |
|
|
0, /* finish */
|
21641 |
|
|
0, /* assembly_start */
|
21642 |
|
|
0, /* define */
|
21643 |
|
|
0, /* undef */
|
21644 |
|
|
0, /* start_source_file */
|
21645 |
|
|
0, /* end_source_file */
|
21646 |
|
|
0, /* begin_block */
|
21647 |
|
|
0, /* end_block */
|
21648 |
|
|
0, /* ignore_block */
|
21649 |
|
|
0, /* source_line */
|
21650 |
|
|
0, /* begin_prologue */
|
21651 |
|
|
0, /* end_prologue */
|
21652 |
|
|
0, /* end_epilogue */
|
21653 |
|
|
0, /* begin_function */
|
21654 |
|
|
0, /* end_function */
|
21655 |
|
|
0, /* function_decl */
|
21656 |
|
|
0, /* global_decl */
|
21657 |
|
|
0, /* type_decl */
|
21658 |
|
|
0, /* imported_module_or_decl */
|
21659 |
|
|
0, /* deferred_inline_function */
|
21660 |
|
|
0, /* outlining_inline_function */
|
21661 |
|
|
0, /* label */
|
21662 |
|
|
0, /* handle_pch */
|
21663 |
|
|
0, /* var_location */
|
21664 |
|
|
0, /* switch_text_section */
|
21665 |
|
|
0, /* direct_call */
|
21666 |
|
|
0, /* virtual_call_token */
|
21667 |
|
|
0, /* copy_call_info */
|
21668 |
|
|
0, /* virtual_call */
|
21669 |
|
|
0, /* set_name */
|
21670 |
|
|
|
21671 |
|
|
};
|
21672 |
|
|
|
21673 |
|
|
#endif /* DWARF2_DEBUGGING_INFO */
|
21674 |
|
|
|
21675 |
|
|
#include "gt-dwarf2out.h"
|