OSDN Git Service

PR c++/10784
[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 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          PARAMS ((const char *));
132 static unsigned int lookup_filename PARAMS ((const char *));
133 static void addr_const_to_string PARAMS ((char *, rtx));
134 static int write_debug_header   PARAMS ((DST_HEADER *, const char *, int));
135 static int write_debug_addr     PARAMS ((char *, const char *, int));
136 static int write_debug_data1    PARAMS ((unsigned int, const char *, int));
137 static int write_debug_data2    PARAMS ((unsigned int, const char *, int));
138 static int write_debug_data4    PARAMS ((unsigned long, const char *, int));
139 static int write_debug_data8    PARAMS ((unsigned long long, const char *,
140                                          int));
141 static int write_debug_delta4   PARAMS ((char *, char *, const char *, int));
142 static int write_debug_string   PARAMS ((char *, const char *, int));
143 static int write_modbeg         PARAMS ((int));
144 static int write_modend         PARAMS ((int));
145 static int write_rtnbeg         PARAMS ((int, int));
146 static int write_rtnend         PARAMS ((int, int));
147 static int write_pclines        PARAMS ((int));
148 static int write_srccorr        PARAMS ((int, dst_file_info_entry, int));
149 static int write_srccorrs       PARAMS ((int));
150
151 static void vmsdbgout_init              PARAMS ((const char *));
152 static void vmsdbgout_finish            PARAMS ((const char *));
153 static void vmsdbgout_define            PARAMS ((unsigned int, const char *));
154 static void vmsdbgout_undef             PARAMS ((unsigned int, const char *));
155 static void vmsdbgout_start_source_file PARAMS ((unsigned int, const char *));
156 static void vmsdbgout_end_source_file   PARAMS ((unsigned int));
157 static void vmsdbgout_begin_block       PARAMS ((unsigned int, unsigned int));
158 static void vmsdbgout_end_block         PARAMS ((unsigned int, unsigned int));
159 static bool vmsdbgout_ignore_block      PARAMS ((tree));
160 static void vmsdbgout_source_line       PARAMS ((unsigned int, const char *));
161 static void vmsdbgout_begin_prologue    PARAMS ((unsigned int, const char *));
162 static void vmsdbgout_end_prologue      PARAMS ((unsigned int, const char *));
163 static void vmsdbgout_end_function      PARAMS ((unsigned int));
164 static void vmsdbgout_end_epilogue      PARAMS ((unsigned int, const char *));
165 static void vmsdbgout_begin_function    PARAMS ((tree));
166 static void vmsdbgout_decl              PARAMS ((tree));
167 static void vmsdbgout_global_decl       PARAMS ((tree));
168 static void vmsdbgout_abstract_function PARAMS ((tree));
169
170 /* The debug hooks structure.  */
171
172 const struct gcc_debug_hooks vmsdbg_debug_hooks
173 = {vmsdbgout_init,
174    vmsdbgout_finish,
175    vmsdbgout_define,
176    vmsdbgout_undef,
177    vmsdbgout_start_source_file,
178    vmsdbgout_end_source_file,
179    vmsdbgout_begin_block,
180    vmsdbgout_end_block,
181    vmsdbgout_ignore_block,
182    vmsdbgout_source_line,
183    vmsdbgout_begin_prologue,
184    vmsdbgout_end_prologue,
185    vmsdbgout_end_epilogue,
186    vmsdbgout_begin_function,
187    vmsdbgout_end_function,
188    vmsdbgout_decl,
189    vmsdbgout_global_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 (str, x)
407      char *str;
408      rtx x;
409 {
410   char buf1[256];
411   char buf2[256];
412
413 restart:
414   str[0] = '\0';
415   switch (GET_CODE (x))
416     {
417     case PC:
418       if (flag_pic)
419         strcat (str, ",");
420       else
421         abort ();
422       break;
423
424     case SYMBOL_REF:
425       ASM_NAME_TO_STRING (buf1, XSTR (x, 0));
426       strcat (str, buf1);
427       break;
428
429     case LABEL_REF:
430       ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
431       ASM_NAME_TO_STRING (buf2, buf1);
432       strcat (str, buf2);
433       break;
434
435     case CODE_LABEL:
436       ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (x));
437       ASM_NAME_TO_STRING (buf2, buf1);
438       strcat (str, buf2);
439       break;
440
441     case CONST_INT:
442       sprintf (buf1, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
443       strcat (str, buf1);
444       break;
445
446     case CONST:
447       /* This used to output parentheses around the expression, but that does
448          not work on the 386 (either ATT or BSD assembler).  */
449       addr_const_to_string (buf1, XEXP (x, 0));
450       strcat (str, buf1);
451       break;
452
453     case CONST_DOUBLE:
454       if (GET_MODE (x) == VOIDmode)
455         {
456           /* We can use %d if the number is one word and positive.  */
457           if (CONST_DOUBLE_HIGH (x))
458             sprintf (buf1, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
459                      CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
460           else if (CONST_DOUBLE_LOW (x) < 0)
461             sprintf (buf1, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (x));
462           else
463             sprintf (buf1, HOST_WIDE_INT_PRINT_DEC,
464                      CONST_DOUBLE_LOW (x));
465           strcat (str, buf1);
466         }
467       else
468         /* We can't handle floating point constants; PRINT_OPERAND must
469            handle them.  */
470         output_operand_lossage ("floating constant misused");
471       break;
472
473     case PLUS:
474       /* Some assemblers need integer constants to appear last (eg masm).  */
475       if (GET_CODE (XEXP (x, 0)) == CONST_INT)
476         {
477           addr_const_to_string (buf1, XEXP (x, 1));
478           strcat (str, buf1);
479           if (INTVAL (XEXP (x, 0)) >= 0)
480             strcat (str, "+");
481           addr_const_to_string (buf1, XEXP (x, 0));
482           strcat (str, buf1);
483         }
484       else
485         {
486           addr_const_to_string (buf1, XEXP (x, 0));
487           strcat (str, buf1);
488           if (INTVAL (XEXP (x, 1)) >= 0)
489             strcat (str, "+");
490           addr_const_to_string (buf1, XEXP (x, 1));
491           strcat (str, buf1);
492         }
493       break;
494
495     case MINUS:
496       /* Avoid outputting things like x-x or x+5-x, since some assemblers
497          can't handle that.  */
498       x = simplify_subtraction (x);
499       if (GET_CODE (x) != MINUS)
500         goto restart;
501
502       addr_const_to_string (buf1, XEXP (x, 0));
503       strcat (str, buf1);
504       strcat (str, "-");
505       if (GET_CODE (XEXP (x, 1)) == CONST_INT
506           && INTVAL (XEXP (x, 1)) < 0)
507         {
508           strcat (str, "(");
509           addr_const_to_string (buf1, XEXP (x, 1));
510           strcat (str, buf1);
511           strcat (str, ")");
512         }
513       else
514         {
515           addr_const_to_string (buf1, XEXP (x, 1));
516           strcat (str, buf1);
517         }
518       break;
519
520     case ZERO_EXTEND:
521     case SIGN_EXTEND:
522       addr_const_to_string (buf1, XEXP (x, 0));
523       strcat (str, buf1);
524       break;
525
526     default:
527       output_operand_lossage ("invalid expression as operand");
528     }
529 }
530
531 /* Output the debug header HEADER.  Also output COMMENT if flag_verbose_asm is
532    set.  Return the header size.  Just return the size if DOSIZEONLY is
533    nonzero.  */
534
535 static int
536 write_debug_header (header, comment, dosizeonly)
537      DST_HEADER *header;
538      const char *comment;
539      int dosizeonly;
540 {
541   if (!dosizeonly)
542     {
543       ASM_OUTPUT_DEBUG_DATA2 (asm_out_file,
544                               header->dst__header_length.dst_w_length);
545
546       if (flag_verbose_asm)
547         fprintf (asm_out_file, "\t%s record length", ASM_COMMENT_START);
548       fputc ('\n', asm_out_file);
549
550       ASM_OUTPUT_DEBUG_DATA2 (asm_out_file,
551                               header->dst__header_type.dst_w_type);
552
553       if (flag_verbose_asm)
554         fprintf (asm_out_file, "\t%s record type (%s)", ASM_COMMENT_START,
555                  comment);
556
557       fputc ('\n', asm_out_file);
558     }
559
560   return 4;
561 }
562
563 /* Output the address of SYMBOL.  Also output COMMENT if flag_verbose_asm is
564    set.  Return the address size.  Just return the size if DOSIZEONLY is
565    nonzero.  */
566
567 static int
568 write_debug_addr (symbol, comment, dosizeonly)
569      char *symbol;
570      const char *comment;
571      int dosizeonly;
572 {
573   if (!dosizeonly)
574     {
575       ASM_OUTPUT_DEBUG_ADDR (asm_out_file, symbol);
576       if (flag_verbose_asm)
577         fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
578       fputc ('\n', asm_out_file);
579     }
580
581   return PTR_SIZE;
582 }
583
584 /* Output the single byte DATA1.  Also output COMMENT if flag_verbose_asm is
585    set.  Return the data size.  Just return the size if DOSIZEONLY is
586    nonzero.  */
587
588 static int
589 write_debug_data1 (data1, comment, dosizeonly)
590      unsigned int data1;
591      const char *comment;
592      int dosizeonly;
593 {
594   if (!dosizeonly)
595     {
596       ASM_OUTPUT_DEBUG_DATA1 (asm_out_file, data1);
597       if (flag_verbose_asm)
598         fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
599       fputc ('\n', asm_out_file);
600     }
601
602   return 1;
603 }
604
605 /* Output the single word DATA2.  Also output COMMENT if flag_verbose_asm is
606    set.  Return the data size.  Just return the size if DOSIZEONLY is
607    nonzero.  */
608
609 static int
610 write_debug_data2 (data2, comment, dosizeonly)
611      unsigned int data2;
612      const char *comment;
613      int dosizeonly;
614 {
615   if (!dosizeonly)
616     {
617       ASM_OUTPUT_DEBUG_DATA2 (asm_out_file, data2);
618       if (flag_verbose_asm)
619         fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
620       fputc ('\n', asm_out_file);
621     }
622
623   return 2;
624 }
625
626 /* Output double word DATA4.  Also output COMMENT if flag_verbose_asm is set.
627    Return the data size.  Just return the size if DOSIZEONLY is nonzero.  */
628
629 static int
630 write_debug_data4 (data4, comment, dosizeonly)
631      unsigned long data4;
632      const char *comment;
633      int dosizeonly;
634 {
635   if (!dosizeonly)
636     {
637       ASM_OUTPUT_DEBUG_DATA4 (asm_out_file, data4);
638       if (flag_verbose_asm)
639         fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
640       fputc ('\n', asm_out_file);
641     }
642
643   return 4;
644 }
645
646 /* Output quad word DATA8.  Also output COMMENT if flag_verbose_asm is set.
647    Return the data size.  Just return the size if DOSIZEONLY is nonzero.  */
648
649 static int
650 write_debug_data8 (data8, comment, dosizeonly)
651      unsigned long long data8;
652      const char *comment;
653      int dosizeonly;
654 {
655   if (!dosizeonly)
656     {
657       ASM_OUTPUT_DEBUG_DATA8 (asm_out_file, data8);
658       if (flag_verbose_asm)
659         fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
660       fputc ('\n', asm_out_file);
661     }
662
663   return 8;
664 }
665
666 /* Output the difference between LABEL1 and LABEL2.  Also output COMMENT if
667    flag_verbose_asm is set.  Return the data size.  Just return the size if
668    DOSIZEONLY is nonzero.  */
669
670 static int
671 write_debug_delta4 (label1, label2, comment, dosizeonly)
672      char *label1;
673      char *label2;
674      const char *comment;
675      int dosizeonly;
676 {
677   if (!dosizeonly)
678     {
679       ASM_OUTPUT_DEBUG_DELTA4 (asm_out_file, label1, label2);
680       if (flag_verbose_asm)
681         fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
682       fputc ('\n', asm_out_file);
683     }
684
685   return 4;
686 }
687
688 /* Output a character string STRING.  Also write COMMENT if flag_verbose_asm is
689    set.  Return the string length.  Just return the length if DOSIZEONLY is
690    nonzero.  */
691
692 static int
693 write_debug_string (string, comment, dosizeonly)
694      char *string;
695      const char *comment;
696      int dosizeonly;
697 {
698   if (!dosizeonly)
699     {
700       ASM_OUTPUT_DEBUG_STRING (asm_out_file, string);
701       if (flag_verbose_asm)
702         fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
703       fputc ('\n', asm_out_file);
704     }
705
706   return strlen (string);
707 }
708
709 /* Output a module begin header and return the header size.  Just return the
710    size if DOSIZEONLY is nonzero.  */
711
712 static int
713 write_modbeg (dosizeonly)
714      int dosizeonly;
715 {
716   DST_MODULE_BEGIN modbeg;
717   DST_MB_TRLR mb_trlr;
718   int i;
719   char *module_name, *m;
720   int modnamelen;
721   int prodnamelen;
722   int totsize = 0;
723
724   /* Assumes primary filename has Unix syntax file spec.  */
725   module_name = xstrdup (basename ((char *) primary_filename));
726
727   m = strrchr (module_name, '.');
728   if (m)
729     *m = 0;
730
731   modnamelen = strlen (module_name);
732   for (i = 0; i < modnamelen; i++)
733     module_name[i] = TOUPPER (module_name[i]);
734
735   prodnamelen = strlen (module_producer);
736
737   modbeg.dst_a_modbeg_header.dst__header_length.dst_w_length
738     = DST_K_MODBEG_SIZE + modnamelen + DST_K_MB_TRLR_SIZE + prodnamelen - 1;
739   modbeg.dst_a_modbeg_header.dst__header_type.dst_w_type = DST_K_MODBEG;
740   modbeg.dst_b_modbeg_flags.dst_v_modbeg_hide = 0;
741   modbeg.dst_b_modbeg_flags.dst_v_modbeg_version = 1;
742   modbeg.dst_b_modbeg_flags.dst_v_modbeg_unused = 0;
743   modbeg.dst_b_modbeg_unused = 0;
744   modbeg.dst_l_modbeg_language = module_language;
745   modbeg.dst_w_version_major = DST_K_VERSION_MAJOR;
746   modbeg.dst_w_version_minor = DST_K_VERSION_MINOR;
747   modbeg.dst_b_modbeg_name = strlen (module_name);
748
749   mb_trlr.dst_b_compiler = strlen (module_producer);
750
751   totsize += write_debug_header (&modbeg.dst_a_modbeg_header,
752                                  "modbeg", dosizeonly);
753   totsize += write_debug_data1 (*((char *) &modbeg.dst_b_modbeg_flags),
754                                 "flags", dosizeonly);
755   totsize += write_debug_data1 (modbeg.dst_b_modbeg_unused,
756                                 "unused", dosizeonly);
757   totsize += write_debug_data4 (modbeg.dst_l_modbeg_language,
758                                 "language", dosizeonly);
759   totsize += write_debug_data2 (modbeg.dst_w_version_major,
760                                 "DST major version", dosizeonly);
761   totsize += write_debug_data2 (modbeg.dst_w_version_minor,
762                                 "DST minor version", dosizeonly);
763   totsize += write_debug_data1 (modbeg.dst_b_modbeg_name,
764                                 "length of module name", dosizeonly);
765   totsize += write_debug_string (module_name, "module name", dosizeonly);
766   totsize += write_debug_data1 (mb_trlr.dst_b_compiler,
767                                 "length of compiler name", dosizeonly);
768   totsize += write_debug_string (module_producer, "compiler name", dosizeonly);
769
770   return totsize;
771 }
772
773 /* Output a module end trailer and return the trailer size.   Just return
774    the size if DOSIZEONLY is nonzero.  */
775
776 static int
777 write_modend (dosizeonly)
778      int dosizeonly;
779 {
780   DST_MODULE_END modend;
781   int totsize = 0;
782
783   modend.dst_a_modend_header.dst__header_length.dst_w_length
784    = DST_K_MODEND_SIZE - 1;
785   modend.dst_a_modend_header.dst__header_type.dst_w_type = DST_K_MODEND;
786
787   totsize += write_debug_header (&modend.dst_a_modend_header, "modend",
788                                  dosizeonly);
789
790   return totsize;
791 }
792
793 /* Output a routine begin header routine RTNNUM and return the header size.
794    Just return the size if DOSIZEONLY is nonzero.  */
795
796 static int
797 write_rtnbeg (rtnnum, dosizeonly)
798      int rtnnum;
799      int dosizeonly;
800 {
801   char *rtnname;
802   int rtnnamelen;
803   char *rtnentryname;
804   int totsize = 0;
805   char label[MAX_ARTIFICIAL_LABEL_BYTES];
806   DST_ROUTINE_BEGIN rtnbeg;
807   DST_PROLOG prolog;
808
809   rtnname = func_table[rtnnum];
810   rtnnamelen = strlen (rtnname);
811   rtnentryname = concat (rtnname, "..en", NULL);
812
813   if (!strcmp (rtnname, "main"))
814     {
815       DST_HEADER header;
816       const char *go = "TRANSFER$BREAK$GO";
817
818       /* This command isn't documented in DSTRECORDS, so it's made to
819          look like what DEC C does */
820
821       /* header size - 1st byte + flag byte + STO_LW size
822          + string count byte + string length */
823       header.dst__header_length.dst_w_length
824         = DST_K_DST_HEADER_SIZE - 1 + 1 + 4 + 1 + strlen (go);
825       header.dst__header_type.dst_w_type = 0x17;
826
827       totsize += write_debug_header (&header, "transfer", dosizeonly);
828
829       /* I think this is a flag byte, but I don't know what this flag means */
830       totsize += write_debug_data1 (0x1, "flags ???", dosizeonly);
831
832       /* Routine Begin PD Address */
833       totsize += write_debug_addr (rtnname, "main procedure descriptor",
834                                    dosizeonly);
835       totsize += write_debug_data1 (strlen (go), "length of main_name",
836                                     dosizeonly);
837       totsize += write_debug_string ((char *) go, "main name", dosizeonly);
838     }
839
840   /* The header length never includes the length byte */
841   rtnbeg.dst_a_rtnbeg_header.dst__header_length.dst_w_length
842    = DST_K_RTNBEG_SIZE + rtnnamelen - 1;
843   rtnbeg.dst_a_rtnbeg_header.dst__header_type.dst_w_type = DST_K_RTNBEG;
844   rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_unused = 0;
845   rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_unalloc = 0;
846   rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_prototype = 0;
847   rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_inlined = 0;
848   rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_no_call = 1;
849   rtnbeg.dst_b_rtnbeg_name = rtnnamelen;
850
851   totsize += write_debug_header (&rtnbeg.dst_a_rtnbeg_header, "rtnbeg",
852                                  dosizeonly);
853   totsize += write_debug_data1 (*((char *) &rtnbeg.dst_b_rtnbeg_flags),
854                                 "flags", dosizeonly);
855
856   /* Routine Begin Address */
857   totsize += write_debug_addr (rtnentryname, "routine entry name", dosizeonly);
858
859   /* Routine Begin PD Address */
860   totsize += write_debug_addr (rtnname, "routine procedure descriptor",
861                                dosizeonly);
862
863   /* Routine Begin Name */
864   totsize += write_debug_data1 (rtnbeg.dst_b_rtnbeg_name,
865                                 "length of routine name", dosizeonly);
866
867   totsize += write_debug_string (rtnname, "routine name", dosizeonly);
868
869   free (rtnentryname);
870
871   if (debug_info_level > DINFO_LEVEL_TERSE)
872     {
873       prolog.dst_a_prolog_header.dst__header_length.dst_w_length
874         = DST_K_PROLOG_SIZE - 1;
875       prolog.dst_a_prolog_header.dst__header_type.dst_w_type = DST_K_PROLOG;
876
877       totsize += write_debug_header (&prolog.dst_a_prolog_header, "prolog",
878                                      dosizeonly);
879
880       ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL, rtnnum);
881       totsize += write_debug_addr (label, "prolog breakpoint addr",
882                                    dosizeonly);
883     }
884
885   return totsize;
886 }
887
888 /* Output a routine end trailer for routine RTNNUM and return the header size.
889    Just return the size if DOSIZEONLY is nonzero.  */
890
891 static int
892 write_rtnend (rtnnum, dosizeonly)
893      int rtnnum;
894      int dosizeonly;
895 {
896   DST_ROUTINE_END rtnend;
897   char label1[MAX_ARTIFICIAL_LABEL_BYTES];
898   char label2[MAX_ARTIFICIAL_LABEL_BYTES];
899   int totsize;
900
901   totsize = 0;
902
903   rtnend.dst_a_rtnend_header.dst__header_length.dst_w_length
904    = DST_K_RTNEND_SIZE - 1;
905   rtnend.dst_a_rtnend_header.dst__header_type.dst_w_type = DST_K_RTNEND;
906   rtnend.dst_b_rtnend_unused = 0;
907   rtnend.dst_l_rtnend_size = 0; /* Calculated below.  */
908
909   totsize += write_debug_header (&rtnend.dst_a_rtnend_header, "rtnend",
910                                  dosizeonly);
911   totsize += write_debug_data1 (rtnend.dst_b_rtnend_unused, "unused",
912                                 dosizeonly);
913
914   ASM_GENERATE_INTERNAL_LABEL (label1, FUNC_BEGIN_LABEL, rtnnum);
915   ASM_GENERATE_INTERNAL_LABEL (label2, FUNC_END_LABEL, rtnnum);
916   totsize += write_debug_delta4 (label2, label1, "routine size", dosizeonly);
917
918   return totsize;
919 }
920
921 #define K_DELTA_PC(I) \
922  ((I) < 128 ? -(I) : (I) < 65536 ? DST_K_DELTA_PC_W : DST_K_DELTA_PC_L)
923
924 #define K_SET_LINUM(I) \
925  ((I) < 256 ? DST_K_SET_LINUM_B \
926   : (I) < 65536 ? DST_K_SET_LINUM : DST_K_SET_LINUM_L)
927
928 #define K_INCR_LINUM(I) \
929  ((I) < 256 ? DST_K_INCR_LINUM \
930   : (I) < 65536 ? DST_K_INCR_LINUM_W : DST_K_INCR_LINUM_L)
931
932 /* Output the PC to line number correlations and return the size.  Just return
933    the size if DOSIZEONLY is nonzero */
934
935 static int
936 write_pclines (dosizeonly)
937      int dosizeonly;
938 {
939   unsigned i;
940   int fn;
941   int ln, lastln;
942   int linestart = 0;
943   int max_line;
944   DST_LINE_NUM_HEADER line_num;
945   DST_PCLINE_COMMANDS pcline;
946   char label[MAX_ARTIFICIAL_LABEL_BYTES];
947   char lastlabel[MAX_ARTIFICIAL_LABEL_BYTES];
948   int totsize = 0;
949   char buff[256];
950
951   max_line = file_info_table[1].max_line;
952   file_info_table[1].listing_line_start = linestart;
953   linestart = linestart + ((max_line / 100000) + 1) * 100000;
954
955   for (i = 2; i < file_info_table_in_use; i++)
956     {
957       max_line = file_info_table[i].max_line;
958       file_info_table[i].listing_line_start = linestart;
959       linestart = linestart + ((max_line / 10000) + 1) * 10000;
960     }
961
962   /* Set starting address to beginning of text section */
963   line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 8;
964   line_num.dst_a_line_num_header.dst__header_type.dst_w_type = DST_K_LINE_NUM;
965   pcline.dst_b_pcline_command = DST_K_SET_ABS_PC;
966
967   totsize += write_debug_header (&line_num.dst_a_line_num_header,
968                                  "line_num", dosizeonly);
969   totsize += write_debug_data1 (pcline.dst_b_pcline_command,
970                                 "line_num (SET ABS PC)", dosizeonly);
971
972   if (dosizeonly)
973     totsize += 4;
974   else
975     {
976       ASM_OUTPUT_DEBUG_ADDR (asm_out_file, TEXT_SECTION_ASM_OP);
977       if (flag_verbose_asm)
978         fprintf (asm_out_file, "\t%s line_num", ASM_COMMENT_START);
979       fputc ('\n', asm_out_file);
980     }
981
982   fn = line_info_table[1].dst_file_num;
983   ln = (file_info_table[fn].listing_line_start
984         + line_info_table[1].dst_line_num);
985   line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 4 + 4;
986   pcline.dst_b_pcline_command = DST_K_SET_LINUM_L;
987
988   totsize += write_debug_header (&line_num.dst_a_line_num_header,
989                                  "line_num", dosizeonly);
990   totsize += write_debug_data1 (pcline.dst_b_pcline_command,
991                                 "line_num (SET LINUM LONG)", dosizeonly);
992
993   sprintf (buff, "line_num (%d)", ln ? ln - 1 : 0);
994   totsize += write_debug_data4 (ln ? ln - 1 : 0, buff, dosizeonly);
995
996   lastln = ln;
997   strcpy (lastlabel, TEXT_SECTION_ASM_OP);
998   for (i = 1; i < line_info_table_in_use; i++)
999     {
1000       int extrabytes;
1001
1002       fn = line_info_table[i].dst_file_num;
1003       ln = (file_info_table[fn].listing_line_start
1004             + line_info_table[i].dst_line_num);
1005
1006       if (ln - lastln > 1)
1007         extrabytes = 5; /* NUMBYTES (ln - lastln - 1) + 1; */
1008       else if (ln <= lastln)
1009         extrabytes = 5; /* NUMBYTES (ln - 1) + 1; */
1010       else
1011         extrabytes = 0;
1012
1013       line_num.dst_a_line_num_header.dst__header_length.dst_w_length
1014         = 8 + extrabytes;
1015
1016       totsize += write_debug_header
1017         (&line_num.dst_a_line_num_header, "line_num", dosizeonly);
1018
1019       if (ln - lastln > 1)
1020         {
1021           int lndif = ln - lastln - 1;
1022
1023           /* K_INCR_LINUM (lndif); */
1024           pcline.dst_b_pcline_command = DST_K_INCR_LINUM_L;
1025
1026           totsize += write_debug_data1 (pcline.dst_b_pcline_command,
1027                                         "line_num (INCR LINUM LONG)",
1028                                         dosizeonly);
1029
1030           sprintf (buff, "line_num (%d)", lndif);
1031           totsize += write_debug_data4 (lndif, buff, dosizeonly);
1032         }
1033       else if (ln <= lastln)
1034         {
1035           /* K_SET_LINUM (ln-1); */
1036           pcline.dst_b_pcline_command = DST_K_SET_LINUM_L;
1037
1038           totsize += write_debug_data1 (pcline.dst_b_pcline_command,
1039                                         "line_num (SET LINUM LONG)",
1040                                         dosizeonly);
1041
1042           sprintf (buff, "line_num (%d)", ln - 1);
1043           totsize += write_debug_data4 (ln - 1, buff, dosizeonly);
1044         }
1045
1046       pcline.dst_b_pcline_command = DST_K_DELTA_PC_L;
1047
1048       totsize += write_debug_data1 (pcline.dst_b_pcline_command,
1049                                     "line_num (DELTA PC LONG)", dosizeonly);
1050
1051       ASM_GENERATE_INTERNAL_LABEL (label, LINE_CODE_LABEL, i);
1052       totsize += write_debug_delta4 (label, lastlabel, "increment line_num",
1053                                      dosizeonly);
1054
1055       lastln = ln;
1056       strcpy (lastlabel, label);
1057     }
1058
1059   return totsize;
1060 }
1061
1062 /* Output a source correlation for file FILEID using information saved in
1063    FILE_INFO_ENTRY and return the size.  Just return the size if DOSIZEONLY is
1064    nonzero.  */
1065
1066 static int
1067 write_srccorr (fileid, file_info_entry, dosizeonly)
1068      int fileid;
1069      dst_file_info_entry file_info_entry;
1070      int dosizeonly;
1071 {
1072   int src_command_size;
1073   int linesleft = file_info_entry.max_line;
1074   int linestart = file_info_entry.listing_line_start;
1075   int flen = file_info_entry.flen;
1076   int linestodo = 0;
1077   DST_SOURCE_CORR src_header;
1078   DST_SRC_COMMAND src_command;
1079   DST_SRC_COMMAND src_command_sf;
1080   DST_SRC_COMMAND src_command_sl;
1081   DST_SRC_COMMAND src_command_sr;
1082   DST_SRC_COMMAND src_command_dl;
1083   DST_SRC_CMDTRLR src_cmdtrlr;
1084   char buff[256];
1085   int totsize = 0;
1086
1087   if (fileid == 1)
1088     {
1089       src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1090         = DST_K_SOURCE_CORR_HEADER_SIZE + 1 - 1;
1091       src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1092         = DST_K_SOURCE;
1093       src_command.dst_b_src_command = DST_K_SRC_FORMFEED;
1094
1095       totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1096                                      "source corr", dosizeonly);
1097
1098       totsize += write_debug_data1 (src_command.dst_b_src_command,
1099                                     "source_corr (SRC FORMFEED)",
1100                                     dosizeonly);
1101     }
1102
1103   src_command_size
1104     = DST_K_SRC_COMMAND_SIZE + flen + DST_K_SRC_CMDTRLR_SIZE;
1105   src_command.dst_b_src_command = DST_K_SRC_DECLFILE;
1106   src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_length
1107     = src_command_size - 2;
1108   src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_flags = 0;
1109   src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_fileid
1110     = fileid;
1111   src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt
1112     = file_info_entry.cdt;
1113   src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk
1114     = file_info_entry.ebk;
1115   src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_rms_ffb
1116     = file_info_entry.ffb;
1117   src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_rms_rfo
1118     = file_info_entry.rfo;
1119   src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename
1120     = file_info_entry.flen;
1121
1122   src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1123     = DST_K_SOURCE_CORR_HEADER_SIZE + src_command_size - 1;
1124   src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1125     = DST_K_SOURCE;
1126
1127   src_cmdtrlr.dst_b_src_df_libmodname = 0;
1128
1129   totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1130                                  "source corr", dosizeonly);
1131   totsize += write_debug_data1 (src_command.dst_b_src_command,
1132                                 "source_corr (DECL SRC FILE)", dosizeonly);
1133   totsize += write_debug_data1
1134     (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_length,
1135      "source_corr (length)", dosizeonly);
1136
1137   totsize += write_debug_data1
1138     (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_flags,
1139      "source_corr (flags)", dosizeonly);
1140
1141   totsize += write_debug_data2
1142     (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_fileid,
1143      "source_corr (fileid)", dosizeonly);
1144
1145   totsize += write_debug_data8
1146     (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt,
1147      "source_corr (creation date)", dosizeonly);
1148
1149   totsize += write_debug_data4
1150     (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk,
1151      "source_corr (EOF block number)", dosizeonly);
1152
1153   totsize += write_debug_data2
1154     (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_rms_ffb,
1155      "source_corr (first free byte)", dosizeonly);
1156
1157   totsize += write_debug_data1
1158     (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_rms_rfo,
1159      "source_corr (record and file organization)", dosizeonly);
1160
1161   totsize += write_debug_data1
1162     (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename,
1163      "source_corr (filename length)", dosizeonly);
1164
1165   totsize += write_debug_string (file_info_entry.file_name,
1166                                  "source file name", dosizeonly);
1167   totsize += write_debug_data1 (src_cmdtrlr.dst_b_src_df_libmodname,
1168                                 "source_corr (libmodname)", dosizeonly);
1169
1170   src_command_sf.dst_b_src_command = DST_K_SRC_SETFILE;
1171   src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword = fileid;
1172
1173   src_command_sr.dst_b_src_command = DST_K_SRC_SETREC_W;
1174   src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword = 1;
1175
1176   src_command_sl.dst_b_src_command = DST_K_SRC_SETLNUM_L;
1177   src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong = linestart + 1;
1178
1179   src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W;
1180
1181   if (linesleft > 65534)
1182     linesleft = linesleft - 65534, linestodo = 65534;
1183   else
1184     linestodo = linesleft, linesleft = 0;
1185
1186   src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo;
1187
1188   src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1189     = DST_K_SOURCE_CORR_HEADER_SIZE + 3 + 3 + 5 + 3 - 1;
1190   src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1191     = DST_K_SOURCE;
1192
1193   if (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword)
1194     {
1195       totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1196                                      "source corr", dosizeonly);
1197
1198       totsize += write_debug_data1 (src_command_sf.dst_b_src_command,
1199                                     "source_corr (src setfile)", dosizeonly);
1200
1201       totsize += write_debug_data2
1202         (src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword,
1203          "source_corr (fileid)", dosizeonly);
1204
1205       totsize += write_debug_data1 (src_command_sr.dst_b_src_command,
1206                                     "source_corr (setrec)", dosizeonly);
1207
1208       totsize += write_debug_data2
1209         (src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword,
1210          "source_corr (recnum)", dosizeonly);
1211
1212       totsize += write_debug_data1 (src_command_sl.dst_b_src_command,
1213                                     "source_corr (setlnum)", dosizeonly);
1214
1215       totsize += write_debug_data4
1216         (src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong,
1217          "source_corr (linenum)", dosizeonly);
1218
1219       totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
1220                                     "source_corr (deflines)", dosizeonly);
1221
1222       sprintf (buff, "source_corr (%d)",
1223                src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
1224       totsize += write_debug_data2
1225         (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword,
1226          buff, dosizeonly);
1227
1228       while (linesleft > 0)
1229         {
1230           src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1231             = DST_K_SOURCE_CORR_HEADER_SIZE + 3 - 1;
1232           src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1233             = DST_K_SOURCE;
1234           src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W;
1235
1236           if (linesleft > 65534)
1237             linesleft = linesleft - 65534, linestodo = 65534;
1238           else
1239             linestodo = linesleft, linesleft = 0;
1240
1241           src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo;
1242
1243           totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1244                                          "source corr", dosizeonly);
1245           totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
1246                                         "source_corr (deflines)", dosizeonly);
1247           sprintf (buff, "source_corr (%d)",
1248                    src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
1249           totsize += write_debug_data2
1250             (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword,
1251              buff, dosizeonly);
1252         }
1253     }
1254
1255   return totsize;
1256 }
1257
1258 /* Output all the source correlation entries and return the size.  Just return
1259    the size if DOSIZEONLY is nonzero.  */
1260
1261 static int
1262 write_srccorrs (dosizeonly)
1263      int dosizeonly;
1264 {
1265   unsigned int i;
1266   int totsize = 0;
1267
1268   for (i = 1; i < file_info_table_in_use; i++)
1269     totsize += write_srccorr (i, file_info_table[i], dosizeonly);
1270
1271   return totsize;
1272 }
1273 \f
1274 /* Output a marker (i.e. a label) for the beginning of a function, before
1275    the prologue.  */
1276
1277 static void
1278 vmsdbgout_begin_prologue (line, file)
1279      unsigned int line;
1280      const char *file;
1281 {
1282   char label[MAX_ARTIFICIAL_LABEL_BYTES];
1283
1284   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1285     (*dwarf2_debug_hooks.begin_prologue) (line, file);
1286
1287   if (debug_info_level > DINFO_LEVEL_NONE)
1288     {
1289       ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL,
1290                                    current_function_funcdef_no);
1291       ASM_OUTPUT_LABEL (asm_out_file, label);
1292     }
1293 }
1294
1295 /* Output a marker (i.e. a label) for the beginning of a function, after
1296    the prologue.  */
1297
1298 static void
1299 vmsdbgout_end_prologue (line, file)
1300      unsigned int line;
1301      const char *file;
1302 {
1303   char label[MAX_ARTIFICIAL_LABEL_BYTES];
1304
1305   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1306     (*dwarf2_debug_hooks.end_prologue) (line, file);
1307
1308   if (debug_info_level > DINFO_LEVEL_TERSE)
1309     {
1310       ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL,
1311                                    current_function_funcdef_no);
1312       ASM_OUTPUT_LABEL (asm_out_file, label);
1313
1314       /* VMS PCA expects every PC range to correlate to some line and file */
1315       vmsdbgout_source_line (line, file);
1316     }
1317 }
1318
1319 /* No output for VMS debug, but make obligatory call to Dwarf2 debug */
1320
1321 static void
1322 vmsdbgout_end_function (line)
1323      unsigned int line;
1324 {
1325   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1326     (*dwarf2_debug_hooks.end_function) (line);
1327 }
1328
1329 /* Output a marker (i.e. a label) for the absolute end of the generated code
1330    for a function definition.  This gets called *after* the epilogue code has
1331    been generated.  */
1332
1333 static void
1334 vmsdbgout_end_epilogue (line, file)
1335      unsigned int line;
1336      const char *file;
1337 {
1338   char label[MAX_ARTIFICIAL_LABEL_BYTES];
1339
1340   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1341     (*dwarf2_debug_hooks.end_epilogue) (line, file);
1342
1343   if (debug_info_level > DINFO_LEVEL_NONE)
1344     {
1345       /* Output a label to mark the endpoint of the code generated for this
1346          function.  */
1347       ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL,
1348                                    current_function_funcdef_no);
1349       ASM_OUTPUT_LABEL (asm_out_file, label);
1350
1351       /* VMS PCA expects every PC range to correlate to some line and file */
1352       vmsdbgout_source_line (line, file);
1353     }
1354 }
1355
1356 /* Output a marker (i.e. a label) for the beginning of the generated code for
1357    a lexical block.  */
1358
1359 static void
1360 vmsdbgout_begin_block (line, blocknum)
1361      register unsigned line;
1362      register unsigned blocknum;
1363 {
1364   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1365     (*dwarf2_debug_hooks.begin_block) (line, blocknum);
1366
1367   if (debug_info_level > DINFO_LEVEL_TERSE)
1368     (*targetm.asm_out.internal_label) (asm_out_file, BLOCK_BEGIN_LABEL, blocknum);
1369 }
1370
1371 /* Output a marker (i.e. a label) for the end of the generated code for a
1372    lexical block.  */
1373
1374 static void
1375 vmsdbgout_end_block (line, blocknum)
1376      register unsigned line;
1377      register unsigned blocknum;
1378 {
1379   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1380     (*dwarf2_debug_hooks.end_block) (line, blocknum);
1381
1382   if (debug_info_level > DINFO_LEVEL_TERSE)
1383     (*targetm.asm_out.internal_label) (asm_out_file, BLOCK_END_LABEL, blocknum);
1384 }
1385
1386 /* Not implemented in VMS Debug.  */
1387
1388 static bool
1389 vmsdbgout_ignore_block (block)
1390      tree block;
1391 {
1392   bool retval = 0;
1393
1394   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1395     retval = (*dwarf2_debug_hooks.ignore_block) (block);
1396
1397   return retval;
1398 }
1399
1400 /* Add an entry for function DECL into the func_table.  */
1401
1402 static void
1403 vmsdbgout_begin_function (decl)
1404      tree decl;
1405 {
1406   const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
1407
1408   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1409     (*dwarf2_debug_hooks.begin_function) (decl);
1410
1411   if (func_table_in_use == func_table_allocated)
1412     {
1413       func_table_allocated += FUNC_TABLE_INCREMENT;
1414       func_table = (char **) xrealloc (func_table,
1415                                        func_table_allocated * sizeof (char *));
1416     }
1417
1418   /* Add the new entry to the end of the function name table.  */
1419   func_table[func_table_in_use++] = xstrdup (name);
1420 }
1421
1422 static char fullname_buff [4096];
1423
1424 /* Return the full file specification for FILENAME.  The specification must be
1425    in VMS syntax in order to be processed by VMS Debug.  */
1426
1427 static char *
1428 full_name (filename)
1429      const char *filename;
1430 {
1431 #ifdef VMS
1432   FILE *fp = fopen (filename, "r");
1433
1434   fgetname (fp, fullname_buff, 1);
1435   fclose (fp);
1436 #else
1437   getcwd (fullname_buff, sizeof (fullname_buff));
1438
1439   strcat (fullname_buff, "/");
1440   strcat (fullname_buff, filename);
1441
1442   /* ??? Insert hairy code here to translate Unix style file specification
1443      to VMS style.  */
1444 #endif
1445
1446   return fullname_buff;
1447 }
1448
1449 /* Lookup a filename (in the list of filenames that we know about here in
1450    vmsdbgout.c) and return its "index".  The index of each (known) filename is
1451    just a unique number which is associated with only that one filename.  We
1452    need such numbers for the sake of generating labels  and references
1453    to those files numbers.  If the filename given as an argument is not
1454    found in our current list, add it to the list and assign it the next
1455    available unique index number.  In order to speed up searches, we remember
1456    the index of the filename was looked up last.  This handles the majority of
1457    all searches.  */
1458
1459 static unsigned int
1460 lookup_filename (file_name)
1461      const char *file_name;
1462 {
1463   static unsigned int last_file_lookup_index = 0;
1464   register char *fn;
1465   register unsigned i;
1466   char *fnam;
1467   long long cdt;
1468   long ebk;
1469   short ffb;
1470   char rfo;
1471   char flen;
1472   struct stat statbuf;
1473
1474   if (stat (file_name, &statbuf) == 0)
1475     {
1476       long gmtoff;
1477 #ifdef VMS
1478       struct tm *ts;
1479
1480       /* Adjust for GMT */
1481       ts = (struct tm *) localtime (&statbuf.st_ctime);
1482       gmtoff = ts->tm_gmtoff;
1483
1484       /* VMS has multiple file format types */
1485       rfo = statbuf.st_fab_rfm;
1486 #else
1487       /* Is GMT adjustment an issue with a cross-compiler? */
1488       gmtoff = 0;
1489
1490       /* Assume stream LF type file */
1491       rfo = 2;
1492 #endif
1493       cdt = 10000000 * (statbuf.st_ctime + gmtoff + vms_epoch_offset);
1494       ebk = statbuf.st_size / 512 + 1;
1495       ffb = statbuf.st_size - ((statbuf.st_size / 512) * 512);
1496       fnam = full_name (file_name);
1497       flen = strlen (fnam);
1498     }
1499   else
1500     {
1501       cdt = 0;
1502       ebk = 0;
1503       ffb = 0;
1504       rfo = 0;
1505       fnam = (char *) "";
1506       flen = 0;
1507     }
1508
1509   /* Check to see if the file name that was searched on the previous call
1510      matches this file name. If so, return the index.  */
1511   if (last_file_lookup_index != 0)
1512     {
1513       fn = file_info_table[last_file_lookup_index].file_name;
1514       if (strcmp (fnam, fn) == 0)
1515         return last_file_lookup_index;
1516     }
1517
1518   /* Didn't match the previous lookup, search the table */
1519   for (i = 1; i < file_info_table_in_use; ++i)
1520     {
1521       fn = file_info_table[i].file_name;
1522       if (strcmp (fnam, fn) == 0)
1523         {
1524           last_file_lookup_index = i;
1525           return i;
1526         }
1527     }
1528
1529   /* Prepare to add a new table entry by making sure there is enough space in
1530      the table to do so.  If not, expand the current table.  */
1531   if (file_info_table_in_use == file_info_table_allocated)
1532     {
1533
1534       file_info_table_allocated += FILE_TABLE_INCREMENT;
1535       file_info_table
1536         = (dst_file_info_ref) xrealloc (file_info_table,
1537                                         (file_info_table_allocated
1538                                          * sizeof (dst_file_info_entry)));
1539     }
1540
1541   /* Add the new entry to the end of the filename table.  */
1542   file_info_table[file_info_table_in_use].file_name = xstrdup (fnam);
1543   file_info_table[file_info_table_in_use].max_line = 0;
1544   file_info_table[file_info_table_in_use].cdt = cdt;
1545   file_info_table[file_info_table_in_use].ebk = ebk;
1546   file_info_table[file_info_table_in_use].ffb = ffb;
1547   file_info_table[file_info_table_in_use].rfo = rfo;
1548   file_info_table[file_info_table_in_use].flen = flen;
1549
1550   last_file_lookup_index = file_info_table_in_use++;
1551   return last_file_lookup_index;
1552 }
1553
1554 /* Output a label to mark the beginning of a source code line entry
1555    and record information relating to this source line, in
1556    'line_info_table' for later output of the .debug_line section.  */
1557
1558 static void
1559 vmsdbgout_source_line (line, filename)
1560      register unsigned line;
1561      register const char *filename;
1562 {
1563   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1564     (*dwarf2_debug_hooks.source_line) (line, filename);
1565
1566   if (debug_info_level >= DINFO_LEVEL_TERSE)
1567     {
1568       dst_line_info_ref line_info;
1569
1570       (*targetm.asm_out.internal_label) (asm_out_file, LINE_CODE_LABEL,
1571                                  line_info_table_in_use);
1572
1573       /* Expand the line info table if necessary.  */
1574       if (line_info_table_in_use == line_info_table_allocated)
1575         {
1576           line_info_table_allocated += LINE_INFO_TABLE_INCREMENT;
1577           line_info_table
1578             = (dst_line_info_ref) xrealloc (line_info_table,
1579                                             (line_info_table_allocated
1580                                              * sizeof (dst_line_info_entry)));
1581         }
1582
1583       /* Add the new entry at the end of the line_info_table.  */
1584       line_info = &line_info_table[line_info_table_in_use++];
1585       line_info->dst_file_num = lookup_filename (filename);
1586       line_info->dst_line_num = line;
1587       if (line > file_info_table[line_info->dst_file_num].max_line)
1588         file_info_table[line_info->dst_file_num].max_line = line;
1589     }
1590 }
1591
1592 /* Record the beginning of a new source file, for later output.
1593    At present, unimplemented.  */
1594
1595 static void
1596 vmsdbgout_start_source_file (lineno, filename)
1597      unsigned int lineno;
1598      const char *filename;
1599 {
1600   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1601     (*dwarf2_debug_hooks.start_source_file) (lineno, filename);
1602 }
1603
1604 /* Record the end of a source file, for later output.
1605    At present, unimplemented.  */
1606
1607 static void
1608 vmsdbgout_end_source_file (lineno)
1609      unsigned int lineno ATTRIBUTE_UNUSED;
1610 {
1611   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1612     (*dwarf2_debug_hooks.end_source_file) (lineno);
1613 }
1614
1615 /* Set up for Debug output at the start of compilation.  */
1616
1617 static void
1618 vmsdbgout_init (main_input_filename)
1619      const char *main_input_filename;
1620 {
1621   const char *language_string = lang_hooks.name;
1622
1623   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1624     (*dwarf2_debug_hooks.init) (main_input_filename);
1625
1626   if (debug_info_level == DINFO_LEVEL_NONE)
1627     return;
1628
1629   /* Remember the name of the primary input file.  */
1630   primary_filename = main_input_filename;
1631
1632   /* Allocate the initial hunk of the file_info_table.  */
1633   file_info_table
1634     = (dst_file_info_ref) xcalloc (FILE_TABLE_INCREMENT,
1635                                    sizeof (dst_file_info_entry));
1636   file_info_table_allocated = FILE_TABLE_INCREMENT;
1637
1638   /* Skip the first entry - file numbers begin at 1 */
1639   file_info_table_in_use = 1;
1640
1641   func_table = (char **) xcalloc (FUNC_TABLE_INCREMENT, sizeof (char *));
1642   func_table_allocated = FUNC_TABLE_INCREMENT;
1643   func_table_in_use = 1;
1644
1645   /* Allocate the initial hunk of the line_info_table.  */
1646   line_info_table
1647     = (dst_line_info_ref) xcalloc (LINE_INFO_TABLE_INCREMENT,
1648                                    sizeof (dst_line_info_entry));
1649   line_info_table_allocated = LINE_INFO_TABLE_INCREMENT;
1650   /* zero-th entry is allocated, but unused */
1651   line_info_table_in_use = 1;
1652
1653   lookup_filename (primary_filename);
1654
1655   if (!strcmp (language_string, "GNU C"))
1656     module_language = DST_K_C;
1657   else if (!strcmp (language_string, "GNU C++"))
1658     module_language = DST_K_CXX;
1659   else if (!strcmp (language_string, "GNU Ada"))
1660     module_language = DST_K_ADA;
1661   else if (!strcmp (language_string, "GNU F77"))
1662     module_language = DST_K_FORTRAN;
1663   else
1664     module_language = DST_K_UNKNOWN;
1665
1666   module_producer = concat (language_string, " ", version_string, NULL);
1667
1668   ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
1669
1670 }
1671
1672 /* Not implemented in VMS Debug.  */
1673
1674 static void
1675 vmsdbgout_define (lineno, buffer)
1676      unsigned int lineno;
1677      const char *buffer;
1678 {
1679   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1680     (*dwarf2_debug_hooks.define) (lineno, buffer);
1681 }
1682
1683 /* Not implemented in VMS Debug.  */
1684
1685 static void
1686 vmsdbgout_undef (lineno, buffer)
1687      unsigned int lineno;
1688      const char *buffer;
1689 {
1690   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1691     (*dwarf2_debug_hooks.undef) (lineno, buffer);
1692 }
1693
1694 /* Not implemented in VMS Debug.  */
1695
1696 static void
1697 vmsdbgout_decl (decl)
1698      tree decl;
1699 {
1700   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1701     (*dwarf2_debug_hooks.function_decl) (decl);
1702 }
1703
1704 /* Not implemented in VMS Debug.  */
1705
1706 static void
1707 vmsdbgout_global_decl (decl)
1708      tree decl;
1709 {
1710   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1711     (*dwarf2_debug_hooks.global_decl) (decl);
1712 }
1713
1714 /* Not implemented in VMS Debug.  */
1715
1716 static void
1717 vmsdbgout_abstract_function (decl)
1718      tree decl;
1719 {
1720   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1721     (*dwarf2_debug_hooks.outlining_inline_function) (decl);
1722 }
1723
1724 /* Output stuff that Debug requires at the end of every file and generate the
1725    VMS Debug debugging info.  */
1726
1727 static void
1728 vmsdbgout_finish (main_input_filename)
1729      const char *main_input_filename ATTRIBUTE_UNUSED;
1730 {
1731   unsigned int i;
1732   int totsize;
1733
1734   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1735     (*dwarf2_debug_hooks.finish) (main_input_filename);
1736
1737   if (debug_info_level == DINFO_LEVEL_NONE)
1738     return;
1739
1740   /* Output a terminator label for the .text section.  */
1741   text_section ();
1742   (*targetm.asm_out.internal_label) (asm_out_file, TEXT_END_LABEL, 0);
1743
1744   /* Output debugging information.
1745      Warning! Do not change the name of the .vmsdebug section without
1746      changing it in the assembler also.  */
1747   named_section (NULL_TREE, ".vmsdebug", 0);
1748   ASM_OUTPUT_ALIGN (asm_out_file, 0);
1749
1750   totsize = write_modbeg (1);
1751   for (i = 1; i < func_table_in_use; i++)
1752     {
1753       totsize += write_rtnbeg (i, 1);
1754       totsize += write_rtnend (i, 1);
1755     }
1756   totsize += write_pclines (1);
1757
1758   write_modbeg (0);
1759   for (i = 1; i < func_table_in_use; i++)
1760     {
1761       write_rtnbeg (i, 0);
1762       write_rtnend (i, 0);
1763     }
1764   write_pclines (0);
1765
1766   if (debug_info_level > DINFO_LEVEL_TERSE)
1767     {
1768       totsize = write_srccorrs (1);
1769       write_srccorrs (0);
1770     }
1771
1772   totsize = write_modend (1);
1773   write_modend (0);
1774 }
1775 #endif /* VMS_DEBUGGING_INFO */