* config/epiphany/epiphany.h (EPIPHANY_LIBRARY_EXTRA_SPEC): Define.
[official-gcc.git] / gcc / vmsdbgout.c
blobcb8479ff24ab57ee345d97dd77a18545413726e9
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, 2011
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;
75 dst_file_info_entry;
77 /* Maximum size (in bytes) of an artificially generated label. */
78 #define MAX_ARTIFICIAL_LABEL_BYTES 30
80 /* Make sure we know the sizes of the various types debug can describe. These
81 are only defaults. If the sizes are different for your target, you should
82 override these values by defining the appropriate symbols in your tm.h
83 file. */
84 #ifndef PTR_SIZE
85 #define PTR_SIZE 4 /* Must be 32 bits for VMS debug info */
86 #endif
88 /* Pointer to a structure of filenames referenced by this compilation unit. */
89 static dst_file_info_ref file_info_table;
91 /* Total number of entries in the table (i.e. array) pointed to by
92 `file_info_table'. This is the *total* and includes both used and unused
93 slots. */
94 static unsigned int file_info_table_allocated;
96 /* Number of entries in the file_info_table which are actually in use. */
97 static unsigned int file_info_table_in_use;
99 /* Size (in elements) of increments by which we may expand the filename
100 table. */
101 #define FILE_TABLE_INCREMENT 64
103 typedef char *char_p;
105 static vec<char_p> funcnam_table;
106 static vec<unsigned> funcnum_table;
107 #define FUNC_TABLE_INITIAL 256
109 /* Local pointer to the name of the main input file. Initialized in
110 vmsdbgout_init. */
111 static const char *primary_filename;
113 static char *module_producer;
114 static unsigned int module_language;
116 /* A pointer to the base of a table that contains line information
117 for each source code line in .text in the compilation unit. */
118 static dst_line_info_ref line_info_table;
120 /* Number of elements currently allocated for line_info_table. */
121 static unsigned int line_info_table_allocated;
123 /* Number of elements in line_info_table currently in use. */
124 static unsigned int line_info_table_in_use;
126 /* Size (in elements) of increments by which we may expand line_info_table. */
127 #define LINE_INFO_TABLE_INCREMENT 1024
129 /* Forward declarations for functions defined in this file. */
130 static char *full_name (const char *);
131 static unsigned int lookup_filename (const char *);
132 static int write_debug_header (DST_HEADER *, const char *, int);
133 static int write_debug_addr (const char *, const char *, int);
134 static int write_debug_data1 (unsigned int, const char *, int);
135 static int write_debug_data2 (unsigned int, const char *, int);
136 static int write_debug_data4 (unsigned long, const char *, int);
137 static int write_debug_data8 (unsigned long long, const char *, int);
138 static int write_debug_delta4 (const char *, const char *, const char *, int);
139 static int write_debug_string (const char *, const char *, int);
140 static int write_modbeg (int);
141 static int write_modend (int);
142 static int write_rtnbeg (int, int);
143 static int write_rtnend (int, int);
144 static int write_pclines (int);
145 static int write_srccorr (int, dst_file_info_entry, int);
146 static int write_srccorrs (int);
148 static void vmsdbgout_init (const char *);
149 static void vmsdbgout_finish (const char *);
150 static void vmsdbgout_assembly_start (void);
151 static void vmsdbgout_define (unsigned int, const char *);
152 static void vmsdbgout_undef (unsigned int, const char *);
153 static void vmsdbgout_start_source_file (unsigned int, const char *);
154 static void vmsdbgout_end_source_file (unsigned int);
155 static void vmsdbgout_begin_block (unsigned int, unsigned int);
156 static void vmsdbgout_end_block (unsigned int, unsigned int);
157 static bool vmsdbgout_ignore_block (const_tree);
158 static void vmsdbgout_source_line (unsigned int, const char *, int, bool);
159 static void vmsdbgout_write_source_line (unsigned, const char *, int , bool);
160 static void vmsdbgout_begin_prologue (unsigned int, const char *);
161 static void vmsdbgout_end_prologue (unsigned int, const char *);
162 static void vmsdbgout_end_function (unsigned int);
163 static void vmsdbgout_begin_epilogue (unsigned int, const char *);
164 static void vmsdbgout_end_epilogue (unsigned int, const char *);
165 static void vmsdbgout_begin_function (tree);
166 static void vmsdbgout_decl (tree);
167 static void vmsdbgout_global_decl (tree);
168 static void vmsdbgout_type_decl (tree, int);
169 static void vmsdbgout_abstract_function (tree);
171 /* The debug hooks structure. */
173 const struct gcc_debug_hooks vmsdbg_debug_hooks
174 = {vmsdbgout_init,
175 vmsdbgout_finish,
176 vmsdbgout_assembly_start,
177 vmsdbgout_define,
178 vmsdbgout_undef,
179 vmsdbgout_start_source_file,
180 vmsdbgout_end_source_file,
181 vmsdbgout_begin_block,
182 vmsdbgout_end_block,
183 vmsdbgout_ignore_block,
184 vmsdbgout_source_line,
185 vmsdbgout_begin_prologue,
186 vmsdbgout_end_prologue,
187 vmsdbgout_begin_epilogue,
188 vmsdbgout_end_epilogue,
189 vmsdbgout_begin_function,
190 vmsdbgout_end_function,
191 vmsdbgout_decl,
192 vmsdbgout_global_decl,
193 vmsdbgout_type_decl, /* type_decl */
194 debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */
195 debug_nothing_tree, /* deferred_inline_function */
196 vmsdbgout_abstract_function,
197 debug_nothing_rtx, /* label */
198 debug_nothing_int, /* handle_pch */
199 debug_nothing_rtx, /* var_location */
200 debug_nothing_void, /* switch_text_section */
201 debug_nothing_tree_tree, /* set_name */
202 0, /* start_end_main_source_file */
203 TYPE_SYMTAB_IS_ADDRESS /* tree_type_symtab_field */
206 /* Definitions of defaults for assembler-dependent names of various
207 pseudo-ops and section names. */
208 #define VMS_UNALIGNED_SHORT_ASM_OP ".word"
209 #define VMS_UNALIGNED_INT_ASM_OP ".long"
210 #define VMS_UNALIGNED_LONG_ASM_OP ".long"
211 #define VMS_UNALIGNED_DOUBLE_INT_ASM_OP ".quad"
213 #define VMS_ASM_BYTE_OP ".byte"
215 #define NUMBYTES(I) ((I) < 256 ? 1 : (I) < 65536 ? 2 : 4)
217 #define NUMBYTES0(I) ((I) < 128 ? 0 : (I) < 65536 ? 2 : 4)
219 #ifndef UNALIGNED_PTR_ASM_OP
220 #define UNALIGNED_PTR_ASM_OP \
221 (PTR_SIZE == 8 ? VMS_UNALIGNED_DOUBLE_INT_ASM_OP : VMS_UNALIGNED_INT_ASM_OP)
222 #endif
224 #ifndef UNALIGNED_OFFSET_ASM_OP
225 #define UNALIGNED_OFFSET_ASM_OP(OFFSET) \
226 (NUMBYTES(OFFSET) == 4 \
227 ? VMS_UNALIGNED_LONG_ASM_OP \
228 : (NUMBYTES(OFFSET) == 2 ? VMS_UNALIGNED_SHORT_ASM_OP : VMS_ASM_BYTE_OP))
229 #endif
231 /* Definitions of defaults for formats and names of various special
232 (artificial) labels which may be generated within this file (when the -g
233 options is used and VMS_DEBUGGING_INFO is in effect. If necessary, these
234 may be overridden from within the tm.h file, but typically, overriding these
235 defaults is unnecessary. */
237 static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
239 #ifndef TEXT_END_LABEL
240 #define TEXT_END_LABEL "Lvetext"
241 #endif
242 #ifndef FUNC_BEGIN_LABEL
243 #define FUNC_BEGIN_LABEL "LVFB"
244 #endif
245 #ifndef FUNC_PROLOG_LABEL
246 #define FUNC_PROLOG_LABEL "LVFP"
247 #endif
248 #ifndef FUNC_EPILOG_LABEL
249 #define FUNC_EPILOG_LABEL "LVEB"
250 #endif
251 #ifndef FUNC_END_LABEL
252 #define FUNC_END_LABEL "LVFE"
253 #endif
254 #ifndef BLOCK_BEGIN_LABEL
255 #define BLOCK_BEGIN_LABEL "LVBB"
256 #endif
257 #ifndef BLOCK_END_LABEL
258 #define BLOCK_END_LABEL "LVBE"
259 #endif
260 #ifndef LINE_CODE_LABEL
261 #define LINE_CODE_LABEL "LVM"
262 #endif
264 #ifndef ASM_OUTPUT_DEBUG_DELTA2
265 #define ASM_OUTPUT_DEBUG_DELTA2(FILE,LABEL1,LABEL2) \
266 do \
268 fprintf ((FILE), "\t%s\t", VMS_UNALIGNED_SHORT_ASM_OP); \
269 assemble_name (FILE, LABEL1); \
270 fprintf (FILE, "-"); \
271 assemble_name (FILE, LABEL2); \
273 while (0)
274 #endif
276 #ifndef ASM_OUTPUT_DEBUG_DELTA4
277 #define ASM_OUTPUT_DEBUG_DELTA4(FILE,LABEL1,LABEL2) \
278 do \
280 fprintf ((FILE), "\t%s\t", VMS_UNALIGNED_INT_ASM_OP); \
281 assemble_name (FILE, LABEL1); \
282 fprintf (FILE, "-"); \
283 assemble_name (FILE, LABEL2); \
285 while (0)
286 #endif
288 #ifndef ASM_OUTPUT_DEBUG_ADDR_DELTA
289 #define ASM_OUTPUT_DEBUG_ADDR_DELTA(FILE,LABEL1,LABEL2) \
290 do \
292 fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP); \
293 assemble_name (FILE, LABEL1); \
294 fprintf (FILE, "-"); \
295 assemble_name (FILE, LABEL2); \
297 while (0)
298 #endif
300 #ifndef ASM_OUTPUT_DEBUG_ADDR
301 #define ASM_OUTPUT_DEBUG_ADDR(FILE,LABEL) \
302 do \
304 fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP); \
305 assemble_name (FILE, LABEL); \
307 while (0)
308 #endif
310 #ifndef ASM_OUTPUT_DEBUG_ADDR_CONST
311 #define ASM_OUTPUT_DEBUG_ADDR_CONST(FILE,ADDR) \
312 fprintf ((FILE), "\t%s\t%s", UNALIGNED_PTR_ASM_OP, (ADDR))
313 #endif
315 #ifndef ASM_OUTPUT_DEBUG_DATA1
316 #define ASM_OUTPUT_DEBUG_DATA1(FILE,VALUE) \
317 fprintf ((FILE), "\t%s\t%#x", VMS_ASM_BYTE_OP, (unsigned char) VALUE)
318 #endif
320 #ifndef ASM_OUTPUT_DEBUG_DATA2
321 #define ASM_OUTPUT_DEBUG_DATA2(FILE,VALUE) \
322 fprintf ((FILE), "\t%s\t%#x", VMS_UNALIGNED_SHORT_ASM_OP, \
323 (unsigned short) VALUE)
324 #endif
326 #ifndef ASM_OUTPUT_DEBUG_DATA4
327 #define ASM_OUTPUT_DEBUG_DATA4(FILE,VALUE) \
328 fprintf ((FILE), "\t%s\t%#lx", VMS_UNALIGNED_INT_ASM_OP, \
329 (unsigned long) VALUE)
330 #endif
332 #ifndef ASM_OUTPUT_DEBUG_DATA
333 #define ASM_OUTPUT_DEBUG_DATA(FILE,VALUE) \
334 fprintf ((FILE), "\t%s\t%#lx", UNALIGNED_OFFSET_ASM_OP(VALUE), VALUE)
335 #endif
337 #ifndef ASM_OUTPUT_DEBUG_ADDR_DATA
338 #define ASM_OUTPUT_DEBUG_ADDR_DATA(FILE,VALUE) \
339 fprintf ((FILE), "\t%s\t%#lx", UNALIGNED_PTR_ASM_OP, \
340 (unsigned long) VALUE)
341 #endif
343 #ifndef ASM_OUTPUT_DEBUG_DATA8
344 #define ASM_OUTPUT_DEBUG_DATA8(FILE,VALUE) \
345 fprintf ((FILE), "\t%s\t%#llx", VMS_UNALIGNED_DOUBLE_INT_ASM_OP, \
346 (unsigned long long) VALUE)
347 #endif
349 /* This is similar to the default ASM_OUTPUT_ASCII, except that no trailing
350 newline is produced. When flag_verbose_asm is asserted, we add commentary
351 at the end of the line, so we must avoid output of a newline here. */
352 #ifndef ASM_OUTPUT_DEBUG_STRING
353 #define ASM_OUTPUT_DEBUG_STRING(FILE,P) \
354 do \
356 register int slen = strlen(P); \
357 register const char *p = (P); \
358 register int i; \
359 fprintf (FILE, "\t.ascii \""); \
360 for (i = 0; i < slen; i++) \
362 register int c = p[i]; \
363 if (c == '\"' || c == '\\') \
364 putc ('\\', FILE); \
365 if (c >= ' ' && c < 0177) \
366 putc (c, FILE); \
367 else \
368 fprintf (FILE, "\\%o", c); \
370 fprintf (FILE, "\""); \
372 while (0)
373 #endif
375 /* Convert a reference to the assembler name of a C-level name. This
376 macro has the same effect as ASM_OUTPUT_LABELREF, but copies to
377 a string rather than writing to a file. */
378 #ifndef ASM_NAME_TO_STRING
379 #define ASM_NAME_TO_STRING(STR, NAME) \
380 do \
382 if ((NAME)[0] == '*') \
383 strcpy (STR, NAME+1); \
384 else \
385 strcpy (STR, NAME); \
387 while (0)
388 #endif
391 /* Output the debug header HEADER. Also output COMMENT if flag_verbose_asm is
392 set. Return the header size. Just return the size if DOSIZEONLY is
393 nonzero. */
395 static int
396 write_debug_header (DST_HEADER *header, const char *comment, int dosizeonly)
398 if (!dosizeonly)
400 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file,
401 header->dst__header_length.dst_w_length);
403 if (flag_verbose_asm)
404 fprintf (asm_out_file, "\t%s record length", ASM_COMMENT_START);
405 fputc ('\n', asm_out_file);
407 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file,
408 header->dst__header_type.dst_w_type);
410 if (flag_verbose_asm)
411 fprintf (asm_out_file, "\t%s record type (%s)", ASM_COMMENT_START,
412 comment);
414 fputc ('\n', asm_out_file);
417 return 4;
420 /* Output the address of SYMBOL. Also output COMMENT if flag_verbose_asm is
421 set. Return the address size. Just return the size if DOSIZEONLY is
422 nonzero. */
424 static int
425 write_debug_addr (const char *symbol, const char *comment, int dosizeonly)
427 if (!dosizeonly)
429 ASM_OUTPUT_DEBUG_ADDR (asm_out_file, symbol);
430 if (flag_verbose_asm)
431 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
432 fputc ('\n', asm_out_file);
435 return PTR_SIZE;
438 /* Output the single byte DATA1. Also output COMMENT if flag_verbose_asm is
439 set. Return the data size. Just return the size if DOSIZEONLY is
440 nonzero. */
442 static int
443 write_debug_data1 (unsigned int data1, const char *comment, int dosizeonly)
445 if (!dosizeonly)
447 ASM_OUTPUT_DEBUG_DATA1 (asm_out_file, data1);
448 if (flag_verbose_asm)
449 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
450 fputc ('\n', asm_out_file);
453 return 1;
456 /* Output the single word DATA2. Also output COMMENT if flag_verbose_asm is
457 set. Return the data size. Just return the size if DOSIZEONLY is
458 nonzero. */
460 static int
461 write_debug_data2 (unsigned int data2, const char *comment, int dosizeonly)
463 if (!dosizeonly)
465 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file, data2);
466 if (flag_verbose_asm)
467 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
468 fputc ('\n', asm_out_file);
471 return 2;
474 /* Output double word DATA4. Also output COMMENT if flag_verbose_asm is set.
475 Return the data size. Just return the size if DOSIZEONLY is nonzero. */
477 static int
478 write_debug_data4 (unsigned long data4, const char *comment, int dosizeonly)
480 if (!dosizeonly)
482 ASM_OUTPUT_DEBUG_DATA4 (asm_out_file, data4);
483 if (flag_verbose_asm)
484 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
485 fputc ('\n', asm_out_file);
488 return 4;
491 /* Output quad word DATA8. Also output COMMENT if flag_verbose_asm is set.
492 Return the data size. Just return the size if DOSIZEONLY is nonzero. */
494 static int
495 write_debug_data8 (unsigned long long data8, const char *comment,
496 int dosizeonly)
498 if (!dosizeonly)
500 ASM_OUTPUT_DEBUG_DATA8 (asm_out_file, data8);
501 if (flag_verbose_asm)
502 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
503 fputc ('\n', asm_out_file);
506 return 8;
509 /* Output the difference between LABEL1 and LABEL2. Also output COMMENT if
510 flag_verbose_asm is set. Return the data size. Just return the size if
511 DOSIZEONLY is nonzero. */
513 static int
514 write_debug_delta4 (const char *label1, const char *label2,
515 const char *comment, int dosizeonly)
517 if (!dosizeonly)
519 ASM_OUTPUT_DEBUG_DELTA4 (asm_out_file, label1, label2);
520 if (flag_verbose_asm)
521 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
522 fputc ('\n', asm_out_file);
525 return 4;
528 /* Output a character string STRING. Also write COMMENT if flag_verbose_asm is
529 set. Return the string length. Just return the length if DOSIZEONLY is
530 nonzero. */
532 static int
533 write_debug_string (const char *string, const char *comment, int dosizeonly)
535 if (!dosizeonly)
537 ASM_OUTPUT_DEBUG_STRING (asm_out_file, string);
538 if (flag_verbose_asm)
539 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
540 fputc ('\n', asm_out_file);
543 return strlen (string);
546 /* Output a module begin header and return the header size. Just return the
547 size if DOSIZEONLY is nonzero. */
549 static int
550 write_modbeg (int dosizeonly)
552 DST_MODULE_BEGIN modbeg;
553 DST_MB_TRLR mb_trlr;
554 int i;
555 char *module_name, *m;
556 int modnamelen;
557 int prodnamelen;
558 int totsize = 0;
560 /* Assumes primary filename has Unix syntax file spec. */
561 module_name = xstrdup (lbasename (primary_filename));
563 m = strrchr (module_name, '.');
564 if (m)
565 *m = 0;
567 modnamelen = strlen (module_name);
568 for (i = 0; i < modnamelen; i++)
569 module_name[i] = TOUPPER (module_name[i]);
571 prodnamelen = strlen (module_producer);
573 modbeg.dst_a_modbeg_header.dst__header_length.dst_w_length
574 = DST_K_MODBEG_SIZE + modnamelen + DST_K_MB_TRLR_SIZE + prodnamelen - 1;
575 modbeg.dst_a_modbeg_header.dst__header_type.dst_w_type = DST_K_MODBEG;
576 modbeg.dst_b_modbeg_flags.dst_v_modbeg_hide = 0;
577 modbeg.dst_b_modbeg_flags.dst_v_modbeg_version = 1;
578 modbeg.dst_b_modbeg_flags.dst_v_modbeg_unused = 0;
579 modbeg.dst_b_modbeg_unused = 0;
580 modbeg.dst_l_modbeg_language = (DST_LANGUAGE) module_language;
581 modbeg.dst_w_version_major = DST_K_VERSION_MAJOR;
582 modbeg.dst_w_version_minor = DST_K_VERSION_MINOR;
583 modbeg.dst_b_modbeg_name = strlen (module_name);
585 mb_trlr.dst_b_compiler = strlen (module_producer);
587 totsize += write_debug_header (&modbeg.dst_a_modbeg_header,
588 "modbeg", dosizeonly);
589 totsize += write_debug_data1 (*((char *) &modbeg.dst_b_modbeg_flags),
590 "flags", dosizeonly);
591 totsize += write_debug_data1 (modbeg.dst_b_modbeg_unused,
592 "unused", dosizeonly);
593 totsize += write_debug_data4 (modbeg.dst_l_modbeg_language,
594 "language", dosizeonly);
595 totsize += write_debug_data2 (modbeg.dst_w_version_major,
596 "DST major version", dosizeonly);
597 totsize += write_debug_data2 (modbeg.dst_w_version_minor,
598 "DST minor version", dosizeonly);
599 totsize += write_debug_data1 (modbeg.dst_b_modbeg_name,
600 "length of module name", dosizeonly);
601 totsize += write_debug_string (module_name, "module name", dosizeonly);
602 totsize += write_debug_data1 (mb_trlr.dst_b_compiler,
603 "length of compiler name", dosizeonly);
604 totsize += write_debug_string (module_producer, "compiler name", dosizeonly);
606 return totsize;
609 /* Output a module end trailer and return the trailer size. Just return
610 the size if DOSIZEONLY is nonzero. */
612 static int
613 write_modend (int dosizeonly)
615 DST_MODULE_END modend;
616 int totsize = 0;
618 modend.dst_a_modend_header.dst__header_length.dst_w_length
619 = DST_K_MODEND_SIZE - 1;
620 modend.dst_a_modend_header.dst__header_type.dst_w_type = DST_K_MODEND;
622 totsize += write_debug_header (&modend.dst_a_modend_header, "modend",
623 dosizeonly);
625 return totsize;
628 /* Output a routine begin header routine RTNNUM and return the header size.
629 Just return the size if DOSIZEONLY is nonzero. */
631 static int
632 write_rtnbeg (int rtnnum, int dosizeonly)
634 const char *rtnname;
635 int rtnnamelen;
636 char *rtnentryname;
637 int totsize = 0;
638 char label[MAX_ARTIFICIAL_LABEL_BYTES];
639 DST_ROUTINE_BEGIN rtnbeg;
640 DST_PROLOG prolog;
642 rtnname = funcnam_table[rtnnum];
643 rtnnamelen = strlen (rtnname);
644 rtnentryname = concat (rtnname, "..en", NULL);
646 if (!strcmp (rtnname, "main"))
648 DST_HEADER header;
649 const char *go = "TRANSFER$BREAK$GO";
651 /* This command isn't documented in DSTRECORDS, so it's made to
652 look like what DEC C does */
654 /* header size - 1st byte + flag byte + STO_LW size
655 + string count byte + string length */
656 header.dst__header_length.dst_w_length
657 = DST_K_DST_HEADER_SIZE - 1 + 1 + 4 + 1 + strlen (go);
658 header.dst__header_type.dst_w_type = DST_K_TBG;
660 totsize += write_debug_header (&header, "transfer", dosizeonly);
662 /* I think this is a flag byte, but I don't know what this flag means */
663 totsize += write_debug_data1 (0x1, "flags ???", dosizeonly);
665 /* Routine Begin PD Address */
666 totsize += write_debug_addr (rtnname, "main procedure descriptor",
667 dosizeonly);
668 totsize += write_debug_data1 (strlen (go), "length of main_name",
669 dosizeonly);
670 totsize += write_debug_string (go, "main name", dosizeonly);
673 /* The header length never includes the length byte. */
674 rtnbeg.dst_a_rtnbeg_header.dst__header_length.dst_w_length
675 = DST_K_RTNBEG_SIZE + rtnnamelen - 1;
676 rtnbeg.dst_a_rtnbeg_header.dst__header_type.dst_w_type = DST_K_RTNBEG;
677 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_unused = 0;
678 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_unalloc = 0;
679 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_prototype = 0;
680 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_inlined = 0;
681 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_no_call = 1;
682 rtnbeg.dst_b_rtnbeg_name = rtnnamelen;
684 totsize += write_debug_header (&rtnbeg.dst_a_rtnbeg_header, "rtnbeg",
685 dosizeonly);
686 totsize += write_debug_data1 (*((char *) &rtnbeg.dst_b_rtnbeg_flags),
687 "flags", dosizeonly);
689 /* Routine Begin Address */
690 totsize += write_debug_addr (rtnentryname, "routine entry name", dosizeonly);
692 /* Routine Begin PD Address */
693 totsize += write_debug_addr (rtnname, "routine procedure descriptor",
694 dosizeonly);
696 /* Routine Begin Name */
697 totsize += write_debug_data1 (rtnbeg.dst_b_rtnbeg_name,
698 "length of routine name", dosizeonly);
700 totsize += write_debug_string (rtnname, "routine name", dosizeonly);
702 free (rtnentryname);
704 if (debug_info_level > DINFO_LEVEL_TERSE)
706 prolog.dst_a_prolog_header.dst__header_length.dst_w_length
707 = DST_K_PROLOG_SIZE - 1;
708 prolog.dst_a_prolog_header.dst__header_type.dst_w_type = DST_K_PROLOG;
710 totsize += write_debug_header (&prolog.dst_a_prolog_header, "prolog",
711 dosizeonly);
713 ASM_GENERATE_INTERNAL_LABEL
714 (label, FUNC_PROLOG_LABEL,
715 funcnum_table[rtnnum]);
716 totsize += write_debug_addr (label, "prolog breakpoint addr",
717 dosizeonly);
720 return totsize;
723 /* Output a routine end trailer for routine RTNNUM and return the header size.
724 Just return the size if DOSIZEONLY is nonzero. */
726 static int
727 write_rtnend (int rtnnum, int dosizeonly)
729 DST_ROUTINE_END rtnend;
730 char label1[MAX_ARTIFICIAL_LABEL_BYTES];
731 char label2[MAX_ARTIFICIAL_LABEL_BYTES];
732 int totsize;
734 totsize = 0;
736 rtnend.dst_a_rtnend_header.dst__header_length.dst_w_length
737 = DST_K_RTNEND_SIZE - 1;
738 rtnend.dst_a_rtnend_header.dst__header_type.dst_w_type = DST_K_RTNEND;
739 rtnend.dst_b_rtnend_unused = 0;
740 rtnend.dst_l_rtnend_size = 0; /* Calculated below. */
742 totsize += write_debug_header (&rtnend.dst_a_rtnend_header, "rtnend",
743 dosizeonly);
744 totsize += write_debug_data1 (rtnend.dst_b_rtnend_unused, "unused",
745 dosizeonly);
747 ASM_GENERATE_INTERNAL_LABEL
748 (label1, FUNC_BEGIN_LABEL,
749 funcnum_table[rtnnum]);
750 ASM_GENERATE_INTERNAL_LABEL
751 (label2, FUNC_END_LABEL,
752 funcnum_table[rtnnum]);
753 totsize += write_debug_delta4 (label2, label1, "routine size", dosizeonly);
755 return totsize;
758 #define K_DELTA_PC(I) \
759 ((I) < 128 ? -(I) : (I) < 65536 ? DST_K_DELTA_PC_W : DST_K_DELTA_PC_L)
761 #define K_SET_LINUM(I) \
762 ((I) < 256 ? DST_K_SET_LINUM_B \
763 : (I) < 65536 ? DST_K_SET_LINUM : DST_K_SET_LINUM_L)
765 #define K_INCR_LINUM(I) \
766 ((I) < 256 ? DST_K_INCR_LINUM \
767 : (I) < 65536 ? DST_K_INCR_LINUM_W : DST_K_INCR_LINUM_L)
769 /* Output the PC to line number correlations and return the size. Just return
770 the size if DOSIZEONLY is nonzero */
772 static int
773 write_pclines (int dosizeonly)
775 unsigned i;
776 int fn;
777 int ln, lastln;
778 int linestart = 0;
779 int max_line;
780 DST_LINE_NUM_HEADER line_num;
781 DST_PCLINE_COMMANDS pcline;
782 char label[MAX_ARTIFICIAL_LABEL_BYTES];
783 char lastlabel[MAX_ARTIFICIAL_LABEL_BYTES];
784 int totsize = 0;
785 char buff[256];
787 max_line = file_info_table[1].max_line;
788 file_info_table[1].listing_line_start = linestart;
789 linestart = linestart + ((max_line / 100000) + 1) * 100000;
791 for (i = 2; i < file_info_table_in_use; i++)
793 max_line = file_info_table[i].max_line;
794 file_info_table[i].listing_line_start = linestart;
795 linestart = linestart + ((max_line / 10000) + 1) * 10000;
798 /* Set starting address to beginning of text section. */
799 line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 8;
800 line_num.dst_a_line_num_header.dst__header_type.dst_w_type = DST_K_LINE_NUM;
801 pcline.dst_b_pcline_command = DST_K_SET_ABS_PC;
803 totsize += write_debug_header (&line_num.dst_a_line_num_header,
804 "line_num", dosizeonly);
805 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
806 "line_num (SET ABS PC)", dosizeonly);
808 if (dosizeonly)
809 totsize += 4;
810 else
812 ASM_OUTPUT_DEBUG_ADDR (asm_out_file, TEXT_SECTION_ASM_OP);
813 if (flag_verbose_asm)
814 fprintf (asm_out_file, "\t%s line_num", ASM_COMMENT_START);
815 fputc ('\n', asm_out_file);
818 fn = line_info_table[1].dst_file_num;
819 ln = (file_info_table[fn].listing_line_start
820 + line_info_table[1].dst_line_num);
821 line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 4 + 4;
822 pcline.dst_b_pcline_command = DST_K_SET_LINUM_L;
824 totsize += write_debug_header (&line_num.dst_a_line_num_header,
825 "line_num", dosizeonly);
826 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
827 "line_num (SET LINUM LONG)", dosizeonly);
829 sprintf (buff, "line_num (%d)", ln ? ln - 1 : 0);
830 totsize += write_debug_data4 (ln ? ln - 1 : 0, buff, dosizeonly);
832 lastln = ln;
833 strcpy (lastlabel, TEXT_SECTION_ASM_OP);
834 for (i = 1; i < line_info_table_in_use; i++)
836 int extrabytes;
838 fn = line_info_table[i].dst_file_num;
839 ln = (file_info_table[fn].listing_line_start
840 + line_info_table[i].dst_line_num);
842 if (ln - lastln > 1)
843 extrabytes = 5; /* NUMBYTES (ln - lastln - 1) + 1; */
844 else if (ln <= lastln)
845 extrabytes = 5; /* NUMBYTES (ln - 1) + 1; */
846 else
847 extrabytes = 0;
849 line_num.dst_a_line_num_header.dst__header_length.dst_w_length
850 = 8 + extrabytes;
852 totsize += write_debug_header
853 (&line_num.dst_a_line_num_header, "line_num", dosizeonly);
855 if (ln - lastln > 1)
857 int lndif = ln - lastln - 1;
859 /* K_INCR_LINUM (lndif); */
860 pcline.dst_b_pcline_command = DST_K_INCR_LINUM_L;
862 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
863 "line_num (INCR LINUM LONG)",
864 dosizeonly);
866 sprintf (buff, "line_num (%d)", lndif);
867 totsize += write_debug_data4 (lndif, buff, dosizeonly);
869 else if (ln <= lastln)
871 /* K_SET_LINUM (ln-1); */
872 pcline.dst_b_pcline_command = DST_K_SET_LINUM_L;
874 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
875 "line_num (SET LINUM LONG)",
876 dosizeonly);
878 sprintf (buff, "line_num (%d)", ln - 1);
879 totsize += write_debug_data4 (ln - 1, buff, dosizeonly);
882 pcline.dst_b_pcline_command = DST_K_DELTA_PC_L;
884 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
885 "line_num (DELTA PC LONG)", dosizeonly);
887 ASM_GENERATE_INTERNAL_LABEL (label, LINE_CODE_LABEL, i);
888 totsize += write_debug_delta4 (label, lastlabel, "increment line_num",
889 dosizeonly);
891 lastln = ln;
892 strcpy (lastlabel, label);
895 return totsize;
898 /* Output a source correlation for file FILEID using information saved in
899 FILE_INFO_ENTRY and return the size. Just return the size if DOSIZEONLY is
900 nonzero. */
902 static int
903 write_srccorr (int fileid, dst_file_info_entry file_info_entry,
904 int dosizeonly)
906 int src_command_size;
907 int linesleft = file_info_entry.max_line;
908 int linestart = file_info_entry.listing_line_start;
909 int flen = strlen (file_info_entry.file_name);
910 int linestodo = 0;
911 DST_SOURCE_CORR src_header;
912 DST_SRC_COMMAND src_command;
913 DST_SRC_COMMAND src_command_sf;
914 DST_SRC_COMMAND src_command_sl;
915 DST_SRC_COMMAND src_command_sr;
916 DST_SRC_COMMAND src_command_dl;
917 DST_SRC_CMDTRLR src_cmdtrlr;
918 char buff[256];
919 int totsize = 0;
921 if (fileid == 1)
923 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
924 = DST_K_SOURCE_CORR_HEADER_SIZE + 1 - 1;
925 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
926 = DST_K_SOURCE;
927 src_command.dst_b_src_command = DST_K_SRC_FORMFEED;
929 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
930 "source corr", dosizeonly);
932 totsize += write_debug_data1 (src_command.dst_b_src_command,
933 "source_corr (SRC FORMFEED)",
934 dosizeonly);
937 src_command_size
938 = DST_K_SRC_COMMAND_SIZE + flen + DST_K_SRC_CMDTRLR_SIZE;
939 src_command.dst_b_src_command = DST_K_SRC_DECLFILE;
940 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_length
941 = src_command_size - 2;
942 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_flags = 0;
943 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_fileid
944 = fileid;
945 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt
946 = file_info_entry.cdt;
947 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk
948 = file_info_entry.ebk;
949 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_rms_ffb
950 = file_info_entry.ffb;
951 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_rms_rfo
952 = file_info_entry.rfo;
953 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename
954 = flen;
956 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
957 = DST_K_SOURCE_CORR_HEADER_SIZE + src_command_size - 1;
958 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
959 = DST_K_SOURCE;
961 src_cmdtrlr.dst_b_src_df_libmodname = 0;
963 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
964 "source corr", dosizeonly);
965 totsize += write_debug_data1 (src_command.dst_b_src_command,
966 "source_corr (DECL SRC FILE)", dosizeonly);
967 totsize += write_debug_data1
968 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_length,
969 "source_corr (length)", dosizeonly);
971 totsize += write_debug_data1
972 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_flags,
973 "source_corr (flags)", dosizeonly);
975 totsize += write_debug_data2
976 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_fileid,
977 "source_corr (fileid)", dosizeonly);
979 totsize += write_debug_data8
980 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt,
981 "source_corr (creation date)", dosizeonly);
983 totsize += write_debug_data4
984 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk,
985 "source_corr (EOF block number)", dosizeonly);
987 totsize += write_debug_data2
988 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_rms_ffb,
989 "source_corr (first free byte)", dosizeonly);
991 totsize += write_debug_data1
992 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_rms_rfo,
993 "source_corr (record and file organization)", dosizeonly);
995 totsize += write_debug_data1
996 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename,
997 "source_corr (filename length)", dosizeonly);
999 totsize += write_debug_string (remap_debug_filename (
1000 file_info_entry.file_name),
1001 "source file name", dosizeonly);
1002 totsize += write_debug_data1 (src_cmdtrlr.dst_b_src_df_libmodname,
1003 "source_corr (libmodname)", dosizeonly);
1005 src_command_sf.dst_b_src_command = DST_K_SRC_SETFILE;
1006 src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword = fileid;
1008 src_command_sr.dst_b_src_command = DST_K_SRC_SETREC_W;
1009 src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword = 1;
1011 src_command_sl.dst_b_src_command = DST_K_SRC_SETLNUM_L;
1012 src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong = linestart + 1;
1014 src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W;
1016 if (linesleft > 65534)
1017 linesleft = linesleft - 65534, linestodo = 65534;
1018 else
1019 linestodo = linesleft, linesleft = 0;
1021 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo;
1023 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1024 = DST_K_SOURCE_CORR_HEADER_SIZE + 3 + 3 + 5 + 3 - 1;
1025 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1026 = DST_K_SOURCE;
1028 if (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword)
1030 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1031 "source corr", dosizeonly);
1033 totsize += write_debug_data1 (src_command_sf.dst_b_src_command,
1034 "source_corr (src setfile)", dosizeonly);
1036 totsize += write_debug_data2
1037 (src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword,
1038 "source_corr (fileid)", dosizeonly);
1040 totsize += write_debug_data1 (src_command_sr.dst_b_src_command,
1041 "source_corr (setrec)", dosizeonly);
1043 totsize += write_debug_data2
1044 (src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword,
1045 "source_corr (recnum)", dosizeonly);
1047 totsize += write_debug_data1 (src_command_sl.dst_b_src_command,
1048 "source_corr (setlnum)", dosizeonly);
1050 totsize += write_debug_data4
1051 (src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong,
1052 "source_corr (linenum)", dosizeonly);
1054 totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
1055 "source_corr (deflines)", dosizeonly);
1057 sprintf (buff, "source_corr (%d)",
1058 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
1059 totsize += write_debug_data2
1060 (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword,
1061 buff, dosizeonly);
1063 while (linesleft > 0)
1065 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1066 = DST_K_SOURCE_CORR_HEADER_SIZE + 3 - 1;
1067 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1068 = DST_K_SOURCE;
1069 src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W;
1071 if (linesleft > 65534)
1072 linesleft = linesleft - 65534, linestodo = 65534;
1073 else
1074 linestodo = linesleft, linesleft = 0;
1076 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo;
1078 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1079 "source corr", dosizeonly);
1080 totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
1081 "source_corr (deflines)", dosizeonly);
1082 sprintf (buff, "source_corr (%d)",
1083 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
1084 totsize += write_debug_data2
1085 (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword,
1086 buff, dosizeonly);
1090 return totsize;
1093 /* Output all the source correlation entries and return the size. Just return
1094 the size if DOSIZEONLY is nonzero. */
1096 static int
1097 write_srccorrs (int dosizeonly)
1099 unsigned int i;
1100 int totsize = 0;
1102 for (i = 1; i < file_info_table_in_use; i++)
1103 totsize += write_srccorr (i, file_info_table[i], dosizeonly);
1105 return totsize;
1108 /* Output a marker (i.e. a label) for the beginning of a function, before
1109 the prologue. */
1111 static void
1112 vmsdbgout_begin_prologue (unsigned int line, const char *file)
1114 char label[MAX_ARTIFICIAL_LABEL_BYTES];
1116 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1117 (*dwarf2_debug_hooks.begin_prologue) (line, file);
1119 if (debug_info_level > DINFO_LEVEL_NONE)
1121 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL,
1122 current_function_funcdef_no);
1123 ASM_OUTPUT_LABEL (asm_out_file, label);
1127 /* Output a marker (i.e. a label) for the beginning of a function, after
1128 the prologue. */
1130 static void
1131 vmsdbgout_end_prologue (unsigned int line, const char *file)
1133 char label[MAX_ARTIFICIAL_LABEL_BYTES];
1135 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1136 (*dwarf2_debug_hooks.end_prologue) (line, file);
1138 if (debug_info_level > DINFO_LEVEL_TERSE)
1140 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL,
1141 current_function_funcdef_no);
1142 ASM_OUTPUT_LABEL (asm_out_file, label);
1144 /* VMS PCA expects every PC range to correlate to some line and file. */
1145 vmsdbgout_write_source_line (line, file, 0, true);
1149 /* No output for VMS debug, but make obligatory call to Dwarf2 debug */
1151 static void
1152 vmsdbgout_end_function (unsigned int line)
1154 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1155 (*dwarf2_debug_hooks.end_function) (line);
1158 /* Output a marker (i.e. a label) for the beginning of the epilogue.
1159 This gets called *before* the epilogue code has been generated. */
1161 static void
1162 vmsdbgout_begin_epilogue (unsigned int line, const char *file)
1164 char label[MAX_ARTIFICIAL_LABEL_BYTES];
1165 static int save_current_function_funcdef_no = -1;
1167 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1168 (*dwarf2_debug_hooks.begin_epilogue) (line, file);
1170 if (debug_info_level > DINFO_LEVEL_NONE)
1172 if (save_current_function_funcdef_no != current_function_funcdef_no)
1174 /* Output a label to mark the endpoint of the code generated for this
1175 function. */
1176 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_EPILOG_LABEL,
1177 current_function_funcdef_no);
1179 ASM_OUTPUT_LABEL (asm_out_file, label);
1181 save_current_function_funcdef_no = current_function_funcdef_no;
1183 /* VMS PCA expects every PC range to correlate to some line and
1184 file. */
1185 vmsdbgout_write_source_line (line, file, 0, true);
1190 /* Output a marker (i.e. a label) for the absolute end of the generated code
1191 for a function definition. This gets called *after* the epilogue code has
1192 been generated. */
1194 static void
1195 vmsdbgout_end_epilogue (unsigned int line, const char *file)
1197 char label[MAX_ARTIFICIAL_LABEL_BYTES];
1199 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1200 (*dwarf2_debug_hooks.end_epilogue) (line, file);
1202 if (debug_info_level > DINFO_LEVEL_NONE)
1204 /* Output a label to mark the endpoint of the code generated for this
1205 function. */
1206 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL,
1207 current_function_funcdef_no);
1208 ASM_OUTPUT_LABEL (asm_out_file, label);
1210 /* VMS PCA expects every PC range to correlate to some line and file. */
1211 vmsdbgout_write_source_line (line, file, 0, true);
1215 /* Output a marker (i.e. a label) for the beginning of the generated code for
1216 a lexical block. */
1218 static void
1219 vmsdbgout_begin_block (register unsigned line, register unsigned blocknum)
1221 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1222 (*dwarf2_debug_hooks.begin_block) (line, blocknum);
1224 if (debug_info_level > DINFO_LEVEL_TERSE)
1225 targetm.asm_out.internal_label (asm_out_file, BLOCK_BEGIN_LABEL, blocknum);
1228 /* Output a marker (i.e. a label) for the end of the generated code for a
1229 lexical block. */
1231 static void
1232 vmsdbgout_end_block (register unsigned line, register unsigned blocknum)
1234 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1235 (*dwarf2_debug_hooks.end_block) (line, blocknum);
1237 if (debug_info_level > DINFO_LEVEL_TERSE)
1238 targetm.asm_out.internal_label (asm_out_file, BLOCK_END_LABEL, blocknum);
1241 /* Not implemented in VMS Debug. */
1243 static bool
1244 vmsdbgout_ignore_block (const_tree block)
1246 bool retval = 0;
1248 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1249 retval = (*dwarf2_debug_hooks.ignore_block) (block);
1251 return retval;
1254 /* Add an entry for function DECL into the funcnam_table. */
1256 static void
1257 vmsdbgout_begin_function (tree decl)
1259 const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
1261 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1262 (*dwarf2_debug_hooks.begin_function) (decl);
1264 /* Add the new entry to the end of the function name table. */
1265 funcnam_table.safe_push (xstrdup (name));
1266 funcnum_table.safe_push (current_function_funcdef_no);
1269 static char fullname_buff [4096];
1271 /* Return the full file specification for FILENAME. The specification must be
1272 in VMS syntax in order to be processed by VMS Debug. */
1274 static char *
1275 full_name (const char *filename)
1277 #ifdef VMS
1278 FILE *fp = fopen (filename, "r");
1280 fgetname (fp, fullname_buff, 1);
1281 fclose (fp);
1282 #else
1283 /* Unix paths really mess up VMS debug. Better to just output the
1284 base filename. */
1285 strcpy (fullname_buff, filename);
1286 #endif
1288 return fullname_buff;
1291 /* Lookup a filename (in the list of filenames that we know about here in
1292 vmsdbgout.c) and return its "index". The index of each (known) filename is
1293 just a unique number which is associated with only that one filename. We
1294 need such numbers for the sake of generating labels and references
1295 to those files numbers. If the filename given as an argument is not
1296 found in our current list, add it to the list and assign it the next
1297 available unique index number. In order to speed up searches, we remember
1298 the index of the filename was looked up last. This handles the majority of
1299 all searches. */
1301 static unsigned int
1302 lookup_filename (const char *file_name)
1304 static unsigned int last_file_lookup_index = 0;
1305 register char *fn;
1306 register unsigned i;
1307 const char *fnam;
1308 long long cdt = 0;
1309 long ebk = 0;
1310 short ffb = 0;
1311 char rfo = 0;
1312 long siz = 0;
1313 int ver = 0;
1315 fnam = full_name (file_name);
1317 /* Check to see if the file name that was searched on the previous call
1318 matches this file name. If so, return the index. */
1319 if (last_file_lookup_index != 0)
1321 fn = file_info_table[last_file_lookup_index].file_name;
1322 if (strcmp (fnam, fn) == 0)
1323 return last_file_lookup_index;
1326 /* Didn't match the previous lookup, search the table */
1327 for (i = 1; i < file_info_table_in_use; ++i)
1329 fn = file_info_table[i].file_name;
1330 if (strcmp (fnam, fn) == 0)
1332 last_file_lookup_index = i;
1333 return i;
1337 /* Prepare to add a new table entry by making sure there is enough space in
1338 the table to do so. If not, expand the current table. */
1339 if (file_info_table_in_use == file_info_table_allocated)
1342 file_info_table_allocated += FILE_TABLE_INCREMENT;
1343 file_info_table = XRESIZEVEC (dst_file_info_entry, file_info_table,
1344 file_info_table_allocated);
1347 if (vms_file_stats_name (file_name, &cdt, &siz, &rfo, &ver) == 0)
1349 ebk = siz / 512 + 1;
1350 ffb = siz - ((siz / 512) * 512);
1353 /* Add the new entry to the end of the filename table. */
1354 file_info_table[file_info_table_in_use].file_name = xstrdup (fnam);
1355 file_info_table[file_info_table_in_use].max_line = 0;
1356 file_info_table[file_info_table_in_use].cdt = cdt;
1357 file_info_table[file_info_table_in_use].ebk = ebk;
1358 file_info_table[file_info_table_in_use].ffb = ffb;
1359 file_info_table[file_info_table_in_use].rfo = rfo;
1361 last_file_lookup_index = file_info_table_in_use++;
1362 return last_file_lookup_index;
1365 /* Output a label to mark the beginning of a source code line entry
1366 and record information relating to this source line, in
1367 'line_info_table' for later output of the .debug_line section. */
1369 static void
1370 vmsdbgout_write_source_line (unsigned line, const char *filename,
1371 int /* discriminator */, bool /* is_stmt */)
1373 dst_line_info_ref line_info;
1375 targetm.asm_out.internal_label (asm_out_file, LINE_CODE_LABEL,
1376 line_info_table_in_use);
1378 /* Expand the line info table if necessary. */
1379 if (line_info_table_in_use == line_info_table_allocated)
1381 line_info_table_allocated += LINE_INFO_TABLE_INCREMENT;
1382 line_info_table = XRESIZEVEC (dst_line_info_entry, line_info_table,
1383 line_info_table_allocated);
1386 /* Add the new entry at the end of the line_info_table. */
1387 line_info = &line_info_table[line_info_table_in_use++];
1388 line_info->dst_file_num = lookup_filename (filename);
1389 line_info->dst_line_num = line;
1390 if (line > file_info_table[line_info->dst_file_num].max_line)
1391 file_info_table[line_info->dst_file_num].max_line = line;
1394 static void
1395 vmsdbgout_source_line (register unsigned line, register const char *filename,
1396 int discriminator, bool is_stmt)
1398 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1399 (*dwarf2_debug_hooks.source_line) (line, filename, discriminator, is_stmt);
1401 if (debug_info_level >= DINFO_LEVEL_TERSE)
1402 vmsdbgout_write_source_line (line, filename, discriminator, is_stmt);
1405 /* Record the beginning of a new source file, for later output.
1406 At present, unimplemented. */
1408 static void
1409 vmsdbgout_start_source_file (unsigned int lineno, const char *filename)
1411 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1412 (*dwarf2_debug_hooks.start_source_file) (lineno, filename);
1415 /* Record the end of a source file, for later output.
1416 At present, unimplemented. */
1418 static void
1419 vmsdbgout_end_source_file (unsigned int lineno ATTRIBUTE_UNUSED)
1421 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1422 (*dwarf2_debug_hooks.end_source_file) (lineno);
1425 /* Set up for Debug output at the start of compilation. */
1427 static void
1428 vmsdbgout_init (const char *filename)
1430 const char *language_string = lang_hooks.name;
1432 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1433 (*dwarf2_debug_hooks.init) (filename);
1435 if (debug_info_level == DINFO_LEVEL_NONE)
1436 return;
1438 /* Remember the name of the primary input file. */
1439 primary_filename = filename;
1441 /* Allocate the initial hunk of the file_info_table. */
1442 file_info_table = XCNEWVEC (dst_file_info_entry, FILE_TABLE_INCREMENT);
1443 file_info_table_allocated = FILE_TABLE_INCREMENT;
1444 /* Skip the first entry - file numbers begin at 1. */
1445 file_info_table_in_use = 1;
1447 funcnam_table.create (FUNC_TABLE_INITIAL);
1448 funcnum_table.create (FUNC_TABLE_INITIAL);
1450 /* Allocate the initial hunk of the line_info_table. */
1451 line_info_table = XCNEWVEC (dst_line_info_entry, LINE_INFO_TABLE_INCREMENT);
1452 line_info_table_allocated = LINE_INFO_TABLE_INCREMENT;
1453 /* zero-th entry is allocated, but unused */
1454 line_info_table_in_use = 1;
1456 lookup_filename (primary_filename);
1458 if (!strcmp (language_string, "GNU C"))
1459 module_language = DST_K_C;
1460 else if (!strcmp (language_string, "GNU C++"))
1461 module_language = DST_K_CXX;
1462 else if (!strcmp (language_string, "GNU Ada"))
1463 module_language = DST_K_ADA;
1464 else if (!strcmp (language_string, "GNU F77"))
1465 module_language = DST_K_FORTRAN;
1466 else
1467 module_language = DST_K_UNKNOWN;
1469 module_producer = concat (language_string, " ", version_string, NULL);
1471 ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
1475 /* Not implemented in VMS Debug. */
1477 static void
1478 vmsdbgout_assembly_start (void)
1480 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1481 (*dwarf2_debug_hooks.assembly_start) ();
1484 /* Not implemented in VMS Debug. */
1486 static void
1487 vmsdbgout_define (unsigned int lineno, const char *buffer)
1489 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1490 (*dwarf2_debug_hooks.define) (lineno, buffer);
1493 /* Not implemented in VMS Debug. */
1495 static void
1496 vmsdbgout_undef (unsigned int lineno, const char *buffer)
1498 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1499 (*dwarf2_debug_hooks.undef) (lineno, buffer);
1502 /* Not implemented in VMS Debug. */
1504 static void
1505 vmsdbgout_decl (tree decl)
1507 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1508 (*dwarf2_debug_hooks.function_decl) (decl);
1511 /* Not implemented in VMS Debug. */
1513 static void
1514 vmsdbgout_global_decl (tree decl)
1516 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1517 (*dwarf2_debug_hooks.global_decl) (decl);
1520 /* Not implemented in VMS Debug. */
1522 static void
1523 vmsdbgout_type_decl (tree decl, int local)
1525 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1526 (*dwarf2_debug_hooks.type_decl) (decl, local);
1529 /* Not implemented in VMS Debug. */
1531 static void
1532 vmsdbgout_abstract_function (tree decl)
1534 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1535 (*dwarf2_debug_hooks.outlining_inline_function) (decl);
1538 /* Output stuff that Debug requires at the end of every file and generate the
1539 VMS Debug debugging info. */
1541 static void
1542 vmsdbgout_finish (const char *filename ATTRIBUTE_UNUSED)
1544 unsigned int i, ifunc;
1545 int totsize;
1547 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1548 (*dwarf2_debug_hooks.finish) (filename);
1550 if (debug_info_level == DINFO_LEVEL_NONE)
1551 return;
1553 /* Output a terminator label for the .text section. */
1554 switch_to_section (text_section);
1555 targetm.asm_out.internal_label (asm_out_file, TEXT_END_LABEL, 0);
1557 /* Output debugging information.
1558 Warning! Do not change the name of the .vmsdebug section without
1559 changing it in the assembler also. */
1560 switch_to_section (get_named_section (NULL, ".vmsdebug", 0));
1561 ASM_OUTPUT_ALIGN (asm_out_file, 0);
1563 totsize = write_modbeg (1);
1564 FOR_EACH_VEC_ELT (funcnum_table, i, ifunc)
1566 totsize += write_rtnbeg (i, 1);
1567 totsize += write_rtnend (i, 1);
1569 totsize += write_pclines (1);
1571 write_modbeg (0);
1572 FOR_EACH_VEC_ELT (funcnum_table, i, ifunc)
1574 write_rtnbeg (i, 0);
1575 write_rtnend (i, 0);
1577 write_pclines (0);
1579 if (debug_info_level > DINFO_LEVEL_TERSE)
1581 totsize = write_srccorrs (1);
1582 write_srccorrs (0);
1585 totsize = write_modend (1);
1586 write_modend (0);
1589 /* Need for both Dwarf2 on IVMS and VMS Debug on AVMS */
1591 #ifdef VMS
1592 #define __NEW_STARLET 1
1593 #include <vms/rms.h>
1594 #include <vms/atrdef.h>
1595 #include <vms/fibdef.h>
1596 #include <vms/stsdef.h>
1597 #include <vms/iodef.h>
1598 #include <vms/fatdef.h>
1599 #include <vms/descrip.h>
1600 #include <unixlib.h>
1602 #define MAXPATH 256
1604 /* descrip.h doesn't have everything ... */
1605 typedef struct fibdef* __fibdef_ptr32 __attribute__ (( mode (SI) ));
1606 struct dsc$descriptor_fib
1608 unsigned int fib$l_len;
1609 __fibdef_ptr32 fib$l_addr;
1612 /* I/O Status Block. */
1613 struct IOSB
1615 unsigned short status, count;
1616 unsigned int devdep;
1619 static char *tryfile;
1621 /* Variable length string. */
1622 struct vstring
1624 short length;
1625 char string[NAM$C_MAXRSS+1];
1628 static char filename_buff [MAXPATH];
1629 static char vms_filespec [MAXPATH];
1631 /* Callback function for filespec style conversion. */
1633 static int
1634 translate_unix (char *name, int type ATTRIBUTE_UNUSED)
1636 strncpy (filename_buff, name, MAXPATH);
1637 filename_buff [MAXPATH - 1] = (char) 0;
1638 return 0;
1641 /* Wrapper for DECC function that converts a Unix filespec
1642 to VMS style filespec. */
1644 static char *
1645 to_vms_file_spec (char *filespec)
1647 strncpy (vms_filespec, "", MAXPATH);
1648 decc$to_vms (filespec, translate_unix, 1, 1);
1649 strncpy (vms_filespec, filename_buff, MAXPATH);
1651 vms_filespec [MAXPATH - 1] = (char) 0;
1653 return vms_filespec;
1656 #else
1657 #define VMS_EPOCH_OFFSET 35067168000000000LL
1658 #define VMS_GRANULARITY_FACTOR 10000000
1659 #endif
1661 /* Return VMS file date, size, format, version given a name. */
1664 vms_file_stats_name (const char *filename, long long *cdt, long *siz, char *rfo,
1665 int *ver)
1667 #ifdef VMS
1668 struct FAB fab;
1669 struct NAM nam;
1671 unsigned long long create;
1672 FAT recattr;
1673 char ascnamebuff [256];
1675 ATRDEF atrlst[]
1677 { ATR$S_CREDATE, ATR$C_CREDATE, &create },
1678 { ATR$S_RECATTR, ATR$C_RECATTR, &recattr },
1679 { ATR$S_ASCNAME, ATR$C_ASCNAME, &ascnamebuff },
1680 { 0, 0, 0}
1683 FIBDEF fib;
1684 struct dsc$descriptor_fib fibdsc = {sizeof (fib), (void *) &fib};
1686 struct IOSB iosb;
1688 long status;
1689 unsigned short chan;
1691 struct vstring file;
1692 struct dsc$descriptor_s filedsc
1693 = {NAM$C_MAXRSS, DSC$K_DTYPE_T, DSC$K_CLASS_S, (void *) file.string};
1694 struct vstring device;
1695 struct dsc$descriptor_s devicedsc
1696 = {NAM$C_MAXRSS, DSC$K_DTYPE_T, DSC$K_CLASS_S, (void *) device.string};
1697 struct vstring result;
1698 struct dsc$descriptor_s resultdsc
1699 = {NAM$C_MAXRSS, DSC$K_DTYPE_VT, DSC$K_CLASS_VS, (void *) result.string};
1701 if (strcmp (filename, "<internal>") == 0
1702 || strcmp (filename, "<built-in>") == 0)
1704 if (cdt)
1705 *cdt = 0;
1707 if (siz)
1708 *siz = 0;
1710 if (rfo)
1711 *rfo = 0;
1713 if (ver)
1714 *ver = 0;
1716 return 0;
1719 tryfile = to_vms_file_spec (filename);
1721 /* Allocate and initialize a FAB and NAM structures. */
1722 fab = cc$rms_fab;
1723 nam = cc$rms_nam;
1725 nam.nam$l_esa = file.string;
1726 nam.nam$b_ess = NAM$C_MAXRSS;
1727 nam.nam$l_rsa = result.string;
1728 nam.nam$b_rss = NAM$C_MAXRSS;
1729 fab.fab$l_fna = tryfile;
1730 fab.fab$b_fns = strlen (tryfile);
1731 fab.fab$l_nam = &nam;
1733 /* Validate filespec syntax and device existence. */
1734 status = SYS$PARSE (&fab, 0, 0);
1735 if ((status & 1) != 1)
1736 return 1;
1738 file.string[nam.nam$b_esl] = 0;
1740 /* Find matching filespec. */
1741 status = SYS$SEARCH (&fab, 0, 0);
1742 if ((status & 1) != 1)
1743 return 1;
1745 file.string[nam.nam$b_esl] = 0;
1746 result.string[result.length=nam.nam$b_rsl] = 0;
1748 /* Get the device name and assign an IO channel. */
1749 strncpy (device.string, nam.nam$l_dev, nam.nam$b_dev);
1750 devicedsc.dsc$w_length = nam.nam$b_dev;
1751 chan = 0;
1752 status = SYS$ASSIGN (&devicedsc, &chan, 0, 0, 0);
1753 if ((status & 1) != 1)
1754 return 1;
1756 /* Initialize the FIB and fill in the directory id field. */
1757 memset (&fib, 0, sizeof (fib));
1758 fib.fib$w_did[0] = nam.nam$w_did[0];
1759 fib.fib$w_did[1] = nam.nam$w_did[1];
1760 fib.fib$w_did[2] = nam.nam$w_did[2];
1761 fib.fib$l_acctl = 0;
1762 fib.fib$l_wcc = 0;
1763 strcpy (file.string, (strrchr (result.string, ']') + 1));
1764 filedsc.dsc$w_length = strlen (file.string);
1765 result.string[result.length = 0] = 0;
1767 /* Open and close the file to fill in the attributes. */
1768 status
1769 = SYS$QIOW (0, chan, IO$_ACCESS|IO$M_ACCESS, &iosb, 0, 0,
1770 &fibdsc, &filedsc, &result.length, &resultdsc, &atrlst, 0);
1771 if ((status & 1) != 1)
1772 return 1;
1773 if ((iosb.status & 1) != 1)
1774 return 1;
1776 result.string[result.length] = 0;
1777 status = SYS$QIOW (0, chan, IO$_DEACCESS, &iosb, 0, 0, &fibdsc, 0, 0, 0,
1778 &atrlst, 0);
1779 if ((status & 1) != 1)
1780 return 1;
1781 if ((iosb.status & 1) != 1)
1782 return 1;
1784 /* Deassign the channel and exit. */
1785 status = SYS$DASSGN (chan);
1786 if ((status & 1) != 1)
1787 return 1;
1789 if (cdt) *cdt = create;
1790 if (siz) *siz = (512 * 65536 * recattr.fat$w_efblkh) +
1791 (512 * (recattr.fat$w_efblkl - 1)) +
1792 recattr.fat$w_ffbyte;
1793 if (rfo) *rfo = recattr.fat$v_rtype;
1794 if (ver) *ver = strtol (strrchr (ascnamebuff, ';')+1, 0, 10);
1796 return 0;
1797 #else
1798 struct stat buff;
1800 if ((stat (filename, &buff)) != 0)
1801 return 1;
1803 if (cdt)
1804 *cdt = (long long) (buff.st_mtime * VMS_GRANULARITY_FACTOR)
1805 + VMS_EPOCH_OFFSET;
1807 if (siz)
1808 *siz = buff.st_size;
1810 if (rfo)
1811 *rfo = 2; /* Stream LF format */
1813 if (ver)
1814 *ver = 1;
1816 return 0;
1817 #endif
1819 #endif