OSDN Git Service

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