OSDN Git Service

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