OSDN Git Service

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