OSDN Git Service

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