0
|
1 /* Output VMS debug format symbol table information from GCC.
|
|
2 Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
|
|
3 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
|
|
4 Free Software Foundation, Inc.
|
|
5 Contributed by Douglas B. Rupp (rupp@gnat.com).
|
|
6 Updated by Bernard W. Giroud (bgiroud@users.sourceforge.net).
|
|
7
|
|
8 This file is part of GCC.
|
|
9
|
|
10 GCC is free software; you can redistribute it and/or modify it under
|
|
11 the terms of the GNU General Public License as published by the Free
|
|
12 Software Foundation; either version 3, or (at your option) any later
|
|
13 version.
|
|
14
|
|
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
18 for more details.
|
|
19
|
|
20 You should have received a copy of the GNU General Public License
|
|
21 along with GCC; see the file COPYING3. If not see
|
|
22 <http://www.gnu.org/licenses/>. */
|
|
23
|
|
24 #include "config.h"
|
|
25 #include "system.h"
|
|
26 #include "coretypes.h"
|
|
27 #include "tm.h"
|
|
28
|
|
29 #ifdef VMS_DEBUGGING_INFO
|
|
30 #include "tree.h"
|
|
31 #include "version.h"
|
|
32 #include "flags.h"
|
|
33 #include "rtl.h"
|
|
34 #include "output.h"
|
|
35 #include "vmsdbg.h"
|
|
36 #include "debug.h"
|
|
37 #include "langhooks.h"
|
|
38 #include "function.h"
|
|
39 #include "target.h"
|
|
40
|
|
41 /* Difference in seconds between the VMS Epoch and the Unix Epoch */
|
|
42 static const long long vms_epoch_offset = 3506716800ll;
|
|
43
|
|
44 /* NOTE: In the comments in this file, many references are made to "Debug
|
|
45 Symbol Table". This term is abbreviated as `DST' throughout the remainder
|
|
46 of this file. */
|
|
47
|
|
48 typedef struct dst_line_info_struct *dst_line_info_ref;
|
|
49
|
|
50 /* Each entry in the line_info_table maintains the file and
|
|
51 line number associated with the label generated for that
|
|
52 entry. The label gives the PC value associated with
|
|
53 the line number entry. */
|
|
54 typedef struct dst_line_info_struct
|
|
55 {
|
|
56 unsigned long dst_file_num;
|
|
57 unsigned long dst_line_num;
|
|
58 }
|
|
59 dst_line_info_entry;
|
|
60
|
|
61 typedef struct dst_file_info_struct *dst_file_info_ref;
|
|
62
|
|
63 typedef struct dst_file_info_struct
|
|
64 {
|
|
65 char *file_name;
|
|
66 unsigned int max_line;
|
|
67 unsigned int listing_line_start;
|
|
68 long long cdt;
|
|
69 long ebk;
|
|
70 short ffb;
|
|
71 char rfo;
|
|
72 char flen;
|
|
73 }
|
|
74 dst_file_info_entry;
|
|
75
|
|
76 /* How to start an assembler comment. */
|
|
77 #ifndef ASM_COMMENT_START
|
|
78 #define ASM_COMMENT_START ";#"
|
|
79 #endif
|
|
80
|
|
81 /* Maximum size (in bytes) of an artificially generated label. */
|
|
82 #define MAX_ARTIFICIAL_LABEL_BYTES 30
|
|
83
|
|
84 /* Make sure we know the sizes of the various types debug can describe. These
|
|
85 are only defaults. If the sizes are different for your target, you should
|
|
86 override these values by defining the appropriate symbols in your tm.h
|
|
87 file. */
|
|
88 #ifndef PTR_SIZE
|
|
89 #define PTR_SIZE 4 /* Must be 32 bits for VMS debug info */
|
|
90 #endif
|
|
91
|
|
92 /* Pointer to a structure of filenames referenced by this compilation unit. */
|
|
93 static dst_file_info_ref file_info_table;
|
|
94
|
|
95 /* Total number of entries in the table (i.e. array) pointed to by
|
|
96 `file_info_table'. This is the *total* and includes both used and unused
|
|
97 slots. */
|
|
98 static unsigned int file_info_table_allocated;
|
|
99
|
|
100 /* Number of entries in the file_info_table which are actually in use. */
|
|
101 static unsigned int file_info_table_in_use;
|
|
102
|
|
103 /* Size (in elements) of increments by which we may expand the filename
|
|
104 table. */
|
|
105 #define FILE_TABLE_INCREMENT 64
|
|
106
|
|
107 /* A structure to hold basic information for the VMS end
|
|
108 routine. */
|
|
109
|
|
110 typedef struct vms_func_struct
|
|
111 {
|
|
112 const char *vms_func_name;
|
|
113 unsigned funcdef_number;
|
|
114 }
|
|
115 vms_func_node;
|
|
116
|
|
117 typedef struct vms_func_struct *vms_func_ref;
|
|
118
|
|
119 static unsigned int func_table_allocated;
|
|
120 static unsigned int func_table_in_use;
|
|
121 #define FUNC_TABLE_INCREMENT 256
|
|
122
|
|
123 /* A pointer to the base of a table that contains frame description
|
|
124 information for each routine. */
|
|
125 static vms_func_ref func_table;
|
|
126
|
|
127 /* Local pointer to the name of the main input file. Initialized in
|
|
128 vmsdbgout_init. */
|
|
129 static const char *primary_filename;
|
|
130
|
|
131 static char *module_producer;
|
|
132 static unsigned int module_language;
|
|
133
|
|
134 /* A pointer to the base of a table that contains line information
|
|
135 for each source code line in .text in the compilation unit. */
|
|
136 static dst_line_info_ref line_info_table;
|
|
137
|
|
138 /* Number of elements currently allocated for line_info_table. */
|
|
139 static unsigned int line_info_table_allocated;
|
|
140
|
|
141 /* Number of elements in line_info_table currently in use. */
|
|
142 static unsigned int line_info_table_in_use;
|
|
143
|
|
144 /* Size (in elements) of increments by which we may expand line_info_table. */
|
|
145 #define LINE_INFO_TABLE_INCREMENT 1024
|
|
146
|
|
147 /* Forward declarations for functions defined in this file. */
|
|
148 static char *full_name (const char *);
|
|
149 static unsigned int lookup_filename (const char *);
|
|
150 static void addr_const_to_string (char *, rtx);
|
|
151 static int write_debug_header (DST_HEADER *, const char *, int);
|
|
152 static int write_debug_addr (const char *, const char *, int);
|
|
153 static int write_debug_data1 (unsigned int, const char *, int);
|
|
154 static int write_debug_data2 (unsigned int, const char *, int);
|
|
155 static int write_debug_data4 (unsigned long, const char *, int);
|
|
156 static int write_debug_data8 (unsigned long long, const char *, int);
|
|
157 static int write_debug_delta4 (const char *, const char *, const char *, int);
|
|
158 static int write_debug_string (const char *, const char *, int);
|
|
159 static int write_modbeg (int);
|
|
160 static int write_modend (int);
|
|
161 static int write_rtnbeg (int, int);
|
|
162 static int write_rtnend (int, int);
|
|
163 static int write_pclines (int);
|
|
164 static int write_srccorr (int, dst_file_info_entry, int);
|
|
165 static int write_srccorrs (int);
|
|
166
|
|
167 static void vmsdbgout_init (const char *);
|
|
168 static void vmsdbgout_finish (const char *);
|
|
169 static void vmsdbgout_define (unsigned int, const char *);
|
|
170 static void vmsdbgout_undef (unsigned int, const char *);
|
|
171 static void vmsdbgout_start_source_file (unsigned int, const char *);
|
|
172 static void vmsdbgout_end_source_file (unsigned int);
|
|
173 static void vmsdbgout_begin_block (unsigned int, unsigned int);
|
|
174 static void vmsdbgout_end_block (unsigned int, unsigned int);
|
|
175 static bool vmsdbgout_ignore_block (const_tree);
|
|
176 static void vmsdbgout_source_line (unsigned int, const char *);
|
|
177 static void vmsdbgout_begin_prologue (unsigned int, const char *);
|
|
178 static void vmsdbgout_end_prologue (unsigned int, const char *);
|
|
179 static void vmsdbgout_end_function (unsigned int);
|
|
180 static void vmsdbgout_end_epilogue (unsigned int, const char *);
|
|
181 static void vmsdbgout_begin_function (tree);
|
|
182 static void vmsdbgout_decl (tree);
|
|
183 static void vmsdbgout_global_decl (tree);
|
|
184 static void vmsdbgout_abstract_function (tree);
|
|
185
|
|
186 /* The debug hooks structure. */
|
|
187
|
|
188 const struct gcc_debug_hooks vmsdbg_debug_hooks
|
|
189 = {vmsdbgout_init,
|
|
190 vmsdbgout_finish,
|
|
191 vmsdbgout_define,
|
|
192 vmsdbgout_undef,
|
|
193 vmsdbgout_start_source_file,
|
|
194 vmsdbgout_end_source_file,
|
|
195 vmsdbgout_begin_block,
|
|
196 vmsdbgout_end_block,
|
|
197 vmsdbgout_ignore_block,
|
|
198 vmsdbgout_source_line,
|
|
199 vmsdbgout_begin_prologue,
|
|
200 vmsdbgout_end_prologue,
|
|
201 vmsdbgout_end_epilogue,
|
|
202 vmsdbgout_begin_function,
|
|
203 vmsdbgout_end_function,
|
|
204 vmsdbgout_decl,
|
|
205 vmsdbgout_global_decl,
|
|
206 debug_nothing_tree_int, /* type_decl */
|
|
207 debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */
|
|
208 debug_nothing_tree, /* deferred_inline_function */
|
|
209 vmsdbgout_abstract_function,
|
|
210 debug_nothing_rtx, /* label */
|
|
211 debug_nothing_int, /* handle_pch */
|
|
212 debug_nothing_rtx, /* var_location */
|
|
213 debug_nothing_void, /* switch_text_section */
|
|
214 0 /* start_end_main_source_file */
|
|
215 };
|
|
216
|
|
217 /* Definitions of defaults for assembler-dependent names of various
|
|
218 pseudo-ops and section names.
|
|
219 Theses may be overridden in the tm.h file (if necessary) for a particular
|
|
220 assembler. */
|
|
221 #ifdef UNALIGNED_SHORT_ASM_OP
|
|
222 #undef UNALIGNED_SHORT_ASM_OP
|
|
223 #endif
|
|
224 #define UNALIGNED_SHORT_ASM_OP ".word"
|
|
225
|
|
226 #ifdef UNALIGNED_INT_ASM_OP
|
|
227 #undef UNALIGNED_INT_ASM_OP
|
|
228 #endif
|
|
229 #define UNALIGNED_INT_ASM_OP ".long"
|
|
230
|
|
231 #ifdef UNALIGNED_LONG_ASM_OP
|
|
232 #undef UNALIGNED_LONG_ASM_OP
|
|
233 #endif
|
|
234 #define UNALIGNED_LONG_ASM_OP ".long"
|
|
235
|
|
236 #ifdef UNALIGNED_DOUBLE_INT_ASM_OP
|
|
237 #undef UNALIGNED_DOUBLE_INT_ASM_OP
|
|
238 #endif
|
|
239 #define UNALIGNED_DOUBLE_INT_ASM_OP ".quad"
|
|
240
|
|
241 #ifdef ASM_BYTE_OP
|
|
242 #undef ASM_BYTE_OP
|
|
243 #endif
|
|
244 #define ASM_BYTE_OP ".byte"
|
|
245
|
|
246 #define NUMBYTES(I) ((I) < 256 ? 1 : (I) < 65536 ? 2 : 4)
|
|
247
|
|
248 #define NUMBYTES0(I) ((I) < 128 ? 0 : (I) < 65536 ? 2 : 4)
|
|
249
|
|
250 #ifndef UNALIGNED_PTR_ASM_OP
|
|
251 #define UNALIGNED_PTR_ASM_OP \
|
|
252 (PTR_SIZE == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP : UNALIGNED_INT_ASM_OP)
|
|
253 #endif
|
|
254
|
|
255 #ifndef UNALIGNED_OFFSET_ASM_OP
|
|
256 #define UNALIGNED_OFFSET_ASM_OP(OFFSET) \
|
|
257 (NUMBYTES(OFFSET) == 4 \
|
|
258 ? UNALIGNED_LONG_ASM_OP \
|
|
259 : (NUMBYTES(OFFSET) == 2 ? UNALIGNED_SHORT_ASM_OP : ASM_BYTE_OP))
|
|
260 #endif
|
|
261
|
|
262 /* Definitions of defaults for formats and names of various special
|
|
263 (artificial) labels which may be generated within this file (when the -g
|
|
264 options is used and VMS_DEBUGGING_INFO is in effect. If necessary, these
|
|
265 may be overridden from within the tm.h file, but typically, overriding these
|
|
266 defaults is unnecessary. */
|
|
267
|
|
268 static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
|
|
269
|
|
270 #ifndef TEXT_END_LABEL
|
|
271 #define TEXT_END_LABEL "Lvetext"
|
|
272 #endif
|
|
273 #ifndef FUNC_BEGIN_LABEL
|
|
274 #define FUNC_BEGIN_LABEL "LVFB"
|
|
275 #endif
|
|
276 #ifndef FUNC_PROLOG_LABEL
|
|
277 #define FUNC_PROLOG_LABEL "LVFP"
|
|
278 #endif
|
|
279 #ifndef FUNC_END_LABEL
|
|
280 #define FUNC_END_LABEL "LVFE"
|
|
281 #endif
|
|
282 #ifndef BLOCK_BEGIN_LABEL
|
|
283 #define BLOCK_BEGIN_LABEL "LVBB"
|
|
284 #endif
|
|
285 #ifndef BLOCK_END_LABEL
|
|
286 #define BLOCK_END_LABEL "LVBE"
|
|
287 #endif
|
|
288 #ifndef LINE_CODE_LABEL
|
|
289 #define LINE_CODE_LABEL "LVM"
|
|
290 #endif
|
|
291
|
|
292 #ifndef ASM_OUTPUT_DEBUG_DELTA2
|
|
293 #define ASM_OUTPUT_DEBUG_DELTA2(FILE,LABEL1,LABEL2) \
|
|
294 do \
|
|
295 { \
|
|
296 fprintf ((FILE), "\t%s\t", UNALIGNED_SHORT_ASM_OP); \
|
|
297 assemble_name (FILE, LABEL1); \
|
|
298 fprintf (FILE, "-"); \
|
|
299 assemble_name (FILE, LABEL2); \
|
|
300 } \
|
|
301 while (0)
|
|
302 #endif
|
|
303
|
|
304 #ifndef ASM_OUTPUT_DEBUG_DELTA4
|
|
305 #define ASM_OUTPUT_DEBUG_DELTA4(FILE,LABEL1,LABEL2) \
|
|
306 do \
|
|
307 { \
|
|
308 fprintf ((FILE), "\t%s\t", UNALIGNED_INT_ASM_OP); \
|
|
309 assemble_name (FILE, LABEL1); \
|
|
310 fprintf (FILE, "-"); \
|
|
311 assemble_name (FILE, LABEL2); \
|
|
312 } \
|
|
313 while (0)
|
|
314 #endif
|
|
315
|
|
316 #ifndef ASM_OUTPUT_DEBUG_ADDR_DELTA
|
|
317 #define ASM_OUTPUT_DEBUG_ADDR_DELTA(FILE,LABEL1,LABEL2) \
|
|
318 do \
|
|
319 { \
|
|
320 fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP); \
|
|
321 assemble_name (FILE, LABEL1); \
|
|
322 fprintf (FILE, "-"); \
|
|
323 assemble_name (FILE, LABEL2); \
|
|
324 } \
|
|
325 while (0)
|
|
326 #endif
|
|
327
|
|
328 #ifndef ASM_OUTPUT_DEBUG_ADDR
|
|
329 #define ASM_OUTPUT_DEBUG_ADDR(FILE,LABEL) \
|
|
330 do \
|
|
331 { \
|
|
332 fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP); \
|
|
333 assemble_name (FILE, LABEL); \
|
|
334 } \
|
|
335 while (0)
|
|
336 #endif
|
|
337
|
|
338 #ifndef ASM_OUTPUT_DEBUG_ADDR_CONST
|
|
339 #define ASM_OUTPUT_DEBUG_ADDR_CONST(FILE,ADDR) \
|
|
340 fprintf ((FILE), "\t%s\t%s", UNALIGNED_PTR_ASM_OP, (ADDR))
|
|
341 #endif
|
|
342
|
|
343 #ifndef ASM_OUTPUT_DEBUG_DATA1
|
|
344 #define ASM_OUTPUT_DEBUG_DATA1(FILE,VALUE) \
|
|
345 fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, (unsigned char) VALUE)
|
|
346 #endif
|
|
347
|
|
348 #ifndef ASM_OUTPUT_DEBUG_DATA2
|
|
349 #define ASM_OUTPUT_DEBUG_DATA2(FILE,VALUE) \
|
|
350 fprintf ((FILE), "\t%s\t0x%x", UNALIGNED_SHORT_ASM_OP, \
|
|
351 (unsigned short) VALUE)
|
|
352 #endif
|
|
353
|
|
354 #ifndef ASM_OUTPUT_DEBUG_DATA4
|
|
355 #define ASM_OUTPUT_DEBUG_DATA4(FILE,VALUE) \
|
|
356 fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_INT_ASM_OP, (unsigned long) VALUE)
|
|
357 #endif
|
|
358
|
|
359 #ifndef ASM_OUTPUT_DEBUG_DATA
|
|
360 #define ASM_OUTPUT_DEBUG_DATA(FILE,VALUE) \
|
|
361 fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_OFFSET_ASM_OP(VALUE), VALUE)
|
|
362 #endif
|
|
363
|
|
364 #ifndef ASM_OUTPUT_DEBUG_ADDR_DATA
|
|
365 #define ASM_OUTPUT_DEBUG_ADDR_DATA(FILE,VALUE) \
|
|
366 fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_PTR_ASM_OP, \
|
|
367 (unsigned long) VALUE)
|
|
368 #endif
|
|
369
|
|
370 #ifndef ASM_OUTPUT_DEBUG_DATA8
|
|
371 #define ASM_OUTPUT_DEBUG_DATA8(FILE,VALUE) \
|
|
372 fprintf ((FILE), "\t%s\t0x%llx", UNALIGNED_DOUBLE_INT_ASM_OP, \
|
|
373 (unsigned long long) VALUE)
|
|
374 #endif
|
|
375
|
|
376 /* This is similar to the default ASM_OUTPUT_ASCII, except that no trailing
|
|
377 newline is produced. When flag_verbose_asm is asserted, we add commentary
|
|
378 at the end of the line, so we must avoid output of a newline here. */
|
|
379 #ifndef ASM_OUTPUT_DEBUG_STRING
|
|
380 #define ASM_OUTPUT_DEBUG_STRING(FILE,P) \
|
|
381 do \
|
|
382 { \
|
|
383 register int slen = strlen(P); \
|
|
384 register const char *p = (P); \
|
|
385 register int i; \
|
|
386 fprintf (FILE, "\t.ascii \""); \
|
|
387 for (i = 0; i < slen; i++) \
|
|
388 { \
|
|
389 register int c = p[i]; \
|
|
390 if (c == '\"' || c == '\\') \
|
|
391 putc ('\\', FILE); \
|
|
392 if (c >= ' ' && c < 0177) \
|
|
393 putc (c, FILE); \
|
|
394 else \
|
|
395 fprintf (FILE, "\\%o", c); \
|
|
396 } \
|
|
397 fprintf (FILE, "\""); \
|
|
398 } \
|
|
399 while (0)
|
|
400 #endif
|
|
401
|
|
402 /* Convert a reference to the assembler name of a C-level name. This
|
|
403 macro has the same effect as ASM_OUTPUT_LABELREF, but copies to
|
|
404 a string rather than writing to a file. */
|
|
405 #ifndef ASM_NAME_TO_STRING
|
|
406 #define ASM_NAME_TO_STRING(STR, NAME) \
|
|
407 do \
|
|
408 { \
|
|
409 if ((NAME)[0] == '*') \
|
|
410 strcpy (STR, NAME+1); \
|
|
411 else \
|
|
412 strcpy (STR, NAME); \
|
|
413 } \
|
|
414 while (0)
|
|
415 #endif
|
|
416
|
|
417
|
|
418 /* General utility functions. */
|
|
419
|
|
420 /* Convert an integer constant expression into assembler syntax. Addition and
|
|
421 subtraction are the only arithmetic that may appear in these expressions.
|
|
422 This is an adaptation of output_addr_const in final.c. Here, the target
|
|
423 of the conversion is a string buffer. We can't use output_addr_const
|
|
424 directly, because it writes to a file. */
|
|
425
|
|
426 static void
|
|
427 addr_const_to_string (char *str, rtx x)
|
|
428 {
|
|
429 char buf1[256];
|
|
430 char buf2[256];
|
|
431
|
|
432 restart:
|
|
433 str[0] = '\0';
|
|
434 switch (GET_CODE (x))
|
|
435 {
|
|
436 case PC:
|
|
437 gcc_assert (flag_pic);
|
|
438 strcat (str, ",");
|
|
439 break;
|
|
440
|
|
441 case SYMBOL_REF:
|
|
442 ASM_NAME_TO_STRING (buf1, XSTR (x, 0));
|
|
443 strcat (str, buf1);
|
|
444 break;
|
|
445
|
|
446 case LABEL_REF:
|
|
447 ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
|
|
448 ASM_NAME_TO_STRING (buf2, buf1);
|
|
449 strcat (str, buf2);
|
|
450 break;
|
|
451
|
|
452 case CODE_LABEL:
|
|
453 ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (x));
|
|
454 ASM_NAME_TO_STRING (buf2, buf1);
|
|
455 strcat (str, buf2);
|
|
456 break;
|
|
457
|
|
458 case CONST_INT:
|
|
459 sprintf (buf1, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
|
|
460 strcat (str, buf1);
|
|
461 break;
|
|
462
|
|
463 case CONST:
|
|
464 /* This used to output parentheses around the expression, but that does
|
|
465 not work on the 386 (either ATT or BSD assembler). */
|
|
466 addr_const_to_string (buf1, XEXP (x, 0));
|
|
467 strcat (str, buf1);
|
|
468 break;
|
|
469
|
|
470 case CONST_DOUBLE:
|
|
471 if (GET_MODE (x) == VOIDmode)
|
|
472 {
|
|
473 /* We can use %d if the number is one word and positive. */
|
|
474 if (CONST_DOUBLE_HIGH (x))
|
|
475 sprintf (buf1, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
|
|
476 CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
|
|
477 else if (CONST_DOUBLE_LOW (x) < 0)
|
|
478 sprintf (buf1, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (x));
|
|
479 else
|
|
480 sprintf (buf1, HOST_WIDE_INT_PRINT_DEC,
|
|
481 CONST_DOUBLE_LOW (x));
|
|
482 strcat (str, buf1);
|
|
483 }
|
|
484 else
|
|
485 /* We can't handle floating point constants; PRINT_OPERAND must
|
|
486 handle them. */
|
|
487 output_operand_lossage ("floating constant misused");
|
|
488 break;
|
|
489
|
|
490 case PLUS:
|
|
491 /* Some assemblers need integer constants to appear last (eg masm). */
|
|
492 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
|
|
493 {
|
|
494 addr_const_to_string (buf1, XEXP (x, 1));
|
|
495 strcat (str, buf1);
|
|
496 if (INTVAL (XEXP (x, 0)) >= 0)
|
|
497 strcat (str, "+");
|
|
498 addr_const_to_string (buf1, XEXP (x, 0));
|
|
499 strcat (str, buf1);
|
|
500 }
|
|
501 else
|
|
502 {
|
|
503 addr_const_to_string (buf1, XEXP (x, 0));
|
|
504 strcat (str, buf1);
|
|
505 if (INTVAL (XEXP (x, 1)) >= 0)
|
|
506 strcat (str, "+");
|
|
507 addr_const_to_string (buf1, XEXP (x, 1));
|
|
508 strcat (str, buf1);
|
|
509 }
|
|
510 break;
|
|
511
|
|
512 case MINUS:
|
|
513 /* Avoid outputting things like x-x or x+5-x, since some assemblers
|
|
514 can't handle that. */
|
|
515 x = simplify_subtraction (x);
|
|
516 if (GET_CODE (x) != MINUS)
|
|
517 goto restart;
|
|
518
|
|
519 addr_const_to_string (buf1, XEXP (x, 0));
|
|
520 strcat (str, buf1);
|
|
521 strcat (str, "-");
|
|
522 if (GET_CODE (XEXP (x, 1)) == CONST_INT
|
|
523 && INTVAL (XEXP (x, 1)) < 0)
|
|
524 {
|
|
525 strcat (str, "(");
|
|
526 addr_const_to_string (buf1, XEXP (x, 1));
|
|
527 strcat (str, buf1);
|
|
528 strcat (str, ")");
|
|
529 }
|
|
530 else
|
|
531 {
|
|
532 addr_const_to_string (buf1, XEXP (x, 1));
|
|
533 strcat (str, buf1);
|
|
534 }
|
|
535 break;
|
|
536
|
|
537 case ZERO_EXTEND:
|
|
538 case SIGN_EXTEND:
|
|
539 addr_const_to_string (buf1, XEXP (x, 0));
|
|
540 strcat (str, buf1);
|
|
541 break;
|
|
542
|
|
543 default:
|
|
544 output_operand_lossage ("invalid expression as operand");
|
|
545 }
|
|
546 }
|
|
547
|
|
548 /* Output the debug header HEADER. Also output COMMENT if flag_verbose_asm is
|
|
549 set. Return the header size. Just return the size if DOSIZEONLY is
|
|
550 nonzero. */
|
|
551
|
|
552 static int
|
|
553 write_debug_header (DST_HEADER *header, const char *comment, int dosizeonly)
|
|
554 {
|
|
555 if (!dosizeonly)
|
|
556 {
|
|
557 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file,
|
|
558 header->dst__header_length.dst_w_length);
|
|
559
|
|
560 if (flag_verbose_asm)
|
|
561 fprintf (asm_out_file, "\t%s record length", ASM_COMMENT_START);
|
|
562 fputc ('\n', asm_out_file);
|
|
563
|
|
564 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file,
|
|
565 header->dst__header_type.dst_w_type);
|
|
566
|
|
567 if (flag_verbose_asm)
|
|
568 fprintf (asm_out_file, "\t%s record type (%s)", ASM_COMMENT_START,
|
|
569 comment);
|
|
570
|
|
571 fputc ('\n', asm_out_file);
|
|
572 }
|
|
573
|
|
574 return 4;
|
|
575 }
|
|
576
|
|
577 /* Output the address of SYMBOL. Also output COMMENT if flag_verbose_asm is
|
|
578 set. Return the address size. Just return the size if DOSIZEONLY is
|
|
579 nonzero. */
|
|
580
|
|
581 static int
|
|
582 write_debug_addr (const char *symbol, const char *comment, int dosizeonly)
|
|
583 {
|
|
584 if (!dosizeonly)
|
|
585 {
|
|
586 ASM_OUTPUT_DEBUG_ADDR (asm_out_file, symbol);
|
|
587 if (flag_verbose_asm)
|
|
588 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
|
|
589 fputc ('\n', asm_out_file);
|
|
590 }
|
|
591
|
|
592 return PTR_SIZE;
|
|
593 }
|
|
594
|
|
595 /* Output the single byte DATA1. Also output COMMENT if flag_verbose_asm is
|
|
596 set. Return the data size. Just return the size if DOSIZEONLY is
|
|
597 nonzero. */
|
|
598
|
|
599 static int
|
|
600 write_debug_data1 (unsigned int data1, const char *comment, int dosizeonly)
|
|
601 {
|
|
602 if (!dosizeonly)
|
|
603 {
|
|
604 ASM_OUTPUT_DEBUG_DATA1 (asm_out_file, data1);
|
|
605 if (flag_verbose_asm)
|
|
606 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
|
|
607 fputc ('\n', asm_out_file);
|
|
608 }
|
|
609
|
|
610 return 1;
|
|
611 }
|
|
612
|
|
613 /* Output the single word DATA2. Also output COMMENT if flag_verbose_asm is
|
|
614 set. Return the data size. Just return the size if DOSIZEONLY is
|
|
615 nonzero. */
|
|
616
|
|
617 static int
|
|
618 write_debug_data2 (unsigned int data2, const char *comment, int dosizeonly)
|
|
619 {
|
|
620 if (!dosizeonly)
|
|
621 {
|
|
622 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file, data2);
|
|
623 if (flag_verbose_asm)
|
|
624 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
|
|
625 fputc ('\n', asm_out_file);
|
|
626 }
|
|
627
|
|
628 return 2;
|
|
629 }
|
|
630
|
|
631 /* Output double word DATA4. Also output COMMENT if flag_verbose_asm is set.
|
|
632 Return the data size. Just return the size if DOSIZEONLY is nonzero. */
|
|
633
|
|
634 static int
|
|
635 write_debug_data4 (unsigned long data4, const char *comment, int dosizeonly)
|
|
636 {
|
|
637 if (!dosizeonly)
|
|
638 {
|
|
639 ASM_OUTPUT_DEBUG_DATA4 (asm_out_file, data4);
|
|
640 if (flag_verbose_asm)
|
|
641 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
|
|
642 fputc ('\n', asm_out_file);
|
|
643 }
|
|
644
|
|
645 return 4;
|
|
646 }
|
|
647
|
|
648 /* Output quad word DATA8. Also output COMMENT if flag_verbose_asm is set.
|
|
649 Return the data size. Just return the size if DOSIZEONLY is nonzero. */
|
|
650
|
|
651 static int
|
|
652 write_debug_data8 (unsigned long long data8, const char *comment,
|
|
653 int dosizeonly)
|
|
654 {
|
|
655 if (!dosizeonly)
|
|
656 {
|
|
657 ASM_OUTPUT_DEBUG_DATA8 (asm_out_file, data8);
|
|
658 if (flag_verbose_asm)
|
|
659 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
|
|
660 fputc ('\n', asm_out_file);
|
|
661 }
|
|
662
|
|
663 return 8;
|
|
664 }
|
|
665
|
|
666 /* Output the difference between LABEL1 and LABEL2. Also output COMMENT if
|
|
667 flag_verbose_asm is set. Return the data size. Just return the size if
|
|
668 DOSIZEONLY is nonzero. */
|
|
669
|
|
670 static int
|
|
671 write_debug_delta4 (const char *label1, const char *label2,
|
|
672 const char *comment, int dosizeonly)
|
|
673 {
|
|
674 if (!dosizeonly)
|
|
675 {
|
|
676 ASM_OUTPUT_DEBUG_DELTA4 (asm_out_file, label1, label2);
|
|
677 if (flag_verbose_asm)
|
|
678 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
|
|
679 fputc ('\n', asm_out_file);
|
|
680 }
|
|
681
|
|
682 return 4;
|
|
683 }
|
|
684
|
|
685 /* Output a character string STRING. Also write COMMENT if flag_verbose_asm is
|
|
686 set. Return the string length. Just return the length if DOSIZEONLY is
|
|
687 nonzero. */
|
|
688
|
|
689 static int
|
|
690 write_debug_string (const char *string, const char *comment, int dosizeonly)
|
|
691 {
|
|
692 if (!dosizeonly)
|
|
693 {
|
|
694 ASM_OUTPUT_DEBUG_STRING (asm_out_file, string);
|
|
695 if (flag_verbose_asm)
|
|
696 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
|
|
697 fputc ('\n', asm_out_file);
|
|
698 }
|
|
699
|
|
700 return strlen (string);
|
|
701 }
|
|
702
|
|
703 /* Output a module begin header and return the header size. Just return the
|
|
704 size if DOSIZEONLY is nonzero. */
|
|
705
|
|
706 static int
|
|
707 write_modbeg (int dosizeonly)
|
|
708 {
|
|
709 DST_MODULE_BEGIN modbeg;
|
|
710 DST_MB_TRLR mb_trlr;
|
|
711 int i;
|
|
712 char *module_name, *m;
|
|
713 int modnamelen;
|
|
714 int prodnamelen;
|
|
715 int totsize = 0;
|
|
716
|
|
717 /* Assumes primary filename has Unix syntax file spec. */
|
|
718 module_name = xstrdup (lbasename (primary_filename));
|
|
719
|
|
720 m = strrchr (module_name, '.');
|
|
721 if (m)
|
|
722 *m = 0;
|
|
723
|
|
724 modnamelen = strlen (module_name);
|
|
725 for (i = 0; i < modnamelen; i++)
|
|
726 module_name[i] = TOUPPER (module_name[i]);
|
|
727
|
|
728 prodnamelen = strlen (module_producer);
|
|
729
|
|
730 modbeg.dst_a_modbeg_header.dst__header_length.dst_w_length
|
|
731 = DST_K_MODBEG_SIZE + modnamelen + DST_K_MB_TRLR_SIZE + prodnamelen - 1;
|
|
732 modbeg.dst_a_modbeg_header.dst__header_type.dst_w_type = DST_K_MODBEG;
|
|
733 modbeg.dst_b_modbeg_flags.dst_v_modbeg_hide = 0;
|
|
734 modbeg.dst_b_modbeg_flags.dst_v_modbeg_version = 1;
|
|
735 modbeg.dst_b_modbeg_flags.dst_v_modbeg_unused = 0;
|
|
736 modbeg.dst_b_modbeg_unused = 0;
|
|
737 modbeg.dst_l_modbeg_language = module_language;
|
|
738 modbeg.dst_w_version_major = DST_K_VERSION_MAJOR;
|
|
739 modbeg.dst_w_version_minor = DST_K_VERSION_MINOR;
|
|
740 modbeg.dst_b_modbeg_name = strlen (module_name);
|
|
741
|
|
742 mb_trlr.dst_b_compiler = strlen (module_producer);
|
|
743
|
|
744 totsize += write_debug_header (&modbeg.dst_a_modbeg_header,
|
|
745 "modbeg", dosizeonly);
|
|
746 totsize += write_debug_data1 (*((char *) &modbeg.dst_b_modbeg_flags),
|
|
747 "flags", dosizeonly);
|
|
748 totsize += write_debug_data1 (modbeg.dst_b_modbeg_unused,
|
|
749 "unused", dosizeonly);
|
|
750 totsize += write_debug_data4 (modbeg.dst_l_modbeg_language,
|
|
751 "language", dosizeonly);
|
|
752 totsize += write_debug_data2 (modbeg.dst_w_version_major,
|
|
753 "DST major version", dosizeonly);
|
|
754 totsize += write_debug_data2 (modbeg.dst_w_version_minor,
|
|
755 "DST minor version", dosizeonly);
|
|
756 totsize += write_debug_data1 (modbeg.dst_b_modbeg_name,
|
|
757 "length of module name", dosizeonly);
|
|
758 totsize += write_debug_string (module_name, "module name", dosizeonly);
|
|
759 totsize += write_debug_data1 (mb_trlr.dst_b_compiler,
|
|
760 "length of compiler name", dosizeonly);
|
|
761 totsize += write_debug_string (module_producer, "compiler name", dosizeonly);
|
|
762
|
|
763 return totsize;
|
|
764 }
|
|
765
|
|
766 /* Output a module end trailer and return the trailer size. Just return
|
|
767 the size if DOSIZEONLY is nonzero. */
|
|
768
|
|
769 static int
|
|
770 write_modend (int dosizeonly)
|
|
771 {
|
|
772 DST_MODULE_END modend;
|
|
773 int totsize = 0;
|
|
774
|
|
775 modend.dst_a_modend_header.dst__header_length.dst_w_length
|
|
776 = DST_K_MODEND_SIZE - 1;
|
|
777 modend.dst_a_modend_header.dst__header_type.dst_w_type = DST_K_MODEND;
|
|
778
|
|
779 totsize += write_debug_header (&modend.dst_a_modend_header, "modend",
|
|
780 dosizeonly);
|
|
781
|
|
782 return totsize;
|
|
783 }
|
|
784
|
|
785 /* Output a routine begin header routine RTNNUM and return the header size.
|
|
786 Just return the size if DOSIZEONLY is nonzero. */
|
|
787
|
|
788 static int
|
|
789 write_rtnbeg (int rtnnum, int dosizeonly)
|
|
790 {
|
|
791 const char *rtnname;
|
|
792 int rtnnamelen;
|
|
793 char *rtnentryname;
|
|
794 int totsize = 0;
|
|
795 char label[MAX_ARTIFICIAL_LABEL_BYTES];
|
|
796 DST_ROUTINE_BEGIN rtnbeg;
|
|
797 DST_PROLOG prolog;
|
|
798 vms_func_ref fde = &func_table[rtnnum];
|
|
799
|
|
800 rtnname = fde->vms_func_name;
|
|
801 rtnnamelen = strlen (rtnname);
|
|
802 rtnentryname = concat (rtnname, "..en", NULL);
|
|
803
|
|
804 if (!strcmp (rtnname, "main"))
|
|
805 {
|
|
806 DST_HEADER header;
|
|
807 const char *go = "TRANSFER$BREAK$GO";
|
|
808
|
|
809 /* This command isn't documented in DSTRECORDS, so it's made to
|
|
810 look like what DEC C does */
|
|
811
|
|
812 /* header size - 1st byte + flag byte + STO_LW size
|
|
813 + string count byte + string length */
|
|
814 header.dst__header_length.dst_w_length
|
|
815 = DST_K_DST_HEADER_SIZE - 1 + 1 + 4 + 1 + strlen (go);
|
|
816 header.dst__header_type.dst_w_type = 0x17;
|
|
817
|
|
818 totsize += write_debug_header (&header, "transfer", dosizeonly);
|
|
819
|
|
820 /* I think this is a flag byte, but I don't know what this flag means */
|
|
821 totsize += write_debug_data1 (0x1, "flags ???", dosizeonly);
|
|
822
|
|
823 /* Routine Begin PD Address */
|
|
824 totsize += write_debug_addr (rtnname, "main procedure descriptor",
|
|
825 dosizeonly);
|
|
826 totsize += write_debug_data1 (strlen (go), "length of main_name",
|
|
827 dosizeonly);
|
|
828 totsize += write_debug_string (go, "main name", dosizeonly);
|
|
829 }
|
|
830
|
|
831 /* The header length never includes the length byte. */
|
|
832 rtnbeg.dst_a_rtnbeg_header.dst__header_length.dst_w_length
|
|
833 = DST_K_RTNBEG_SIZE + rtnnamelen - 1;
|
|
834 rtnbeg.dst_a_rtnbeg_header.dst__header_type.dst_w_type = DST_K_RTNBEG;
|
|
835 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_unused = 0;
|
|
836 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_unalloc = 0;
|
|
837 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_prototype = 0;
|
|
838 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_inlined = 0;
|
|
839 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_no_call = 1;
|
|
840 rtnbeg.dst_b_rtnbeg_name = rtnnamelen;
|
|
841
|
|
842 totsize += write_debug_header (&rtnbeg.dst_a_rtnbeg_header, "rtnbeg",
|
|
843 dosizeonly);
|
|
844 totsize += write_debug_data1 (*((char *) &rtnbeg.dst_b_rtnbeg_flags),
|
|
845 "flags", dosizeonly);
|
|
846
|
|
847 /* Routine Begin Address */
|
|
848 totsize += write_debug_addr (rtnentryname, "routine entry name", dosizeonly);
|
|
849
|
|
850 /* Routine Begin PD Address */
|
|
851 totsize += write_debug_addr (rtnname, "routine procedure descriptor",
|
|
852 dosizeonly);
|
|
853
|
|
854 /* Routine Begin Name */
|
|
855 totsize += write_debug_data1 (rtnbeg.dst_b_rtnbeg_name,
|
|
856 "length of routine name", dosizeonly);
|
|
857
|
|
858 totsize += write_debug_string (rtnname, "routine name", dosizeonly);
|
|
859
|
|
860 free (rtnentryname);
|
|
861
|
|
862 if (debug_info_level > DINFO_LEVEL_TERSE)
|
|
863 {
|
|
864 prolog.dst_a_prolog_header.dst__header_length.dst_w_length
|
|
865 = DST_K_PROLOG_SIZE - 1;
|
|
866 prolog.dst_a_prolog_header.dst__header_type.dst_w_type = DST_K_PROLOG;
|
|
867
|
|
868 totsize += write_debug_header (&prolog.dst_a_prolog_header, "prolog",
|
|
869 dosizeonly);
|
|
870
|
|
871 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL, fde->funcdef_number);
|
|
872 totsize += write_debug_addr (label, "prolog breakpoint addr",
|
|
873 dosizeonly);
|
|
874 }
|
|
875
|
|
876 return totsize;
|
|
877 }
|
|
878
|
|
879 /* Output a routine end trailer for routine RTNNUM and return the header size.
|
|
880 Just return the size if DOSIZEONLY is nonzero. */
|
|
881
|
|
882 static int
|
|
883 write_rtnend (int rtnnum, int dosizeonly)
|
|
884 {
|
|
885 DST_ROUTINE_END rtnend;
|
|
886 char label1[MAX_ARTIFICIAL_LABEL_BYTES];
|
|
887 char label2[MAX_ARTIFICIAL_LABEL_BYTES];
|
|
888 int totsize;
|
|
889 vms_func_ref fde = &func_table[rtnnum];
|
|
890 int corrected_rtnnum = fde->funcdef_number;
|
|
891
|
|
892 totsize = 0;
|
|
893
|
|
894 rtnend.dst_a_rtnend_header.dst__header_length.dst_w_length
|
|
895 = DST_K_RTNEND_SIZE - 1;
|
|
896 rtnend.dst_a_rtnend_header.dst__header_type.dst_w_type = DST_K_RTNEND;
|
|
897 rtnend.dst_b_rtnend_unused = 0;
|
|
898 rtnend.dst_l_rtnend_size = 0; /* Calculated below. */
|
|
899
|
|
900 totsize += write_debug_header (&rtnend.dst_a_rtnend_header, "rtnend",
|
|
901 dosizeonly);
|
|
902 totsize += write_debug_data1 (rtnend.dst_b_rtnend_unused, "unused",
|
|
903 dosizeonly);
|
|
904
|
|
905 ASM_GENERATE_INTERNAL_LABEL (label1, FUNC_BEGIN_LABEL, corrected_rtnnum);
|
|
906 ASM_GENERATE_INTERNAL_LABEL (label2, FUNC_END_LABEL, corrected_rtnnum);
|
|
907 totsize += write_debug_delta4 (label2, label1, "routine size", dosizeonly);
|
|
908
|
|
909 return totsize;
|
|
910 }
|
|
911
|
|
912 #define K_DELTA_PC(I) \
|
|
913 ((I) < 128 ? -(I) : (I) < 65536 ? DST_K_DELTA_PC_W : DST_K_DELTA_PC_L)
|
|
914
|
|
915 #define K_SET_LINUM(I) \
|
|
916 ((I) < 256 ? DST_K_SET_LINUM_B \
|
|
917 : (I) < 65536 ? DST_K_SET_LINUM : DST_K_SET_LINUM_L)
|
|
918
|
|
919 #define K_INCR_LINUM(I) \
|
|
920 ((I) < 256 ? DST_K_INCR_LINUM \
|
|
921 : (I) < 65536 ? DST_K_INCR_LINUM_W : DST_K_INCR_LINUM_L)
|
|
922
|
|
923 /* Output the PC to line number correlations and return the size. Just return
|
|
924 the size if DOSIZEONLY is nonzero */
|
|
925
|
|
926 static int
|
|
927 write_pclines (int dosizeonly)
|
|
928 {
|
|
929 unsigned i;
|
|
930 int fn;
|
|
931 int ln, lastln;
|
|
932 int linestart = 0;
|
|
933 int max_line;
|
|
934 DST_LINE_NUM_HEADER line_num;
|
|
935 DST_PCLINE_COMMANDS pcline;
|
|
936 char label[MAX_ARTIFICIAL_LABEL_BYTES];
|
|
937 char lastlabel[MAX_ARTIFICIAL_LABEL_BYTES];
|
|
938 int totsize = 0;
|
|
939 char buff[256];
|
|
940
|
|
941 max_line = file_info_table[1].max_line;
|
|
942 file_info_table[1].listing_line_start = linestart;
|
|
943 linestart = linestart + ((max_line / 100000) + 1) * 100000;
|
|
944
|
|
945 for (i = 2; i < file_info_table_in_use; i++)
|
|
946 {
|
|
947 max_line = file_info_table[i].max_line;
|
|
948 file_info_table[i].listing_line_start = linestart;
|
|
949 linestart = linestart + ((max_line / 10000) + 1) * 10000;
|
|
950 }
|
|
951
|
|
952 /* Set starting address to beginning of text section. */
|
|
953 line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 8;
|
|
954 line_num.dst_a_line_num_header.dst__header_type.dst_w_type = DST_K_LINE_NUM;
|
|
955 pcline.dst_b_pcline_command = DST_K_SET_ABS_PC;
|
|
956
|
|
957 totsize += write_debug_header (&line_num.dst_a_line_num_header,
|
|
958 "line_num", dosizeonly);
|
|
959 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
|
|
960 "line_num (SET ABS PC)", dosizeonly);
|
|
961
|
|
962 if (dosizeonly)
|
|
963 totsize += 4;
|
|
964 else
|
|
965 {
|
|
966 ASM_OUTPUT_DEBUG_ADDR (asm_out_file, TEXT_SECTION_ASM_OP);
|
|
967 if (flag_verbose_asm)
|
|
968 fprintf (asm_out_file, "\t%s line_num", ASM_COMMENT_START);
|
|
969 fputc ('\n', asm_out_file);
|
|
970 }
|
|
971
|
|
972 fn = line_info_table[1].dst_file_num;
|
|
973 ln = (file_info_table[fn].listing_line_start
|
|
974 + line_info_table[1].dst_line_num);
|
|
975 line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 4 + 4;
|
|
976 pcline.dst_b_pcline_command = DST_K_SET_LINUM_L;
|
|
977
|
|
978 totsize += write_debug_header (&line_num.dst_a_line_num_header,
|
|
979 "line_num", dosizeonly);
|
|
980 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
|
|
981 "line_num (SET LINUM LONG)", dosizeonly);
|
|
982
|
|
983 sprintf (buff, "line_num (%d)", ln ? ln - 1 : 0);
|
|
984 totsize += write_debug_data4 (ln ? ln - 1 : 0, buff, dosizeonly);
|
|
985
|
|
986 lastln = ln;
|
|
987 strcpy (lastlabel, TEXT_SECTION_ASM_OP);
|
|
988 for (i = 1; i < line_info_table_in_use; i++)
|
|
989 {
|
|
990 int extrabytes;
|
|
991
|
|
992 fn = line_info_table[i].dst_file_num;
|
|
993 ln = (file_info_table[fn].listing_line_start
|
|
994 + line_info_table[i].dst_line_num);
|
|
995
|
|
996 if (ln - lastln > 1)
|
|
997 extrabytes = 5; /* NUMBYTES (ln - lastln - 1) + 1; */
|
|
998 else if (ln <= lastln)
|
|
999 extrabytes = 5; /* NUMBYTES (ln - 1) + 1; */
|
|
1000 else
|
|
1001 extrabytes = 0;
|
|
1002
|
|
1003 line_num.dst_a_line_num_header.dst__header_length.dst_w_length
|
|
1004 = 8 + extrabytes;
|
|
1005
|
|
1006 totsize += write_debug_header
|
|
1007 (&line_num.dst_a_line_num_header, "line_num", dosizeonly);
|
|
1008
|
|
1009 if (ln - lastln > 1)
|
|
1010 {
|
|
1011 int lndif = ln - lastln - 1;
|
|
1012
|
|
1013 /* K_INCR_LINUM (lndif); */
|
|
1014 pcline.dst_b_pcline_command = DST_K_INCR_LINUM_L;
|
|
1015
|
|
1016 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
|
|
1017 "line_num (INCR LINUM LONG)",
|
|
1018 dosizeonly);
|
|
1019
|
|
1020 sprintf (buff, "line_num (%d)", lndif);
|
|
1021 totsize += write_debug_data4 (lndif, buff, dosizeonly);
|
|
1022 }
|
|
1023 else if (ln <= lastln)
|
|
1024 {
|
|
1025 /* K_SET_LINUM (ln-1); */
|
|
1026 pcline.dst_b_pcline_command = DST_K_SET_LINUM_L;
|
|
1027
|
|
1028 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
|
|
1029 "line_num (SET LINUM LONG)",
|
|
1030 dosizeonly);
|
|
1031
|
|
1032 sprintf (buff, "line_num (%d)", ln - 1);
|
|
1033 totsize += write_debug_data4 (ln - 1, buff, dosizeonly);
|
|
1034 }
|
|
1035
|
|
1036 pcline.dst_b_pcline_command = DST_K_DELTA_PC_L;
|
|
1037
|
|
1038 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
|
|
1039 "line_num (DELTA PC LONG)", dosizeonly);
|
|
1040
|
|
1041 ASM_GENERATE_INTERNAL_LABEL (label, LINE_CODE_LABEL, i);
|
|
1042 totsize += write_debug_delta4 (label, lastlabel, "increment line_num",
|
|
1043 dosizeonly);
|
|
1044
|
|
1045 lastln = ln;
|
|
1046 strcpy (lastlabel, label);
|
|
1047 }
|
|
1048
|
|
1049 return totsize;
|
|
1050 }
|
|
1051
|
|
1052 /* Output a source correlation for file FILEID using information saved in
|
|
1053 FILE_INFO_ENTRY and return the size. Just return the size if DOSIZEONLY is
|
|
1054 nonzero. */
|
|
1055
|
|
1056 static int
|
|
1057 write_srccorr (int fileid, dst_file_info_entry file_info_entry,
|
|
1058 int dosizeonly)
|
|
1059 {
|
|
1060 int src_command_size;
|
|
1061 int linesleft = file_info_entry.max_line;
|
|
1062 int linestart = file_info_entry.listing_line_start;
|
|
1063 int flen = file_info_entry.flen;
|
|
1064 int linestodo = 0;
|
|
1065 DST_SOURCE_CORR src_header;
|
|
1066 DST_SRC_COMMAND src_command;
|
|
1067 DST_SRC_COMMAND src_command_sf;
|
|
1068 DST_SRC_COMMAND src_command_sl;
|
|
1069 DST_SRC_COMMAND src_command_sr;
|
|
1070 DST_SRC_COMMAND src_command_dl;
|
|
1071 DST_SRC_CMDTRLR src_cmdtrlr;
|
|
1072 char buff[256];
|
|
1073 int totsize = 0;
|
|
1074
|
|
1075 if (fileid == 1)
|
|
1076 {
|
|
1077 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
|
|
1078 = DST_K_SOURCE_CORR_HEADER_SIZE + 1 - 1;
|
|
1079 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
|
|
1080 = DST_K_SOURCE;
|
|
1081 src_command.dst_b_src_command = DST_K_SRC_FORMFEED;
|
|
1082
|
|
1083 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
|
|
1084 "source corr", dosizeonly);
|
|
1085
|
|
1086 totsize += write_debug_data1 (src_command.dst_b_src_command,
|
|
1087 "source_corr (SRC FORMFEED)",
|
|
1088 dosizeonly);
|
|
1089 }
|
|
1090
|
|
1091 src_command_size
|
|
1092 = DST_K_SRC_COMMAND_SIZE + flen + DST_K_SRC_CMDTRLR_SIZE;
|
|
1093 src_command.dst_b_src_command = DST_K_SRC_DECLFILE;
|
|
1094 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_length
|
|
1095 = src_command_size - 2;
|
|
1096 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_flags = 0;
|
|
1097 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_fileid
|
|
1098 = fileid;
|
|
1099 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt
|
|
1100 = file_info_entry.cdt;
|
|
1101 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk
|
|
1102 = file_info_entry.ebk;
|
|
1103 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_rms_ffb
|
|
1104 = file_info_entry.ffb;
|
|
1105 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_rms_rfo
|
|
1106 = file_info_entry.rfo;
|
|
1107 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename
|
|
1108 = file_info_entry.flen;
|
|
1109
|
|
1110 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
|
|
1111 = DST_K_SOURCE_CORR_HEADER_SIZE + src_command_size - 1;
|
|
1112 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
|
|
1113 = DST_K_SOURCE;
|
|
1114
|
|
1115 src_cmdtrlr.dst_b_src_df_libmodname = 0;
|
|
1116
|
|
1117 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
|
|
1118 "source corr", dosizeonly);
|
|
1119 totsize += write_debug_data1 (src_command.dst_b_src_command,
|
|
1120 "source_corr (DECL SRC FILE)", dosizeonly);
|
|
1121 totsize += write_debug_data1
|
|
1122 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_length,
|
|
1123 "source_corr (length)", dosizeonly);
|
|
1124
|
|
1125 totsize += write_debug_data1
|
|
1126 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_flags,
|
|
1127 "source_corr (flags)", dosizeonly);
|
|
1128
|
|
1129 totsize += write_debug_data2
|
|
1130 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_fileid,
|
|
1131 "source_corr (fileid)", dosizeonly);
|
|
1132
|
|
1133 totsize += write_debug_data8
|
|
1134 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt,
|
|
1135 "source_corr (creation date)", dosizeonly);
|
|
1136
|
|
1137 totsize += write_debug_data4
|
|
1138 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk,
|
|
1139 "source_corr (EOF block number)", dosizeonly);
|
|
1140
|
|
1141 totsize += write_debug_data2
|
|
1142 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_rms_ffb,
|
|
1143 "source_corr (first free byte)", dosizeonly);
|
|
1144
|
|
1145 totsize += write_debug_data1
|
|
1146 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_rms_rfo,
|
|
1147 "source_corr (record and file organization)", dosizeonly);
|
|
1148
|
|
1149 totsize += write_debug_data1
|
|
1150 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename,
|
|
1151 "source_corr (filename length)", dosizeonly);
|
|
1152
|
|
1153 totsize += write_debug_string (remap_debug_filename (
|
|
1154 file_info_entry.file_name),
|
|
1155 "source file name", dosizeonly);
|
|
1156 totsize += write_debug_data1 (src_cmdtrlr.dst_b_src_df_libmodname,
|
|
1157 "source_corr (libmodname)", dosizeonly);
|
|
1158
|
|
1159 src_command_sf.dst_b_src_command = DST_K_SRC_SETFILE;
|
|
1160 src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword = fileid;
|
|
1161
|
|
1162 src_command_sr.dst_b_src_command = DST_K_SRC_SETREC_W;
|
|
1163 src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword = 1;
|
|
1164
|
|
1165 src_command_sl.dst_b_src_command = DST_K_SRC_SETLNUM_L;
|
|
1166 src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong = linestart + 1;
|
|
1167
|
|
1168 src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W;
|
|
1169
|
|
1170 if (linesleft > 65534)
|
|
1171 linesleft = linesleft - 65534, linestodo = 65534;
|
|
1172 else
|
|
1173 linestodo = linesleft, linesleft = 0;
|
|
1174
|
|
1175 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo;
|
|
1176
|
|
1177 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
|
|
1178 = DST_K_SOURCE_CORR_HEADER_SIZE + 3 + 3 + 5 + 3 - 1;
|
|
1179 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
|
|
1180 = DST_K_SOURCE;
|
|
1181
|
|
1182 if (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword)
|
|
1183 {
|
|
1184 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
|
|
1185 "source corr", dosizeonly);
|
|
1186
|
|
1187 totsize += write_debug_data1 (src_command_sf.dst_b_src_command,
|
|
1188 "source_corr (src setfile)", dosizeonly);
|
|
1189
|
|
1190 totsize += write_debug_data2
|
|
1191 (src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword,
|
|
1192 "source_corr (fileid)", dosizeonly);
|
|
1193
|
|
1194 totsize += write_debug_data1 (src_command_sr.dst_b_src_command,
|
|
1195 "source_corr (setrec)", dosizeonly);
|
|
1196
|
|
1197 totsize += write_debug_data2
|
|
1198 (src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword,
|
|
1199 "source_corr (recnum)", dosizeonly);
|
|
1200
|
|
1201 totsize += write_debug_data1 (src_command_sl.dst_b_src_command,
|
|
1202 "source_corr (setlnum)", dosizeonly);
|
|
1203
|
|
1204 totsize += write_debug_data4
|
|
1205 (src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong,
|
|
1206 "source_corr (linenum)", dosizeonly);
|
|
1207
|
|
1208 totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
|
|
1209 "source_corr (deflines)", dosizeonly);
|
|
1210
|
|
1211 sprintf (buff, "source_corr (%d)",
|
|
1212 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
|
|
1213 totsize += write_debug_data2
|
|
1214 (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword,
|
|
1215 buff, dosizeonly);
|
|
1216
|
|
1217 while (linesleft > 0)
|
|
1218 {
|
|
1219 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
|
|
1220 = DST_K_SOURCE_CORR_HEADER_SIZE + 3 - 1;
|
|
1221 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
|
|
1222 = DST_K_SOURCE;
|
|
1223 src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W;
|
|
1224
|
|
1225 if (linesleft > 65534)
|
|
1226 linesleft = linesleft - 65534, linestodo = 65534;
|
|
1227 else
|
|
1228 linestodo = linesleft, linesleft = 0;
|
|
1229
|
|
1230 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo;
|
|
1231
|
|
1232 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
|
|
1233 "source corr", dosizeonly);
|
|
1234 totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
|
|
1235 "source_corr (deflines)", dosizeonly);
|
|
1236 sprintf (buff, "source_corr (%d)",
|
|
1237 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
|
|
1238 totsize += write_debug_data2
|
|
1239 (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword,
|
|
1240 buff, dosizeonly);
|
|
1241 }
|
|
1242 }
|
|
1243
|
|
1244 return totsize;
|
|
1245 }
|
|
1246
|
|
1247 /* Output all the source correlation entries and return the size. Just return
|
|
1248 the size if DOSIZEONLY is nonzero. */
|
|
1249
|
|
1250 static int
|
|
1251 write_srccorrs (int dosizeonly)
|
|
1252 {
|
|
1253 unsigned int i;
|
|
1254 int totsize = 0;
|
|
1255
|
|
1256 for (i = 1; i < file_info_table_in_use; i++)
|
|
1257 totsize += write_srccorr (i, file_info_table[i], dosizeonly);
|
|
1258
|
|
1259 return totsize;
|
|
1260 }
|
|
1261
|
|
1262 /* Output a marker (i.e. a label) for the beginning of a function, before
|
|
1263 the prologue. */
|
|
1264
|
|
1265 static void
|
|
1266 vmsdbgout_begin_prologue (unsigned int line, const char *file)
|
|
1267 {
|
|
1268 char label[MAX_ARTIFICIAL_LABEL_BYTES];
|
|
1269
|
|
1270 if (write_symbols == VMS_AND_DWARF2_DEBUG)
|
|
1271 (*dwarf2_debug_hooks.begin_prologue) (line, file);
|
|
1272
|
|
1273 if (debug_info_level > DINFO_LEVEL_NONE)
|
|
1274 {
|
|
1275 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL,
|
|
1276 current_function_funcdef_no);
|
|
1277 ASM_OUTPUT_LABEL (asm_out_file, label);
|
|
1278 }
|
|
1279 }
|
|
1280
|
|
1281 /* Output a marker (i.e. a label) for the beginning of a function, after
|
|
1282 the prologue. */
|
|
1283
|
|
1284 static void
|
|
1285 vmsdbgout_end_prologue (unsigned int line, const char *file)
|
|
1286 {
|
|
1287 char label[MAX_ARTIFICIAL_LABEL_BYTES];
|
|
1288
|
|
1289 if (write_symbols == VMS_AND_DWARF2_DEBUG)
|
|
1290 (*dwarf2_debug_hooks.end_prologue) (line, file);
|
|
1291
|
|
1292 if (debug_info_level > DINFO_LEVEL_TERSE)
|
|
1293 {
|
|
1294 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL,
|
|
1295 current_function_funcdef_no);
|
|
1296 ASM_OUTPUT_LABEL (asm_out_file, label);
|
|
1297
|
|
1298 /* VMS PCA expects every PC range to correlate to some line and file. */
|
|
1299 vmsdbgout_source_line (line, file);
|
|
1300 }
|
|
1301 }
|
|
1302
|
|
1303 /* No output for VMS debug, but make obligatory call to Dwarf2 debug */
|
|
1304
|
|
1305 static void
|
|
1306 vmsdbgout_end_function (unsigned int line)
|
|
1307 {
|
|
1308 if (write_symbols == VMS_AND_DWARF2_DEBUG)
|
|
1309 (*dwarf2_debug_hooks.end_function) (line);
|
|
1310 }
|
|
1311
|
|
1312 /* Output a marker (i.e. a label) for the absolute end of the generated code
|
|
1313 for a function definition. This gets called *after* the epilogue code has
|
|
1314 been generated. */
|
|
1315
|
|
1316 static void
|
|
1317 vmsdbgout_end_epilogue (unsigned int line, const char *file)
|
|
1318 {
|
|
1319 char label[MAX_ARTIFICIAL_LABEL_BYTES];
|
|
1320
|
|
1321 if (write_symbols == VMS_AND_DWARF2_DEBUG)
|
|
1322 (*dwarf2_debug_hooks.end_epilogue) (line, file);
|
|
1323
|
|
1324 if (debug_info_level > DINFO_LEVEL_NONE)
|
|
1325 {
|
|
1326 /* Output a label to mark the endpoint of the code generated for this
|
|
1327 function. */
|
|
1328 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL,
|
|
1329 current_function_funcdef_no);
|
|
1330 ASM_OUTPUT_LABEL (asm_out_file, label);
|
|
1331
|
|
1332 /* VMS PCA expects every PC range to correlate to some line and file. */
|
|
1333 vmsdbgout_source_line (line, file);
|
|
1334 }
|
|
1335 }
|
|
1336
|
|
1337 /* Output a marker (i.e. a label) for the beginning of the generated code for
|
|
1338 a lexical block. */
|
|
1339
|
|
1340 static void
|
|
1341 vmsdbgout_begin_block (register unsigned line, register unsigned blocknum)
|
|
1342 {
|
|
1343 if (write_symbols == VMS_AND_DWARF2_DEBUG)
|
|
1344 (*dwarf2_debug_hooks.begin_block) (line, blocknum);
|
|
1345
|
|
1346 if (debug_info_level > DINFO_LEVEL_TERSE)
|
|
1347 targetm.asm_out.internal_label (asm_out_file, BLOCK_BEGIN_LABEL, blocknum);
|
|
1348 }
|
|
1349
|
|
1350 /* Output a marker (i.e. a label) for the end of the generated code for a
|
|
1351 lexical block. */
|
|
1352
|
|
1353 static void
|
|
1354 vmsdbgout_end_block (register unsigned line, register unsigned blocknum)
|
|
1355 {
|
|
1356 if (write_symbols == VMS_AND_DWARF2_DEBUG)
|
|
1357 (*dwarf2_debug_hooks.end_block) (line, blocknum);
|
|
1358
|
|
1359 if (debug_info_level > DINFO_LEVEL_TERSE)
|
|
1360 targetm.asm_out.internal_label (asm_out_file, BLOCK_END_LABEL, blocknum);
|
|
1361 }
|
|
1362
|
|
1363 /* Not implemented in VMS Debug. */
|
|
1364
|
|
1365 static bool
|
|
1366 vmsdbgout_ignore_block (const_tree block)
|
|
1367 {
|
|
1368 bool retval = 0;
|
|
1369
|
|
1370 if (write_symbols == VMS_AND_DWARF2_DEBUG)
|
|
1371 retval = (*dwarf2_debug_hooks.ignore_block) (block);
|
|
1372
|
|
1373 return retval;
|
|
1374 }
|
|
1375
|
|
1376 /* Add an entry for function DECL into the func_table. */
|
|
1377
|
|
1378 static void
|
|
1379 vmsdbgout_begin_function (tree decl)
|
|
1380 {
|
|
1381 const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
|
|
1382 vms_func_ref fde;
|
|
1383
|
|
1384 if (write_symbols == VMS_AND_DWARF2_DEBUG)
|
|
1385 (*dwarf2_debug_hooks.begin_function) (decl);
|
|
1386
|
|
1387 if (func_table_in_use == func_table_allocated)
|
|
1388 {
|
|
1389 func_table_allocated += FUNC_TABLE_INCREMENT;
|
|
1390 func_table
|
|
1391 = (vms_func_ref) xrealloc (func_table,
|
|
1392 func_table_allocated * sizeof (vms_func_node));
|
|
1393 }
|
|
1394
|
|
1395 /* Add the new entry to the end of the function name table. */
|
|
1396 fde = &func_table[func_table_in_use++];
|
|
1397 fde->vms_func_name = xstrdup (name);
|
|
1398 fde->funcdef_number = current_function_funcdef_no;
|
|
1399
|
|
1400 }
|
|
1401
|
|
1402 static char fullname_buff [4096];
|
|
1403
|
|
1404 /* Return the full file specification for FILENAME. The specification must be
|
|
1405 in VMS syntax in order to be processed by VMS Debug. */
|
|
1406
|
|
1407 static char *
|
|
1408 full_name (const char *filename)
|
|
1409 {
|
|
1410 #ifdef VMS
|
|
1411 FILE *fp = fopen (filename, "r");
|
|
1412
|
|
1413 fgetname (fp, fullname_buff, 1);
|
|
1414 fclose (fp);
|
|
1415 #else
|
|
1416 getcwd (fullname_buff, sizeof (fullname_buff));
|
|
1417
|
|
1418 strcat (fullname_buff, "/");
|
|
1419 strcat (fullname_buff, filename);
|
|
1420
|
|
1421 /* ??? Insert hairy code here to translate Unix style file specification
|
|
1422 to VMS style. */
|
|
1423 #endif
|
|
1424
|
|
1425 return fullname_buff;
|
|
1426 }
|
|
1427
|
|
1428 /* Lookup a filename (in the list of filenames that we know about here in
|
|
1429 vmsdbgout.c) and return its "index". The index of each (known) filename is
|
|
1430 just a unique number which is associated with only that one filename. We
|
|
1431 need such numbers for the sake of generating labels and references
|
|
1432 to those files numbers. If the filename given as an argument is not
|
|
1433 found in our current list, add it to the list and assign it the next
|
|
1434 available unique index number. In order to speed up searches, we remember
|
|
1435 the index of the filename was looked up last. This handles the majority of
|
|
1436 all searches. */
|
|
1437
|
|
1438 static unsigned int
|
|
1439 lookup_filename (const char *file_name)
|
|
1440 {
|
|
1441 static unsigned int last_file_lookup_index = 0;
|
|
1442 register char *fn;
|
|
1443 register unsigned i;
|
|
1444 const char *fnam;
|
|
1445 long long cdt;
|
|
1446 long ebk;
|
|
1447 short ffb;
|
|
1448 char rfo;
|
|
1449 char flen;
|
|
1450 struct stat statbuf;
|
|
1451
|
|
1452 if (stat (file_name, &statbuf) == 0)
|
|
1453 {
|
|
1454 long gmtoff;
|
|
1455 #ifdef VMS
|
|
1456 struct tm *ts;
|
|
1457
|
|
1458 /* Adjust for GMT. */
|
|
1459 ts = (struct tm *) localtime (&statbuf.st_ctime);
|
|
1460 gmtoff = ts->tm_gmtoff;
|
|
1461
|
|
1462 /* VMS has multiple file format types. */
|
|
1463 rfo = statbuf.st_fab_rfm;
|
|
1464 #else
|
|
1465 /* Is GMT adjustment an issue with a cross-compiler? */
|
|
1466 gmtoff = 0;
|
|
1467
|
|
1468 /* Assume stream LF type file. */
|
|
1469 rfo = 2;
|
|
1470 #endif
|
|
1471 cdt = 10000000 * (statbuf.st_ctime + gmtoff + vms_epoch_offset);
|
|
1472 ebk = statbuf.st_size / 512 + 1;
|
|
1473 ffb = statbuf.st_size - ((statbuf.st_size / 512) * 512);
|
|
1474 fnam = full_name (file_name);
|
|
1475 flen = strlen (fnam);
|
|
1476 }
|
|
1477 else
|
|
1478 {
|
|
1479 cdt = 0;
|
|
1480 ebk = 0;
|
|
1481 ffb = 0;
|
|
1482 rfo = 0;
|
|
1483 fnam = "";
|
|
1484 flen = 0;
|
|
1485 }
|
|
1486
|
|
1487 /* Check to see if the file name that was searched on the previous call
|
|
1488 matches this file name. If so, return the index. */
|
|
1489 if (last_file_lookup_index != 0)
|
|
1490 {
|
|
1491 fn = file_info_table[last_file_lookup_index].file_name;
|
|
1492 if (strcmp (fnam, fn) == 0)
|
|
1493 return last_file_lookup_index;
|
|
1494 }
|
|
1495
|
|
1496 /* Didn't match the previous lookup, search the table */
|
|
1497 for (i = 1; i < file_info_table_in_use; ++i)
|
|
1498 {
|
|
1499 fn = file_info_table[i].file_name;
|
|
1500 if (strcmp (fnam, fn) == 0)
|
|
1501 {
|
|
1502 last_file_lookup_index = i;
|
|
1503 return i;
|
|
1504 }
|
|
1505 }
|
|
1506
|
|
1507 /* Prepare to add a new table entry by making sure there is enough space in
|
|
1508 the table to do so. If not, expand the current table. */
|
|
1509 if (file_info_table_in_use == file_info_table_allocated)
|
|
1510 {
|
|
1511
|
|
1512 file_info_table_allocated += FILE_TABLE_INCREMENT;
|
|
1513 file_info_table = XRESIZEVEC (dst_file_info_entry, file_info_table,
|
|
1514 file_info_table_allocated);
|
|
1515 }
|
|
1516
|
|
1517 /* Add the new entry to the end of the filename table. */
|
|
1518 file_info_table[file_info_table_in_use].file_name = xstrdup (fnam);
|
|
1519 file_info_table[file_info_table_in_use].max_line = 0;
|
|
1520 file_info_table[file_info_table_in_use].cdt = cdt;
|
|
1521 file_info_table[file_info_table_in_use].ebk = ebk;
|
|
1522 file_info_table[file_info_table_in_use].ffb = ffb;
|
|
1523 file_info_table[file_info_table_in_use].rfo = rfo;
|
|
1524 file_info_table[file_info_table_in_use].flen = flen;
|
|
1525
|
|
1526 last_file_lookup_index = file_info_table_in_use++;
|
|
1527 return last_file_lookup_index;
|
|
1528 }
|
|
1529
|
|
1530 /* Output a label to mark the beginning of a source code line entry
|
|
1531 and record information relating to this source line, in
|
|
1532 'line_info_table' for later output of the .debug_line section. */
|
|
1533
|
|
1534 static void
|
|
1535 vmsdbgout_source_line (register unsigned line, register const char *filename)
|
|
1536 {
|
|
1537 if (write_symbols == VMS_AND_DWARF2_DEBUG)
|
|
1538 (*dwarf2_debug_hooks.source_line) (line, filename);
|
|
1539
|
|
1540 if (debug_info_level >= DINFO_LEVEL_TERSE)
|
|
1541 {
|
|
1542 dst_line_info_ref line_info;
|
|
1543
|
|
1544 targetm.asm_out.internal_label (asm_out_file, LINE_CODE_LABEL,
|
|
1545 line_info_table_in_use);
|
|
1546
|
|
1547 /* Expand the line info table if necessary. */
|
|
1548 if (line_info_table_in_use == line_info_table_allocated)
|
|
1549 {
|
|
1550 line_info_table_allocated += LINE_INFO_TABLE_INCREMENT;
|
|
1551 line_info_table = XRESIZEVEC (dst_line_info_entry, line_info_table,
|
|
1552 line_info_table_allocated);
|
|
1553 }
|
|
1554
|
|
1555 /* Add the new entry at the end of the line_info_table. */
|
|
1556 line_info = &line_info_table[line_info_table_in_use++];
|
|
1557 line_info->dst_file_num = lookup_filename (filename);
|
|
1558 line_info->dst_line_num = line;
|
|
1559 if (line > file_info_table[line_info->dst_file_num].max_line)
|
|
1560 file_info_table[line_info->dst_file_num].max_line = line;
|
|
1561 }
|
|
1562 }
|
|
1563
|
|
1564 /* Record the beginning of a new source file, for later output.
|
|
1565 At present, unimplemented. */
|
|
1566
|
|
1567 static void
|
|
1568 vmsdbgout_start_source_file (unsigned int lineno, const char *filename)
|
|
1569 {
|
|
1570 if (write_symbols == VMS_AND_DWARF2_DEBUG)
|
|
1571 (*dwarf2_debug_hooks.start_source_file) (lineno, filename);
|
|
1572 }
|
|
1573
|
|
1574 /* Record the end of a source file, for later output.
|
|
1575 At present, unimplemented. */
|
|
1576
|
|
1577 static void
|
|
1578 vmsdbgout_end_source_file (unsigned int lineno ATTRIBUTE_UNUSED)
|
|
1579 {
|
|
1580 if (write_symbols == VMS_AND_DWARF2_DEBUG)
|
|
1581 (*dwarf2_debug_hooks.end_source_file) (lineno);
|
|
1582 }
|
|
1583
|
|
1584 /* Set up for Debug output at the start of compilation. */
|
|
1585
|
|
1586 static void
|
|
1587 vmsdbgout_init (const char *main_input_filename)
|
|
1588 {
|
|
1589 const char *language_string = lang_hooks.name;
|
|
1590
|
|
1591 if (write_symbols == VMS_AND_DWARF2_DEBUG)
|
|
1592 (*dwarf2_debug_hooks.init) (main_input_filename);
|
|
1593
|
|
1594 if (debug_info_level == DINFO_LEVEL_NONE)
|
|
1595 return;
|
|
1596
|
|
1597 /* Remember the name of the primary input file. */
|
|
1598 primary_filename = main_input_filename;
|
|
1599
|
|
1600 /* Allocate the initial hunk of the file_info_table. */
|
|
1601 file_info_table = XCNEWVEC (dst_file_info_entry, FILE_TABLE_INCREMENT);
|
|
1602 file_info_table_allocated = FILE_TABLE_INCREMENT;
|
|
1603
|
|
1604 /* Skip the first entry - file numbers begin at 1 */
|
|
1605 file_info_table_in_use = 1;
|
|
1606
|
|
1607 func_table = (vms_func_ref) xcalloc (FUNC_TABLE_INCREMENT, sizeof (vms_func_node));
|
|
1608 func_table_allocated = FUNC_TABLE_INCREMENT;
|
|
1609 func_table_in_use = 1;
|
|
1610
|
|
1611 /* Allocate the initial hunk of the line_info_table. */
|
|
1612 line_info_table = XCNEWVEC (dst_line_info_entry, LINE_INFO_TABLE_INCREMENT);
|
|
1613 line_info_table_allocated = LINE_INFO_TABLE_INCREMENT;
|
|
1614 /* zero-th entry is allocated, but unused */
|
|
1615 line_info_table_in_use = 1;
|
|
1616
|
|
1617 lookup_filename (primary_filename);
|
|
1618
|
|
1619 if (!strcmp (language_string, "GNU C"))
|
|
1620 module_language = DST_K_C;
|
|
1621 else if (!strcmp (language_string, "GNU C++"))
|
|
1622 module_language = DST_K_CXX;
|
|
1623 else if (!strcmp (language_string, "GNU Ada"))
|
|
1624 module_language = DST_K_ADA;
|
|
1625 else if (!strcmp (language_string, "GNU F77"))
|
|
1626 module_language = DST_K_FORTRAN;
|
|
1627 else
|
|
1628 module_language = DST_K_UNKNOWN;
|
|
1629
|
|
1630 module_producer = concat (language_string, " ", version_string, NULL);
|
|
1631
|
|
1632 ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
|
|
1633
|
|
1634 }
|
|
1635
|
|
1636 /* Not implemented in VMS Debug. */
|
|
1637
|
|
1638 static void
|
|
1639 vmsdbgout_define (unsigned int lineno, const char *buffer)
|
|
1640 {
|
|
1641 if (write_symbols == VMS_AND_DWARF2_DEBUG)
|
|
1642 (*dwarf2_debug_hooks.define) (lineno, buffer);
|
|
1643 }
|
|
1644
|
|
1645 /* Not implemented in VMS Debug. */
|
|
1646
|
|
1647 static void
|
|
1648 vmsdbgout_undef (unsigned int lineno, const char *buffer)
|
|
1649 {
|
|
1650 if (write_symbols == VMS_AND_DWARF2_DEBUG)
|
|
1651 (*dwarf2_debug_hooks.undef) (lineno, buffer);
|
|
1652 }
|
|
1653
|
|
1654 /* Not implemented in VMS Debug. */
|
|
1655
|
|
1656 static void
|
|
1657 vmsdbgout_decl (tree decl)
|
|
1658 {
|
|
1659 if (write_symbols == VMS_AND_DWARF2_DEBUG)
|
|
1660 (*dwarf2_debug_hooks.function_decl) (decl);
|
|
1661 }
|
|
1662
|
|
1663 /* Not implemented in VMS Debug. */
|
|
1664
|
|
1665 static void
|
|
1666 vmsdbgout_global_decl (tree decl)
|
|
1667 {
|
|
1668 if (write_symbols == VMS_AND_DWARF2_DEBUG)
|
|
1669 (*dwarf2_debug_hooks.global_decl) (decl);
|
|
1670 }
|
|
1671
|
|
1672 /* Not implemented in VMS Debug. */
|
|
1673
|
|
1674 static void
|
|
1675 vmsdbgout_abstract_function (tree decl)
|
|
1676 {
|
|
1677 if (write_symbols == VMS_AND_DWARF2_DEBUG)
|
|
1678 (*dwarf2_debug_hooks.outlining_inline_function) (decl);
|
|
1679 }
|
|
1680
|
|
1681 /* Output stuff that Debug requires at the end of every file and generate the
|
|
1682 VMS Debug debugging info. */
|
|
1683
|
|
1684 static void
|
|
1685 vmsdbgout_finish (const char *main_input_filename ATTRIBUTE_UNUSED)
|
|
1686 {
|
|
1687 unsigned int i;
|
|
1688 int totsize;
|
|
1689
|
|
1690 if (write_symbols == VMS_AND_DWARF2_DEBUG)
|
|
1691 (*dwarf2_debug_hooks.finish) (main_input_filename);
|
|
1692
|
|
1693 if (debug_info_level == DINFO_LEVEL_NONE)
|
|
1694 return;
|
|
1695
|
|
1696 /* Output a terminator label for the .text section. */
|
|
1697 switch_to_section (text_section);
|
|
1698 targetm.asm_out.internal_label (asm_out_file, TEXT_END_LABEL, 0);
|
|
1699
|
|
1700 /* Output debugging information.
|
|
1701 Warning! Do not change the name of the .vmsdebug section without
|
|
1702 changing it in the assembler also. */
|
|
1703 switch_to_section (get_named_section (NULL, ".vmsdebug", 0));
|
|
1704 ASM_OUTPUT_ALIGN (asm_out_file, 0);
|
|
1705
|
|
1706 totsize = write_modbeg (1);
|
|
1707 for (i = 1; i < func_table_in_use; i++)
|
|
1708 {
|
|
1709 totsize += write_rtnbeg (i, 1);
|
|
1710 totsize += write_rtnend (i, 1);
|
|
1711 }
|
|
1712 totsize += write_pclines (1);
|
|
1713
|
|
1714 write_modbeg (0);
|
|
1715 for (i = 1; i < func_table_in_use; i++)
|
|
1716 {
|
|
1717 write_rtnbeg (i, 0);
|
|
1718 write_rtnend (i, 0);
|
|
1719 }
|
|
1720 write_pclines (0);
|
|
1721
|
|
1722 if (debug_info_level > DINFO_LEVEL_TERSE)
|
|
1723 {
|
|
1724 totsize = write_srccorrs (1);
|
|
1725 write_srccorrs (0);
|
|
1726 }
|
|
1727
|
|
1728 totsize = write_modend (1);
|
|
1729 write_modend (0);
|
|
1730 }
|
|
1731 #endif /* VMS_DEBUGGING_INFO */
|