OSDN Git Service

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