OSDN Git Service

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