OSDN Git Service

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