Merge from mainline (165734:167278).
[official-gcc/graphite-test-results.git] / gcc / vmsdbgout.c
blob2278d1ab30d6b07aefaf3f7f3d789bf132c1cb28
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, 2009, 2010
4 Free Software Foundation, Inc.
5 Contributed by Douglas B. Rupp (rupp@gnat.com).
6 Updated by Bernard W. Giroud (bgiroud@users.sourceforge.net).
8 This file is part of GCC.
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.
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.
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/>. */
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tm.h"
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"
41 /* Difference in seconds between the VMS Epoch and the Unix Epoch */
42 static const long long vms_epoch_offset = 3506716800ll;
44 int vms_file_stats_name (const char *, long long *, long *, char *, int *);
46 /* NOTE: In the comments in this file, many references are made to "Debug
47 Symbol Table". This term is abbreviated as `DST' throughout the remainder
48 of this file. */
50 typedef struct dst_line_info_struct *dst_line_info_ref;
52 /* Each entry in the line_info_table maintains the file and
53 line number associated with the label generated for that
54 entry. The label gives the PC value associated with
55 the line number entry. */
56 typedef struct dst_line_info_struct
58 unsigned long dst_file_num;
59 unsigned long dst_line_num;
61 dst_line_info_entry;
63 typedef struct dst_file_info_struct *dst_file_info_ref;
65 typedef struct dst_file_info_struct
67 char *file_name;
68 unsigned int max_line;
69 unsigned int listing_line_start;
70 long long cdt;
71 long ebk;
72 short ffb;
73 char rfo;
74 char flen;
76 dst_file_info_entry;
78 /* How to start an assembler comment. */
79 #ifndef ASM_COMMENT_START
80 #define ASM_COMMENT_START ";#"
81 #endif
83 /* Maximum size (in bytes) of an artificially generated label. */
84 #define MAX_ARTIFICIAL_LABEL_BYTES 30
86 /* Make sure we know the sizes of the various types debug can describe. These
87 are only defaults. If the sizes are different for your target, you should
88 override these values by defining the appropriate symbols in your tm.h
89 file. */
90 #ifndef PTR_SIZE
91 #define PTR_SIZE 4 /* Must be 32 bits for VMS debug info */
92 #endif
94 /* Pointer to a structure of filenames referenced by this compilation unit. */
95 static dst_file_info_ref file_info_table;
97 /* Total number of entries in the table (i.e. array) pointed to by
98 `file_info_table'. This is the *total* and includes both used and unused
99 slots. */
100 static unsigned int file_info_table_allocated;
102 /* Number of entries in the file_info_table which are actually in use. */
103 static unsigned int file_info_table_in_use;
105 /* Size (in elements) of increments by which we may expand the filename
106 table. */
107 #define FILE_TABLE_INCREMENT 64
109 typedef char *char_p;
110 DEF_VEC_P(char_p);
111 DEF_VEC_ALLOC_P(char_p,heap);
113 static VEC(char_p,heap) *funcnam_table;
114 static VEC(unsigned,heap) *funcnum_table;
115 #define FUNC_TABLE_INITIAL 256
117 /* Local pointer to the name of the main input file. Initialized in
118 vmsdbgout_init. */
119 static const char *primary_filename;
121 static char *module_producer;
122 static unsigned int module_language;
124 /* A pointer to the base of a table that contains line information
125 for each source code line in .text in the compilation unit. */
126 static dst_line_info_ref line_info_table;
128 /* Number of elements currently allocated for line_info_table. */
129 static unsigned int line_info_table_allocated;
131 /* Number of elements in line_info_table currently in use. */
132 static unsigned int line_info_table_in_use;
134 /* Size (in elements) of increments by which we may expand line_info_table. */
135 #define LINE_INFO_TABLE_INCREMENT 1024
137 /* Forward declarations for functions defined in this file. */
138 static char *full_name (const char *);
139 static unsigned int lookup_filename (const char *);
140 static int write_debug_header (DST_HEADER *, const char *, int);
141 static int write_debug_addr (const char *, const char *, int);
142 static int write_debug_data1 (unsigned int, const char *, int);
143 static int write_debug_data2 (unsigned int, const char *, int);
144 static int write_debug_data4 (unsigned long, const char *, int);
145 static int write_debug_data8 (unsigned long long, const char *, int);
146 static int write_debug_delta4 (const char *, const char *, const char *, int);
147 static int write_debug_string (const char *, const char *, int);
148 static int write_modbeg (int);
149 static int write_modend (int);
150 static int write_rtnbeg (int, int);
151 static int write_rtnend (int, int);
152 static int write_pclines (int);
153 static int write_srccorr (int, dst_file_info_entry, int);
154 static int write_srccorrs (int);
156 static void vmsdbgout_init (const char *);
157 static void vmsdbgout_finish (const char *);
158 static void vmsdbgout_assembly_start (void);
159 static void vmsdbgout_define (unsigned int, const char *);
160 static void vmsdbgout_undef (unsigned int, const char *);
161 static void vmsdbgout_start_source_file (unsigned int, const char *);
162 static void vmsdbgout_end_source_file (unsigned int);
163 static void vmsdbgout_begin_block (unsigned int, unsigned int);
164 static void vmsdbgout_end_block (unsigned int, unsigned int);
165 static bool vmsdbgout_ignore_block (const_tree);
166 static void vmsdbgout_source_line (unsigned int, const char *, int, bool);
167 static void vmsdbgout_begin_prologue (unsigned int, const char *);
168 static void vmsdbgout_end_prologue (unsigned int, const char *);
169 static void vmsdbgout_end_function (unsigned int);
170 static void vmsdbgout_begin_epilogue (unsigned int, const char *);
171 static void vmsdbgout_end_epilogue (unsigned int, const char *);
172 static void vmsdbgout_begin_function (tree);
173 static void vmsdbgout_decl (tree);
174 static void vmsdbgout_global_decl (tree);
175 static void vmsdbgout_type_decl (tree, int);
176 static void vmsdbgout_abstract_function (tree);
178 /* The debug hooks structure. */
180 const struct gcc_debug_hooks vmsdbg_debug_hooks
181 = {vmsdbgout_init,
182 vmsdbgout_finish,
183 vmsdbgout_assembly_start,
184 vmsdbgout_define,
185 vmsdbgout_undef,
186 vmsdbgout_start_source_file,
187 vmsdbgout_end_source_file,
188 vmsdbgout_begin_block,
189 vmsdbgout_end_block,
190 vmsdbgout_ignore_block,
191 vmsdbgout_source_line,
192 vmsdbgout_begin_prologue,
193 vmsdbgout_end_prologue,
194 vmsdbgout_begin_epilogue,
195 vmsdbgout_end_epilogue,
196 vmsdbgout_begin_function,
197 vmsdbgout_end_function,
198 vmsdbgout_decl,
199 vmsdbgout_global_decl,
200 vmsdbgout_type_decl, /* type_decl */
201 debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */
202 debug_nothing_tree, /* deferred_inline_function */
203 vmsdbgout_abstract_function,
204 debug_nothing_rtx, /* label */
205 debug_nothing_int, /* handle_pch */
206 debug_nothing_rtx, /* var_location */
207 debug_nothing_void, /* switch_text_section */
208 debug_nothing_tree, /* direct_call */
209 debug_nothing_tree_int, /* virtual_call_token */
210 debug_nothing_rtx_rtx, /* copy_call_info */
211 debug_nothing_uid, /* virtual_call */
212 debug_nothing_tree_tree, /* set_name */
213 0, /* start_end_main_source_file */
214 TYPE_SYMTAB_IS_ADDRESS /* tree_type_symtab_field */
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"
226 #ifdef UNALIGNED_INT_ASM_OP
227 #undef UNALIGNED_INT_ASM_OP
228 #endif
229 #define UNALIGNED_INT_ASM_OP ".long"
231 #ifdef UNALIGNED_LONG_ASM_OP
232 #undef UNALIGNED_LONG_ASM_OP
233 #endif
234 #define UNALIGNED_LONG_ASM_OP ".long"
236 #ifdef UNALIGNED_DOUBLE_INT_ASM_OP
237 #undef UNALIGNED_DOUBLE_INT_ASM_OP
238 #endif
239 #define UNALIGNED_DOUBLE_INT_ASM_OP ".quad"
241 #ifdef ASM_BYTE_OP
242 #undef ASM_BYTE_OP
243 #endif
244 #define ASM_BYTE_OP ".byte"
246 #define NUMBYTES(I) ((I) < 256 ? 1 : (I) < 65536 ? 2 : 4)
248 #define NUMBYTES0(I) ((I) < 128 ? 0 : (I) < 65536 ? 2 : 4)
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
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
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. */
268 static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
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_EPILOG_LABEL
280 #define FUNC_EPILOG_LABEL "LVEB"
281 #endif
282 #ifndef FUNC_END_LABEL
283 #define FUNC_END_LABEL "LVFE"
284 #endif
285 #ifndef BLOCK_BEGIN_LABEL
286 #define BLOCK_BEGIN_LABEL "LVBB"
287 #endif
288 #ifndef BLOCK_END_LABEL
289 #define BLOCK_END_LABEL "LVBE"
290 #endif
291 #ifndef LINE_CODE_LABEL
292 #define LINE_CODE_LABEL "LVM"
293 #endif
295 #ifndef ASM_OUTPUT_DEBUG_DELTA2
296 #define ASM_OUTPUT_DEBUG_DELTA2(FILE,LABEL1,LABEL2) \
297 do \
299 fprintf ((FILE), "\t%s\t", UNALIGNED_SHORT_ASM_OP); \
300 assemble_name (FILE, LABEL1); \
301 fprintf (FILE, "-"); \
302 assemble_name (FILE, LABEL2); \
304 while (0)
305 #endif
307 #ifndef ASM_OUTPUT_DEBUG_DELTA4
308 #define ASM_OUTPUT_DEBUG_DELTA4(FILE,LABEL1,LABEL2) \
309 do \
311 fprintf ((FILE), "\t%s\t", UNALIGNED_INT_ASM_OP); \
312 assemble_name (FILE, LABEL1); \
313 fprintf (FILE, "-"); \
314 assemble_name (FILE, LABEL2); \
316 while (0)
317 #endif
319 #ifndef ASM_OUTPUT_DEBUG_ADDR_DELTA
320 #define ASM_OUTPUT_DEBUG_ADDR_DELTA(FILE,LABEL1,LABEL2) \
321 do \
323 fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP); \
324 assemble_name (FILE, LABEL1); \
325 fprintf (FILE, "-"); \
326 assemble_name (FILE, LABEL2); \
328 while (0)
329 #endif
331 #ifndef ASM_OUTPUT_DEBUG_ADDR
332 #define ASM_OUTPUT_DEBUG_ADDR(FILE,LABEL) \
333 do \
335 fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP); \
336 assemble_name (FILE, LABEL); \
338 while (0)
339 #endif
341 #ifndef ASM_OUTPUT_DEBUG_ADDR_CONST
342 #define ASM_OUTPUT_DEBUG_ADDR_CONST(FILE,ADDR) \
343 fprintf ((FILE), "\t%s\t%s", UNALIGNED_PTR_ASM_OP, (ADDR))
344 #endif
346 #ifndef ASM_OUTPUT_DEBUG_DATA1
347 #define ASM_OUTPUT_DEBUG_DATA1(FILE,VALUE) \
348 fprintf ((FILE), "\t%s\t%#x", ASM_BYTE_OP, (unsigned char) VALUE)
349 #endif
351 #ifndef ASM_OUTPUT_DEBUG_DATA2
352 #define ASM_OUTPUT_DEBUG_DATA2(FILE,VALUE) \
353 fprintf ((FILE), "\t%s\t%#x", UNALIGNED_SHORT_ASM_OP, \
354 (unsigned short) VALUE)
355 #endif
357 #ifndef ASM_OUTPUT_DEBUG_DATA4
358 #define ASM_OUTPUT_DEBUG_DATA4(FILE,VALUE) \
359 fprintf ((FILE), "\t%s\t%#lx", UNALIGNED_INT_ASM_OP, (unsigned long) VALUE)
360 #endif
362 #ifndef ASM_OUTPUT_DEBUG_DATA
363 #define ASM_OUTPUT_DEBUG_DATA(FILE,VALUE) \
364 fprintf ((FILE), "\t%s\t%#lx", UNALIGNED_OFFSET_ASM_OP(VALUE), VALUE)
365 #endif
367 #ifndef ASM_OUTPUT_DEBUG_ADDR_DATA
368 #define ASM_OUTPUT_DEBUG_ADDR_DATA(FILE,VALUE) \
369 fprintf ((FILE), "\t%s\t%#lx", UNALIGNED_PTR_ASM_OP, \
370 (unsigned long) VALUE)
371 #endif
373 #ifndef ASM_OUTPUT_DEBUG_DATA8
374 #define ASM_OUTPUT_DEBUG_DATA8(FILE,VALUE) \
375 fprintf ((FILE), "\t%s\t%#llx", UNALIGNED_DOUBLE_INT_ASM_OP, \
376 (unsigned long long) VALUE)
377 #endif
379 /* This is similar to the default ASM_OUTPUT_ASCII, except that no trailing
380 newline is produced. When flag_verbose_asm is asserted, we add commentary
381 at the end of the line, so we must avoid output of a newline here. */
382 #ifndef ASM_OUTPUT_DEBUG_STRING
383 #define ASM_OUTPUT_DEBUG_STRING(FILE,P) \
384 do \
386 register int slen = strlen(P); \
387 register const char *p = (P); \
388 register int i; \
389 fprintf (FILE, "\t.ascii \""); \
390 for (i = 0; i < slen; i++) \
392 register int c = p[i]; \
393 if (c == '\"' || c == '\\') \
394 putc ('\\', FILE); \
395 if (c >= ' ' && c < 0177) \
396 putc (c, FILE); \
397 else \
398 fprintf (FILE, "\\%o", c); \
400 fprintf (FILE, "\""); \
402 while (0)
403 #endif
405 /* Convert a reference to the assembler name of a C-level name. This
406 macro has the same effect as ASM_OUTPUT_LABELREF, but copies to
407 a string rather than writing to a file. */
408 #ifndef ASM_NAME_TO_STRING
409 #define ASM_NAME_TO_STRING(STR, NAME) \
410 do \
412 if ((NAME)[0] == '*') \
413 strcpy (STR, NAME+1); \
414 else \
415 strcpy (STR, NAME); \
417 while (0)
418 #endif
421 /* Output the debug header HEADER. Also output COMMENT if flag_verbose_asm is
422 set. Return the header size. Just return the size if DOSIZEONLY is
423 nonzero. */
425 static int
426 write_debug_header (DST_HEADER *header, const char *comment, int dosizeonly)
428 if (!dosizeonly)
430 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file,
431 header->dst__header_length.dst_w_length);
433 if (flag_verbose_asm)
434 fprintf (asm_out_file, "\t%s record length", ASM_COMMENT_START);
435 fputc ('\n', asm_out_file);
437 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file,
438 header->dst__header_type.dst_w_type);
440 if (flag_verbose_asm)
441 fprintf (asm_out_file, "\t%s record type (%s)", ASM_COMMENT_START,
442 comment);
444 fputc ('\n', asm_out_file);
447 return 4;
450 /* Output the address of SYMBOL. Also output COMMENT if flag_verbose_asm is
451 set. Return the address size. Just return the size if DOSIZEONLY is
452 nonzero. */
454 static int
455 write_debug_addr (const char *symbol, const char *comment, int dosizeonly)
457 if (!dosizeonly)
459 ASM_OUTPUT_DEBUG_ADDR (asm_out_file, symbol);
460 if (flag_verbose_asm)
461 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
462 fputc ('\n', asm_out_file);
465 return PTR_SIZE;
468 /* Output the single byte DATA1. Also output COMMENT if flag_verbose_asm is
469 set. Return the data size. Just return the size if DOSIZEONLY is
470 nonzero. */
472 static int
473 write_debug_data1 (unsigned int data1, const char *comment, int dosizeonly)
475 if (!dosizeonly)
477 ASM_OUTPUT_DEBUG_DATA1 (asm_out_file, data1);
478 if (flag_verbose_asm)
479 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
480 fputc ('\n', asm_out_file);
483 return 1;
486 /* Output the single word DATA2. Also output COMMENT if flag_verbose_asm is
487 set. Return the data size. Just return the size if DOSIZEONLY is
488 nonzero. */
490 static int
491 write_debug_data2 (unsigned int data2, const char *comment, int dosizeonly)
493 if (!dosizeonly)
495 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file, data2);
496 if (flag_verbose_asm)
497 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
498 fputc ('\n', asm_out_file);
501 return 2;
504 /* Output double word DATA4. Also output COMMENT if flag_verbose_asm is set.
505 Return the data size. Just return the size if DOSIZEONLY is nonzero. */
507 static int
508 write_debug_data4 (unsigned long data4, const char *comment, int dosizeonly)
510 if (!dosizeonly)
512 ASM_OUTPUT_DEBUG_DATA4 (asm_out_file, data4);
513 if (flag_verbose_asm)
514 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
515 fputc ('\n', asm_out_file);
518 return 4;
521 /* Output quad word DATA8. Also output COMMENT if flag_verbose_asm is set.
522 Return the data size. Just return the size if DOSIZEONLY is nonzero. */
524 static int
525 write_debug_data8 (unsigned long long data8, const char *comment,
526 int dosizeonly)
528 if (!dosizeonly)
530 ASM_OUTPUT_DEBUG_DATA8 (asm_out_file, data8);
531 if (flag_verbose_asm)
532 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
533 fputc ('\n', asm_out_file);
536 return 8;
539 /* Output the difference between LABEL1 and LABEL2. Also output COMMENT if
540 flag_verbose_asm is set. Return the data size. Just return the size if
541 DOSIZEONLY is nonzero. */
543 static int
544 write_debug_delta4 (const char *label1, const char *label2,
545 const char *comment, int dosizeonly)
547 if (!dosizeonly)
549 ASM_OUTPUT_DEBUG_DELTA4 (asm_out_file, label1, label2);
550 if (flag_verbose_asm)
551 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
552 fputc ('\n', asm_out_file);
555 return 4;
558 /* Output a character string STRING. Also write COMMENT if flag_verbose_asm is
559 set. Return the string length. Just return the length if DOSIZEONLY is
560 nonzero. */
562 static int
563 write_debug_string (const char *string, const char *comment, int dosizeonly)
565 if (!dosizeonly)
567 ASM_OUTPUT_DEBUG_STRING (asm_out_file, string);
568 if (flag_verbose_asm)
569 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
570 fputc ('\n', asm_out_file);
573 return strlen (string);
576 /* Output a module begin header and return the header size. Just return the
577 size if DOSIZEONLY is nonzero. */
579 static int
580 write_modbeg (int dosizeonly)
582 DST_MODULE_BEGIN modbeg;
583 DST_MB_TRLR mb_trlr;
584 int i;
585 char *module_name, *m;
586 int modnamelen;
587 int prodnamelen;
588 int totsize = 0;
590 /* Assumes primary filename has Unix syntax file spec. */
591 module_name = xstrdup (lbasename (primary_filename));
593 m = strrchr (module_name, '.');
594 if (m)
595 *m = 0;
597 modnamelen = strlen (module_name);
598 for (i = 0; i < modnamelen; i++)
599 module_name[i] = TOUPPER (module_name[i]);
601 prodnamelen = strlen (module_producer);
603 modbeg.dst_a_modbeg_header.dst__header_length.dst_w_length
604 = DST_K_MODBEG_SIZE + modnamelen + DST_K_MB_TRLR_SIZE + prodnamelen - 1;
605 modbeg.dst_a_modbeg_header.dst__header_type.dst_w_type = DST_K_MODBEG;
606 modbeg.dst_b_modbeg_flags.dst_v_modbeg_hide = 0;
607 modbeg.dst_b_modbeg_flags.dst_v_modbeg_version = 1;
608 modbeg.dst_b_modbeg_flags.dst_v_modbeg_unused = 0;
609 modbeg.dst_b_modbeg_unused = 0;
610 modbeg.dst_l_modbeg_language = (DST_LANGUAGE) module_language;
611 modbeg.dst_w_version_major = DST_K_VERSION_MAJOR;
612 modbeg.dst_w_version_minor = DST_K_VERSION_MINOR;
613 modbeg.dst_b_modbeg_name = strlen (module_name);
615 mb_trlr.dst_b_compiler = strlen (module_producer);
617 totsize += write_debug_header (&modbeg.dst_a_modbeg_header,
618 "modbeg", dosizeonly);
619 totsize += write_debug_data1 (*((char *) &modbeg.dst_b_modbeg_flags),
620 "flags", dosizeonly);
621 totsize += write_debug_data1 (modbeg.dst_b_modbeg_unused,
622 "unused", dosizeonly);
623 totsize += write_debug_data4 (modbeg.dst_l_modbeg_language,
624 "language", dosizeonly);
625 totsize += write_debug_data2 (modbeg.dst_w_version_major,
626 "DST major version", dosizeonly);
627 totsize += write_debug_data2 (modbeg.dst_w_version_minor,
628 "DST minor version", dosizeonly);
629 totsize += write_debug_data1 (modbeg.dst_b_modbeg_name,
630 "length of module name", dosizeonly);
631 totsize += write_debug_string (module_name, "module name", dosizeonly);
632 totsize += write_debug_data1 (mb_trlr.dst_b_compiler,
633 "length of compiler name", dosizeonly);
634 totsize += write_debug_string (module_producer, "compiler name", dosizeonly);
636 return totsize;
639 /* Output a module end trailer and return the trailer size. Just return
640 the size if DOSIZEONLY is nonzero. */
642 static int
643 write_modend (int dosizeonly)
645 DST_MODULE_END modend;
646 int totsize = 0;
648 modend.dst_a_modend_header.dst__header_length.dst_w_length
649 = DST_K_MODEND_SIZE - 1;
650 modend.dst_a_modend_header.dst__header_type.dst_w_type = DST_K_MODEND;
652 totsize += write_debug_header (&modend.dst_a_modend_header, "modend",
653 dosizeonly);
655 return totsize;
658 /* Output a routine begin header routine RTNNUM and return the header size.
659 Just return the size if DOSIZEONLY is nonzero. */
661 static int
662 write_rtnbeg (int rtnnum, int dosizeonly)
664 const char *rtnname;
665 int rtnnamelen;
666 char *rtnentryname;
667 int totsize = 0;
668 char label[MAX_ARTIFICIAL_LABEL_BYTES];
669 DST_ROUTINE_BEGIN rtnbeg;
670 DST_PROLOG prolog;
672 rtnname = VEC_index (char_p, funcnam_table, rtnnum);
673 rtnnamelen = strlen (rtnname);
674 rtnentryname = concat (rtnname, "..en", NULL);
676 if (!strcmp (rtnname, "main"))
678 DST_HEADER header;
679 const char *go = "TRANSFER$BREAK$GO";
681 /* This command isn't documented in DSTRECORDS, so it's made to
682 look like what DEC C does */
684 /* header size - 1st byte + flag byte + STO_LW size
685 + string count byte + string length */
686 header.dst__header_length.dst_w_length
687 = DST_K_DST_HEADER_SIZE - 1 + 1 + 4 + 1 + strlen (go);
688 header.dst__header_type.dst_w_type = DST_K_TBG;
690 totsize += write_debug_header (&header, "transfer", dosizeonly);
692 /* I think this is a flag byte, but I don't know what this flag means */
693 totsize += write_debug_data1 (0x1, "flags ???", dosizeonly);
695 /* Routine Begin PD Address */
696 totsize += write_debug_addr (rtnname, "main procedure descriptor",
697 dosizeonly);
698 totsize += write_debug_data1 (strlen (go), "length of main_name",
699 dosizeonly);
700 totsize += write_debug_string (go, "main name", dosizeonly);
703 /* The header length never includes the length byte. */
704 rtnbeg.dst_a_rtnbeg_header.dst__header_length.dst_w_length
705 = DST_K_RTNBEG_SIZE + rtnnamelen - 1;
706 rtnbeg.dst_a_rtnbeg_header.dst__header_type.dst_w_type = DST_K_RTNBEG;
707 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_unused = 0;
708 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_unalloc = 0;
709 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_prototype = 0;
710 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_inlined = 0;
711 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_no_call = 1;
712 rtnbeg.dst_b_rtnbeg_name = rtnnamelen;
714 totsize += write_debug_header (&rtnbeg.dst_a_rtnbeg_header, "rtnbeg",
715 dosizeonly);
716 totsize += write_debug_data1 (*((char *) &rtnbeg.dst_b_rtnbeg_flags),
717 "flags", dosizeonly);
719 /* Routine Begin Address */
720 totsize += write_debug_addr (rtnentryname, "routine entry name", dosizeonly);
722 /* Routine Begin PD Address */
723 totsize += write_debug_addr (rtnname, "routine procedure descriptor",
724 dosizeonly);
726 /* Routine Begin Name */
727 totsize += write_debug_data1 (rtnbeg.dst_b_rtnbeg_name,
728 "length of routine name", dosizeonly);
730 totsize += write_debug_string (rtnname, "routine name", dosizeonly);
732 free (rtnentryname);
734 if (debug_info_level > DINFO_LEVEL_TERSE)
736 prolog.dst_a_prolog_header.dst__header_length.dst_w_length
737 = DST_K_PROLOG_SIZE - 1;
738 prolog.dst_a_prolog_header.dst__header_type.dst_w_type = DST_K_PROLOG;
740 totsize += write_debug_header (&prolog.dst_a_prolog_header, "prolog",
741 dosizeonly);
743 ASM_GENERATE_INTERNAL_LABEL
744 (label, FUNC_PROLOG_LABEL,
745 VEC_index (unsigned, funcnum_table, rtnnum));
746 totsize += write_debug_addr (label, "prolog breakpoint addr",
747 dosizeonly);
750 return totsize;
753 /* Output a routine end trailer for routine RTNNUM and return the header size.
754 Just return the size if DOSIZEONLY is nonzero. */
756 static int
757 write_rtnend (int rtnnum, int dosizeonly)
759 DST_ROUTINE_END rtnend;
760 char label1[MAX_ARTIFICIAL_LABEL_BYTES];
761 char label2[MAX_ARTIFICIAL_LABEL_BYTES];
762 int totsize;
764 totsize = 0;
766 rtnend.dst_a_rtnend_header.dst__header_length.dst_w_length
767 = DST_K_RTNEND_SIZE - 1;
768 rtnend.dst_a_rtnend_header.dst__header_type.dst_w_type = DST_K_RTNEND;
769 rtnend.dst_b_rtnend_unused = 0;
770 rtnend.dst_l_rtnend_size = 0; /* Calculated below. */
772 totsize += write_debug_header (&rtnend.dst_a_rtnend_header, "rtnend",
773 dosizeonly);
774 totsize += write_debug_data1 (rtnend.dst_b_rtnend_unused, "unused",
775 dosizeonly);
777 ASM_GENERATE_INTERNAL_LABEL
778 (label1, FUNC_BEGIN_LABEL,
779 VEC_index (unsigned, funcnum_table, rtnnum));
780 ASM_GENERATE_INTERNAL_LABEL
781 (label2, FUNC_END_LABEL,
782 VEC_index (unsigned, funcnum_table, rtnnum));
783 totsize += write_debug_delta4 (label2, label1, "routine size", dosizeonly);
785 return totsize;
788 #define K_DELTA_PC(I) \
789 ((I) < 128 ? -(I) : (I) < 65536 ? DST_K_DELTA_PC_W : DST_K_DELTA_PC_L)
791 #define K_SET_LINUM(I) \
792 ((I) < 256 ? DST_K_SET_LINUM_B \
793 : (I) < 65536 ? DST_K_SET_LINUM : DST_K_SET_LINUM_L)
795 #define K_INCR_LINUM(I) \
796 ((I) < 256 ? DST_K_INCR_LINUM \
797 : (I) < 65536 ? DST_K_INCR_LINUM_W : DST_K_INCR_LINUM_L)
799 /* Output the PC to line number correlations and return the size. Just return
800 the size if DOSIZEONLY is nonzero */
802 static int
803 write_pclines (int dosizeonly)
805 unsigned i;
806 int fn;
807 int ln, lastln;
808 int linestart = 0;
809 int max_line;
810 DST_LINE_NUM_HEADER line_num;
811 DST_PCLINE_COMMANDS pcline;
812 char label[MAX_ARTIFICIAL_LABEL_BYTES];
813 char lastlabel[MAX_ARTIFICIAL_LABEL_BYTES];
814 int totsize = 0;
815 char buff[256];
817 max_line = file_info_table[1].max_line;
818 file_info_table[1].listing_line_start = linestart;
819 linestart = linestart + ((max_line / 100000) + 1) * 100000;
821 for (i = 2; i < file_info_table_in_use; i++)
823 max_line = file_info_table[i].max_line;
824 file_info_table[i].listing_line_start = linestart;
825 linestart = linestart + ((max_line / 10000) + 1) * 10000;
828 /* Set starting address to beginning of text section. */
829 line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 8;
830 line_num.dst_a_line_num_header.dst__header_type.dst_w_type = DST_K_LINE_NUM;
831 pcline.dst_b_pcline_command = DST_K_SET_ABS_PC;
833 totsize += write_debug_header (&line_num.dst_a_line_num_header,
834 "line_num", dosizeonly);
835 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
836 "line_num (SET ABS PC)", dosizeonly);
838 if (dosizeonly)
839 totsize += 4;
840 else
842 ASM_OUTPUT_DEBUG_ADDR (asm_out_file, TEXT_SECTION_ASM_OP);
843 if (flag_verbose_asm)
844 fprintf (asm_out_file, "\t%s line_num", ASM_COMMENT_START);
845 fputc ('\n', asm_out_file);
848 fn = line_info_table[1].dst_file_num;
849 ln = (file_info_table[fn].listing_line_start
850 + line_info_table[1].dst_line_num);
851 line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 4 + 4;
852 pcline.dst_b_pcline_command = DST_K_SET_LINUM_L;
854 totsize += write_debug_header (&line_num.dst_a_line_num_header,
855 "line_num", dosizeonly);
856 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
857 "line_num (SET LINUM LONG)", dosizeonly);
859 sprintf (buff, "line_num (%d)", ln ? ln - 1 : 0);
860 totsize += write_debug_data4 (ln ? ln - 1 : 0, buff, dosizeonly);
862 lastln = ln;
863 strcpy (lastlabel, TEXT_SECTION_ASM_OP);
864 for (i = 1; i < line_info_table_in_use; i++)
866 int extrabytes;
868 fn = line_info_table[i].dst_file_num;
869 ln = (file_info_table[fn].listing_line_start
870 + line_info_table[i].dst_line_num);
872 if (ln - lastln > 1)
873 extrabytes = 5; /* NUMBYTES (ln - lastln - 1) + 1; */
874 else if (ln <= lastln)
875 extrabytes = 5; /* NUMBYTES (ln - 1) + 1; */
876 else
877 extrabytes = 0;
879 line_num.dst_a_line_num_header.dst__header_length.dst_w_length
880 = 8 + extrabytes;
882 totsize += write_debug_header
883 (&line_num.dst_a_line_num_header, "line_num", dosizeonly);
885 if (ln - lastln > 1)
887 int lndif = ln - lastln - 1;
889 /* K_INCR_LINUM (lndif); */
890 pcline.dst_b_pcline_command = DST_K_INCR_LINUM_L;
892 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
893 "line_num (INCR LINUM LONG)",
894 dosizeonly);
896 sprintf (buff, "line_num (%d)", lndif);
897 totsize += write_debug_data4 (lndif, buff, dosizeonly);
899 else if (ln <= lastln)
901 /* K_SET_LINUM (ln-1); */
902 pcline.dst_b_pcline_command = DST_K_SET_LINUM_L;
904 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
905 "line_num (SET LINUM LONG)",
906 dosizeonly);
908 sprintf (buff, "line_num (%d)", ln - 1);
909 totsize += write_debug_data4 (ln - 1, buff, dosizeonly);
912 pcline.dst_b_pcline_command = DST_K_DELTA_PC_L;
914 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
915 "line_num (DELTA PC LONG)", dosizeonly);
917 ASM_GENERATE_INTERNAL_LABEL (label, LINE_CODE_LABEL, i);
918 totsize += write_debug_delta4 (label, lastlabel, "increment line_num",
919 dosizeonly);
921 lastln = ln;
922 strcpy (lastlabel, label);
925 return totsize;
928 /* Output a source correlation for file FILEID using information saved in
929 FILE_INFO_ENTRY and return the size. Just return the size if DOSIZEONLY is
930 nonzero. */
932 static int
933 write_srccorr (int fileid, dst_file_info_entry file_info_entry,
934 int dosizeonly)
936 int src_command_size;
937 int linesleft = file_info_entry.max_line;
938 int linestart = file_info_entry.listing_line_start;
939 int flen = file_info_entry.flen;
940 int linestodo = 0;
941 DST_SOURCE_CORR src_header;
942 DST_SRC_COMMAND src_command;
943 DST_SRC_COMMAND src_command_sf;
944 DST_SRC_COMMAND src_command_sl;
945 DST_SRC_COMMAND src_command_sr;
946 DST_SRC_COMMAND src_command_dl;
947 DST_SRC_CMDTRLR src_cmdtrlr;
948 char buff[256];
949 int totsize = 0;
951 if (fileid == 1)
953 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
954 = DST_K_SOURCE_CORR_HEADER_SIZE + 1 - 1;
955 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
956 = DST_K_SOURCE;
957 src_command.dst_b_src_command = DST_K_SRC_FORMFEED;
959 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
960 "source corr", dosizeonly);
962 totsize += write_debug_data1 (src_command.dst_b_src_command,
963 "source_corr (SRC FORMFEED)",
964 dosizeonly);
967 src_command_size
968 = DST_K_SRC_COMMAND_SIZE + flen + DST_K_SRC_CMDTRLR_SIZE;
969 src_command.dst_b_src_command = DST_K_SRC_DECLFILE;
970 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_length
971 = src_command_size - 2;
972 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_flags = 0;
973 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_fileid
974 = fileid;
975 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt
976 = file_info_entry.cdt;
977 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk
978 = file_info_entry.ebk;
979 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_rms_ffb
980 = file_info_entry.ffb;
981 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_rms_rfo
982 = file_info_entry.rfo;
983 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename
984 = file_info_entry.flen;
986 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
987 = DST_K_SOURCE_CORR_HEADER_SIZE + src_command_size - 1;
988 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
989 = DST_K_SOURCE;
991 src_cmdtrlr.dst_b_src_df_libmodname = 0;
993 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
994 "source corr", dosizeonly);
995 totsize += write_debug_data1 (src_command.dst_b_src_command,
996 "source_corr (DECL SRC FILE)", dosizeonly);
997 totsize += write_debug_data1
998 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_length,
999 "source_corr (length)", dosizeonly);
1001 totsize += write_debug_data1
1002 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_flags,
1003 "source_corr (flags)", dosizeonly);
1005 totsize += write_debug_data2
1006 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_fileid,
1007 "source_corr (fileid)", dosizeonly);
1009 totsize += write_debug_data8
1010 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt,
1011 "source_corr (creation date)", dosizeonly);
1013 totsize += write_debug_data4
1014 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk,
1015 "source_corr (EOF block number)", dosizeonly);
1017 totsize += write_debug_data2
1018 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_rms_ffb,
1019 "source_corr (first free byte)", dosizeonly);
1021 totsize += write_debug_data1
1022 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_rms_rfo,
1023 "source_corr (record and file organization)", dosizeonly);
1025 totsize += write_debug_data1
1026 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename,
1027 "source_corr (filename length)", dosizeonly);
1029 totsize += write_debug_string (remap_debug_filename (
1030 file_info_entry.file_name),
1031 "source file name", dosizeonly);
1032 totsize += write_debug_data1 (src_cmdtrlr.dst_b_src_df_libmodname,
1033 "source_corr (libmodname)", dosizeonly);
1035 src_command_sf.dst_b_src_command = DST_K_SRC_SETFILE;
1036 src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword = fileid;
1038 src_command_sr.dst_b_src_command = DST_K_SRC_SETREC_W;
1039 src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword = 1;
1041 src_command_sl.dst_b_src_command = DST_K_SRC_SETLNUM_L;
1042 src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong = linestart + 1;
1044 src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W;
1046 if (linesleft > 65534)
1047 linesleft = linesleft - 65534, linestodo = 65534;
1048 else
1049 linestodo = linesleft, linesleft = 0;
1051 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo;
1053 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1054 = DST_K_SOURCE_CORR_HEADER_SIZE + 3 + 3 + 5 + 3 - 1;
1055 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1056 = DST_K_SOURCE;
1058 if (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword)
1060 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1061 "source corr", dosizeonly);
1063 totsize += write_debug_data1 (src_command_sf.dst_b_src_command,
1064 "source_corr (src setfile)", dosizeonly);
1066 totsize += write_debug_data2
1067 (src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword,
1068 "source_corr (fileid)", dosizeonly);
1070 totsize += write_debug_data1 (src_command_sr.dst_b_src_command,
1071 "source_corr (setrec)", dosizeonly);
1073 totsize += write_debug_data2
1074 (src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword,
1075 "source_corr (recnum)", dosizeonly);
1077 totsize += write_debug_data1 (src_command_sl.dst_b_src_command,
1078 "source_corr (setlnum)", dosizeonly);
1080 totsize += write_debug_data4
1081 (src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong,
1082 "source_corr (linenum)", dosizeonly);
1084 totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
1085 "source_corr (deflines)", dosizeonly);
1087 sprintf (buff, "source_corr (%d)",
1088 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
1089 totsize += write_debug_data2
1090 (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword,
1091 buff, dosizeonly);
1093 while (linesleft > 0)
1095 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1096 = DST_K_SOURCE_CORR_HEADER_SIZE + 3 - 1;
1097 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1098 = DST_K_SOURCE;
1099 src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W;
1101 if (linesleft > 65534)
1102 linesleft = linesleft - 65534, linestodo = 65534;
1103 else
1104 linestodo = linesleft, linesleft = 0;
1106 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo;
1108 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1109 "source corr", dosizeonly);
1110 totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
1111 "source_corr (deflines)", dosizeonly);
1112 sprintf (buff, "source_corr (%d)",
1113 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
1114 totsize += write_debug_data2
1115 (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword,
1116 buff, dosizeonly);
1120 return totsize;
1123 /* Output all the source correlation entries and return the size. Just return
1124 the size if DOSIZEONLY is nonzero. */
1126 static int
1127 write_srccorrs (int dosizeonly)
1129 unsigned int i;
1130 int totsize = 0;
1132 for (i = 1; i < file_info_table_in_use; i++)
1133 totsize += write_srccorr (i, file_info_table[i], dosizeonly);
1135 return totsize;
1138 /* Output a marker (i.e. a label) for the beginning of a function, before
1139 the prologue. */
1141 static void
1142 vmsdbgout_begin_prologue (unsigned int line, const char *file)
1144 char label[MAX_ARTIFICIAL_LABEL_BYTES];
1146 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1147 (*dwarf2_debug_hooks.begin_prologue) (line, file);
1149 if (debug_info_level > DINFO_LEVEL_NONE)
1151 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL,
1152 current_function_funcdef_no);
1153 ASM_OUTPUT_LABEL (asm_out_file, label);
1157 /* Output a marker (i.e. a label) for the beginning of a function, after
1158 the prologue. */
1160 static void
1161 vmsdbgout_end_prologue (unsigned int line, const char *file)
1163 char label[MAX_ARTIFICIAL_LABEL_BYTES];
1165 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1166 (*dwarf2_debug_hooks.end_prologue) (line, file);
1168 if (debug_info_level > DINFO_LEVEL_TERSE)
1170 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL,
1171 current_function_funcdef_no);
1172 ASM_OUTPUT_LABEL (asm_out_file, label);
1174 /* VMS PCA expects every PC range to correlate to some line and file. */
1175 vmsdbgout_source_line (line, file, 0, true);
1179 /* No output for VMS debug, but make obligatory call to Dwarf2 debug */
1181 static void
1182 vmsdbgout_end_function (unsigned int line)
1184 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1185 (*dwarf2_debug_hooks.end_function) (line);
1188 /* Output a marker (i.e. a label) for the beginning of the epilogue.
1189 This gets called *before* the epilogue code has been generated. */
1191 static void
1192 vmsdbgout_begin_epilogue (unsigned int line, const char *file)
1194 char label[MAX_ARTIFICIAL_LABEL_BYTES];
1195 static int save_current_function_funcdef_no = -1;
1197 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1198 (*dwarf2_debug_hooks.begin_epilogue) (line, file);
1200 if (debug_info_level > DINFO_LEVEL_NONE)
1202 if (save_current_function_funcdef_no != current_function_funcdef_no)
1204 /* Output a label to mark the endpoint of the code generated for this
1205 function. */
1206 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_EPILOG_LABEL,
1207 current_function_funcdef_no);
1209 ASM_OUTPUT_LABEL (asm_out_file, label);
1211 save_current_function_funcdef_no = current_function_funcdef_no;
1213 /* VMS PCA expects every PC range to correlate to some line and
1214 file. */
1215 vmsdbgout_source_line (line, file, 0, true);
1220 /* Output a marker (i.e. a label) for the absolute end of the generated code
1221 for a function definition. This gets called *after* the epilogue code has
1222 been generated. */
1224 static void
1225 vmsdbgout_end_epilogue (unsigned int line, const char *file)
1227 char label[MAX_ARTIFICIAL_LABEL_BYTES];
1229 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1230 (*dwarf2_debug_hooks.end_epilogue) (line, file);
1232 if (debug_info_level > DINFO_LEVEL_NONE)
1234 /* Output a label to mark the endpoint of the code generated for this
1235 function. */
1236 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL,
1237 current_function_funcdef_no);
1238 ASM_OUTPUT_LABEL (asm_out_file, label);
1240 /* VMS PCA expects every PC range to correlate to some line and file. */
1241 vmsdbgout_source_line (line, file, 0, true);
1245 /* Output a marker (i.e. a label) for the beginning of the generated code for
1246 a lexical block. */
1248 static void
1249 vmsdbgout_begin_block (register unsigned line, register unsigned blocknum)
1251 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1252 (*dwarf2_debug_hooks.begin_block) (line, blocknum);
1254 if (debug_info_level > DINFO_LEVEL_TERSE)
1255 targetm.asm_out.internal_label (asm_out_file, BLOCK_BEGIN_LABEL, blocknum);
1258 /* Output a marker (i.e. a label) for the end of the generated code for a
1259 lexical block. */
1261 static void
1262 vmsdbgout_end_block (register unsigned line, register unsigned blocknum)
1264 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1265 (*dwarf2_debug_hooks.end_block) (line, blocknum);
1267 if (debug_info_level > DINFO_LEVEL_TERSE)
1268 targetm.asm_out.internal_label (asm_out_file, BLOCK_END_LABEL, blocknum);
1271 /* Not implemented in VMS Debug. */
1273 static bool
1274 vmsdbgout_ignore_block (const_tree block)
1276 bool retval = 0;
1278 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1279 retval = (*dwarf2_debug_hooks.ignore_block) (block);
1281 return retval;
1284 /* Add an entry for function DECL into the funcnam_table. */
1286 static void
1287 vmsdbgout_begin_function (tree decl)
1289 const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
1291 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1292 (*dwarf2_debug_hooks.begin_function) (decl);
1294 /* Add the new entry to the end of the function name table. */
1295 VEC_safe_push (char_p, heap, funcnam_table, xstrdup (name));
1296 VEC_safe_push (unsigned, heap, funcnum_table,
1297 current_function_funcdef_no);
1300 static char fullname_buff [4096];
1302 /* Return the full file specification for FILENAME. The specification must be
1303 in VMS syntax in order to be processed by VMS Debug. */
1305 static char *
1306 full_name (const char *filename)
1308 #ifdef VMS
1309 FILE *fp = fopen (filename, "r");
1311 fgetname (fp, fullname_buff, 1);
1312 fclose (fp);
1313 #else
1314 /* Unix paths really mess up VMS debug. Better to just output the
1315 base filename. */
1316 strcpy (fullname_buff, filename);
1317 #endif
1319 return fullname_buff;
1322 /* Lookup a filename (in the list of filenames that we know about here in
1323 vmsdbgout.c) and return its "index". The index of each (known) filename is
1324 just a unique number which is associated with only that one filename. We
1325 need such numbers for the sake of generating labels and references
1326 to those files numbers. If the filename given as an argument is not
1327 found in our current list, add it to the list and assign it the next
1328 available unique index number. In order to speed up searches, we remember
1329 the index of the filename was looked up last. This handles the majority of
1330 all searches. */
1332 static unsigned int
1333 lookup_filename (const char *file_name)
1335 static unsigned int last_file_lookup_index = 0;
1336 register char *fn;
1337 register unsigned i;
1338 const char *fnam;
1339 char flen;
1340 long long cdt = 0;
1341 long ebk = 0;
1342 short ffb = 0;
1343 char rfo = 0;
1344 long siz = 0;
1345 int ver = 0;
1347 fnam = full_name (file_name);
1348 flen = strlen (fnam);
1350 /* Check to see if the file name that was searched on the previous call
1351 matches this file name. If so, return the index. */
1352 if (last_file_lookup_index != 0)
1354 fn = file_info_table[last_file_lookup_index].file_name;
1355 if (strcmp (fnam, fn) == 0)
1356 return last_file_lookup_index;
1359 /* Didn't match the previous lookup, search the table */
1360 for (i = 1; i < file_info_table_in_use; ++i)
1362 fn = file_info_table[i].file_name;
1363 if (strcmp (fnam, fn) == 0)
1365 last_file_lookup_index = i;
1366 return i;
1370 /* Prepare to add a new table entry by making sure there is enough space in
1371 the table to do so. If not, expand the current table. */
1372 if (file_info_table_in_use == file_info_table_allocated)
1375 file_info_table_allocated += FILE_TABLE_INCREMENT;
1376 file_info_table = XRESIZEVEC (dst_file_info_entry, file_info_table,
1377 file_info_table_allocated);
1380 if (vms_file_stats_name (file_name, &cdt, &siz, &rfo, &ver) == 0)
1382 ebk = siz / 512 + 1;
1383 ffb = siz - ((siz / 512) * 512);
1386 /* Add the new entry to the end of the filename table. */
1387 file_info_table[file_info_table_in_use].file_name = xstrdup (fnam);
1388 file_info_table[file_info_table_in_use].max_line = 0;
1389 file_info_table[file_info_table_in_use].cdt = cdt;
1390 file_info_table[file_info_table_in_use].ebk = ebk;
1391 file_info_table[file_info_table_in_use].ffb = ffb;
1392 file_info_table[file_info_table_in_use].rfo = rfo;
1393 file_info_table[file_info_table_in_use].flen = flen;
1395 last_file_lookup_index = file_info_table_in_use++;
1396 return last_file_lookup_index;
1399 /* Output a label to mark the beginning of a source code line entry
1400 and record information relating to this source line, in
1401 'line_info_table' for later output of the .debug_line section. */
1403 static void
1404 vmsdbgout_source_line (register unsigned line, register const char *filename,
1405 int discriminator, bool is_stmt)
1407 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1408 (*dwarf2_debug_hooks.source_line) (line, filename, discriminator, is_stmt);
1410 if (debug_info_level >= DINFO_LEVEL_TERSE)
1412 dst_line_info_ref line_info;
1414 targetm.asm_out.internal_label (asm_out_file, LINE_CODE_LABEL,
1415 line_info_table_in_use);
1417 /* Expand the line info table if necessary. */
1418 if (line_info_table_in_use == line_info_table_allocated)
1420 line_info_table_allocated += LINE_INFO_TABLE_INCREMENT;
1421 line_info_table = XRESIZEVEC (dst_line_info_entry, line_info_table,
1422 line_info_table_allocated);
1425 /* Add the new entry at the end of the line_info_table. */
1426 line_info = &line_info_table[line_info_table_in_use++];
1427 line_info->dst_file_num = lookup_filename (filename);
1428 line_info->dst_line_num = line;
1429 if (line > file_info_table[line_info->dst_file_num].max_line)
1430 file_info_table[line_info->dst_file_num].max_line = line;
1434 /* Record the beginning of a new source file, for later output.
1435 At present, unimplemented. */
1437 static void
1438 vmsdbgout_start_source_file (unsigned int lineno, const char *filename)
1440 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1441 (*dwarf2_debug_hooks.start_source_file) (lineno, filename);
1444 /* Record the end of a source file, for later output.
1445 At present, unimplemented. */
1447 static void
1448 vmsdbgout_end_source_file (unsigned int lineno ATTRIBUTE_UNUSED)
1450 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1451 (*dwarf2_debug_hooks.end_source_file) (lineno);
1454 /* Set up for Debug output at the start of compilation. */
1456 static void
1457 vmsdbgout_init (const char *main_input_filename)
1459 const char *language_string = lang_hooks.name;
1461 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1462 (*dwarf2_debug_hooks.init) (main_input_filename);
1464 if (debug_info_level == DINFO_LEVEL_NONE)
1465 return;
1467 /* Remember the name of the primary input file. */
1468 primary_filename = main_input_filename;
1470 /* Allocate the initial hunk of the file_info_table. */
1471 file_info_table = XCNEWVEC (dst_file_info_entry, FILE_TABLE_INCREMENT);
1472 file_info_table_allocated = FILE_TABLE_INCREMENT;
1473 /* Skip the first entry - file numbers begin at 1. */
1474 file_info_table_in_use = 1;
1476 funcnam_table = VEC_alloc (char_p, heap, FUNC_TABLE_INITIAL);
1477 funcnum_table = VEC_alloc (unsigned, heap, FUNC_TABLE_INITIAL);
1479 /* Allocate the initial hunk of the line_info_table. */
1480 line_info_table = XCNEWVEC (dst_line_info_entry, LINE_INFO_TABLE_INCREMENT);
1481 line_info_table_allocated = LINE_INFO_TABLE_INCREMENT;
1482 /* zero-th entry is allocated, but unused */
1483 line_info_table_in_use = 1;
1485 lookup_filename (primary_filename);
1487 if (!strcmp (language_string, "GNU C"))
1488 module_language = DST_K_C;
1489 else if (!strcmp (language_string, "GNU C++"))
1490 module_language = DST_K_CXX;
1491 else if (!strcmp (language_string, "GNU Ada"))
1492 module_language = DST_K_ADA;
1493 else if (!strcmp (language_string, "GNU F77"))
1494 module_language = DST_K_FORTRAN;
1495 else
1496 module_language = DST_K_UNKNOWN;
1498 module_producer = concat (language_string, " ", version_string, NULL);
1500 ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
1504 /* Not implemented in VMS Debug. */
1506 static void
1507 vmsdbgout_assembly_start (void)
1509 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1510 (*dwarf2_debug_hooks.assembly_start) ();
1513 /* Not implemented in VMS Debug. */
1515 static void
1516 vmsdbgout_define (unsigned int lineno, const char *buffer)
1518 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1519 (*dwarf2_debug_hooks.define) (lineno, buffer);
1522 /* Not implemented in VMS Debug. */
1524 static void
1525 vmsdbgout_undef (unsigned int lineno, const char *buffer)
1527 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1528 (*dwarf2_debug_hooks.undef) (lineno, buffer);
1531 /* Not implemented in VMS Debug. */
1533 static void
1534 vmsdbgout_decl (tree decl)
1536 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1537 (*dwarf2_debug_hooks.function_decl) (decl);
1540 /* Not implemented in VMS Debug. */
1542 static void
1543 vmsdbgout_global_decl (tree decl)
1545 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1546 (*dwarf2_debug_hooks.global_decl) (decl);
1549 /* Not implemented in VMS Debug. */
1551 static void
1552 vmsdbgout_type_decl (tree decl, int local)
1554 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1555 (*dwarf2_debug_hooks.type_decl) (decl, local);
1558 /* Not implemented in VMS Debug. */
1560 static void
1561 vmsdbgout_abstract_function (tree decl)
1563 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1564 (*dwarf2_debug_hooks.outlining_inline_function) (decl);
1567 /* Output stuff that Debug requires at the end of every file and generate the
1568 VMS Debug debugging info. */
1570 static void
1571 vmsdbgout_finish (const char *main_input_filename ATTRIBUTE_UNUSED)
1573 unsigned int i, ifunc;
1574 int totsize;
1576 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1577 (*dwarf2_debug_hooks.finish) (main_input_filename);
1579 if (debug_info_level == DINFO_LEVEL_NONE)
1580 return;
1582 /* Output a terminator label for the .text section. */
1583 switch_to_section (text_section);
1584 targetm.asm_out.internal_label (asm_out_file, TEXT_END_LABEL, 0);
1586 /* Output debugging information.
1587 Warning! Do not change the name of the .vmsdebug section without
1588 changing it in the assembler also. */
1589 switch_to_section (get_named_section (NULL, ".vmsdebug", 0));
1590 ASM_OUTPUT_ALIGN (asm_out_file, 0);
1592 totsize = write_modbeg (1);
1593 FOR_EACH_VEC_ELT (unsigned, funcnum_table, i, ifunc)
1595 totsize += write_rtnbeg (i, 1);
1596 totsize += write_rtnend (i, 1);
1598 totsize += write_pclines (1);
1600 write_modbeg (0);
1601 FOR_EACH_VEC_ELT (unsigned, funcnum_table, i, ifunc)
1603 write_rtnbeg (i, 0);
1604 write_rtnend (i, 0);
1606 write_pclines (0);
1608 if (debug_info_level > DINFO_LEVEL_TERSE)
1610 totsize = write_srccorrs (1);
1611 write_srccorrs (0);
1614 totsize = write_modend (1);
1615 write_modend (0);
1618 /* Need for both Dwarf2 on IVMS and VMS Debug on AVMS */
1620 #ifdef VMS
1621 #define __NEW_STARLET 1
1622 #include <vms/rms.h>
1623 #include <vms/atrdef.h>
1624 #include <vms/fibdef.h>
1625 #include <vms/stsdef.h>
1626 #include <vms/iodef.h>
1627 #include <vms/fatdef.h>
1628 #include <vms/descrip.h>
1629 #include <unixlib.h>
1631 #define MAXPATH 256
1633 /* descrip.h doesn't have everything ... */
1634 typedef struct fibdef* __fibdef_ptr32 __attribute__ (( mode (SI) ));
1635 struct dsc$descriptor_fib
1637 unsigned int fib$l_len;
1638 __fibdef_ptr32 fib$l_addr;
1641 /* I/O Status Block. */
1642 struct IOSB
1644 unsigned short status, count;
1645 unsigned int devdep;
1648 static char *tryfile;
1650 /* Variable length string. */
1651 struct vstring
1653 short length;
1654 char string[NAM$C_MAXRSS+1];
1657 static char filename_buff [MAXPATH];
1658 static char vms_filespec [MAXPATH];
1660 /* Callback function for filespec style conversion. */
1662 static int
1663 translate_unix (char *name, int type ATTRIBUTE_UNUSED)
1665 strncpy (filename_buff, name, MAXPATH);
1666 filename_buff [MAXPATH - 1] = (char) 0;
1667 return 0;
1670 /* Wrapper for DECC function that converts a Unix filespec
1671 to VMS style filespec. */
1673 static char *
1674 to_vms_file_spec (char *filespec)
1676 strncpy (vms_filespec, "", MAXPATH);
1677 decc$to_vms (filespec, translate_unix, 1, 1);
1678 strncpy (vms_filespec, filename_buff, MAXPATH);
1680 vms_filespec [MAXPATH - 1] = (char) 0;
1682 return vms_filespec;
1685 #else
1686 #define VMS_EPOCH_OFFSET 35067168000000000
1687 #define VMS_GRANULARITY_FACTOR 10000000
1688 #endif
1690 /* Return VMS file date, size, format, version given a name. */
1693 vms_file_stats_name (const char *filename, long long *cdt, long *siz, char *rfo,
1694 int *ver)
1696 #ifdef VMS
1697 struct FAB fab;
1698 struct NAM nam;
1700 unsigned long long create;
1701 FAT recattr;
1702 char ascnamebuff [256];
1704 ATRDEF atrlst[]
1706 { ATR$S_CREDATE, ATR$C_CREDATE, &create },
1707 { ATR$S_RECATTR, ATR$C_RECATTR, &recattr },
1708 { ATR$S_ASCNAME, ATR$C_ASCNAME, &ascnamebuff },
1709 { 0, 0, 0}
1712 FIBDEF fib;
1713 struct dsc$descriptor_fib fibdsc = {sizeof (fib), (void *) &fib};
1715 struct IOSB iosb;
1717 long status;
1718 unsigned short chan;
1720 struct vstring file;
1721 struct dsc$descriptor_s filedsc
1722 = {NAM$C_MAXRSS, DSC$K_DTYPE_T, DSC$K_CLASS_S, (void *) file.string};
1723 struct vstring device;
1724 struct dsc$descriptor_s devicedsc
1725 = {NAM$C_MAXRSS, DSC$K_DTYPE_T, DSC$K_CLASS_S, (void *) device.string};
1726 struct vstring result;
1727 struct dsc$descriptor_s resultdsc
1728 = {NAM$C_MAXRSS, DSC$K_DTYPE_VT, DSC$K_CLASS_VS, (void *) result.string};
1730 if (strcmp (filename, "<internal>") == 0
1731 || strcmp (filename, "<built-in>") == 0)
1733 if (cdt)
1734 *cdt = 0;
1736 if (siz)
1737 *siz = 0;
1739 if (rfo)
1740 *rfo = 0;
1742 if (ver)
1743 *ver = 0;
1745 return 0;
1748 tryfile = to_vms_file_spec (filename);
1750 /* Allocate and initialize a FAB and NAM structures. */
1751 fab = cc$rms_fab;
1752 nam = cc$rms_nam;
1754 nam.nam$l_esa = file.string;
1755 nam.nam$b_ess = NAM$C_MAXRSS;
1756 nam.nam$l_rsa = result.string;
1757 nam.nam$b_rss = NAM$C_MAXRSS;
1758 fab.fab$l_fna = tryfile;
1759 fab.fab$b_fns = strlen (tryfile);
1760 fab.fab$l_nam = &nam;
1762 /* Validate filespec syntax and device existence. */
1763 status = SYS$PARSE (&fab, 0, 0);
1764 if ((status & 1) != 1)
1765 return 1;
1767 file.string[nam.nam$b_esl] = 0;
1769 /* Find matching filespec. */
1770 status = SYS$SEARCH (&fab, 0, 0);
1771 if ((status & 1) != 1)
1772 return 1;
1774 file.string[nam.nam$b_esl] = 0;
1775 result.string[result.length=nam.nam$b_rsl] = 0;
1777 /* Get the device name and assign an IO channel. */
1778 strncpy (device.string, nam.nam$l_dev, nam.nam$b_dev);
1779 devicedsc.dsc$w_length = nam.nam$b_dev;
1780 chan = 0;
1781 status = SYS$ASSIGN (&devicedsc, &chan, 0, 0, 0);
1782 if ((status & 1) != 1)
1783 return 1;
1785 /* Initialize the FIB and fill in the directory id field. */
1786 memset (&fib, 0, sizeof (fib));
1787 fib.fib$w_did[0] = nam.nam$w_did[0];
1788 fib.fib$w_did[1] = nam.nam$w_did[1];
1789 fib.fib$w_did[2] = nam.nam$w_did[2];
1790 fib.fib$l_acctl = 0;
1791 fib.fib$l_wcc = 0;
1792 strcpy (file.string, (strrchr (result.string, ']') + 1));
1793 filedsc.dsc$w_length = strlen (file.string);
1794 result.string[result.length = 0] = 0;
1796 /* Open and close the file to fill in the attributes. */
1797 status
1798 = SYS$QIOW (0, chan, IO$_ACCESS|IO$M_ACCESS, &iosb, 0, 0,
1799 &fibdsc, &filedsc, &result.length, &resultdsc, &atrlst, 0);
1800 if ((status & 1) != 1)
1801 return 1;
1802 if ((iosb.status & 1) != 1)
1803 return 1;
1805 result.string[result.length] = 0;
1806 status = SYS$QIOW (0, chan, IO$_DEACCESS, &iosb, 0, 0, &fibdsc, 0, 0, 0,
1807 &atrlst, 0);
1808 if ((status & 1) != 1)
1809 return 1;
1810 if ((iosb.status & 1) != 1)
1811 return 1;
1813 /* Deassign the channel and exit. */
1814 status = SYS$DASSGN (chan);
1815 if ((status & 1) != 1)
1816 return 1;
1818 if (cdt) *cdt = create;
1819 if (siz) *siz = (512 * 65536 * recattr.fat$w_efblkh) +
1820 (512 * (recattr.fat$w_efblkl - 1)) +
1821 recattr.fat$w_ffbyte;
1822 if (rfo) *rfo = recattr.fat$v_rtype;
1823 if (ver) *ver = strtol (strrchr (ascnamebuff, ';')+1, 0, 10);
1825 return 0;
1826 #else
1827 struct stat buff;
1829 if ((stat (filename, &buff)) != 0)
1830 return 1;
1832 if (cdt)
1833 *cdt = (long long) (buff.st_mtime * VMS_GRANULARITY_FACTOR)
1834 + VMS_EPOCH_OFFSET;
1836 if (siz)
1837 *siz = buff.st_size;
1839 if (rfo)
1840 *rfo = 2; /* Stream LF format */
1842 if (ver)
1843 *ver = 1;
1845 return 0;
1846 #endif
1848 #endif