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