OSDN Git Service

2003-01-30 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
[pf3gnuchains/gcc-fork.git] / gcc / vmsdbgout.c
index afc17f5..a5cb8a2 100644 (file)
@@ -1,27 +1,31 @@
 /* Output VMS debug format symbol table information from the GNU C compiler.
-   Copyright (C) 1997-2001 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
    Contributed by Douglas B. Rupp (rupp@gnat.com).
 
 This file is part of GNU CC.
 
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
 
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
 
 #include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 
 #ifdef VMS_DEBUGGING_INFO
-#include "system.h"
 #include "tree.h"
 #include "flags.h"
 #include "rtl.h"
@@ -29,6 +33,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "vmsdbg.h"
 #include "debug.h"
 #include "langhooks.h"
+#include "function.h"
+#include "target.h"
 
 /* Difference in seconds between the VMS Epoch and the Unix Epoch */
 static const long long vms_epoch_offset = 3506716800ll;
@@ -70,21 +76,18 @@ dst_file_info_entry;
 #define ASM_COMMENT_START ";#"
 #endif
 
-/* Maximum size (in bytes) of an artificially generated label.   */
+/* Maximum size (in bytes) of an artificially generated label.  */
 #define MAX_ARTIFICIAL_LABEL_BYTES     30
 
 /* Make sure we know the sizes of the various types debug can describe. These
    are only defaults.  If the sizes are different for your target, you should
    override these values by defining the appropriate symbols in your tm.h
    file.  */
-#ifndef CHAR_TYPE_SIZE
-#define CHAR_TYPE_SIZE BITS_PER_UNIT
-#endif
 #ifndef PTR_SIZE
 #define PTR_SIZE 4 /* Must be 32 bits for VMS debug info */
 #endif
 
-/* Pointer to an structure of filenames referenced by this compilation unit. */
+/* Pointer to a structure of filenames referenced by this compilation unit.  */
 static dst_file_info_ref file_info_table;
 
 /* Total number of entries in the table (i.e. array) pointed to by
@@ -124,13 +127,6 @@ static unsigned int line_info_table_in_use;
 /* Size (in elements) of increments by which we may expand line_info_table.  */
 #define LINE_INFO_TABLE_INCREMENT 1024
 
-/* The number of the current function definition for which debugging
-   information is being generated.  These numbers range from 1 up to the
-   maximum number of function definitions contained within the current
-   compilation unit.  These numbers are used to create unique label id's unique
-   to each function definition.  */
-static unsigned int current_funcdef_number = 0;
-
 /* Forward declarations for functions defined in this file.  */
 static char *full_name                 PARAMS ((const char *));
 static unsigned int lookup_filename PARAMS ((const char *));
@@ -163,16 +159,17 @@ static void vmsdbgout_end_block           PARAMS ((unsigned int, unsigned int));
 static bool vmsdbgout_ignore_block     PARAMS ((tree));
 static void vmsdbgout_source_line      PARAMS ((unsigned int, const char *));
 static void vmsdbgout_begin_prologue   PARAMS ((unsigned int, const char *));
-static void vmsdbgout_end_epilogue     PARAMS ((void));
+static void vmsdbgout_end_prologue     PARAMS ((unsigned int, const char *));
+static void vmsdbgout_end_function     PARAMS ((unsigned int));
+static void vmsdbgout_end_epilogue     PARAMS ((unsigned int, const char *));
 static void vmsdbgout_begin_function   PARAMS ((tree));
 static void vmsdbgout_decl             PARAMS ((tree));
 static void vmsdbgout_global_decl      PARAMS ((tree));
 static void vmsdbgout_abstract_function PARAMS ((tree));
 
-
 /* The debug hooks structure.  */
 
-struct gcc_debug_hooks vmsdbg_debug_hooks
+const struct gcc_debug_hooks vmsdbg_debug_hooks
 = {vmsdbgout_init,
    vmsdbgout_finish,
    vmsdbgout_define,
@@ -184,10 +181,10 @@ struct gcc_debug_hooks vmsdbg_debug_hooks
    vmsdbgout_ignore_block,
    vmsdbgout_source_line,
    vmsdbgout_begin_prologue,
-   debug_nothing_int,          /* end_prologue */
-   vmsdbgout_end_epilogue,     /* end_epilogue */
-   vmsdbgout_begin_function,   /* begin_function */
-   debug_nothing_int,          /* end_function */
+   vmsdbgout_end_prologue,
+   vmsdbgout_end_epilogue,
+   vmsdbgout_begin_function,
+   vmsdbgout_end_function,
    vmsdbgout_decl,
    vmsdbgout_global_decl,
    debug_nothing_tree,         /* deferred_inline_function */
@@ -240,11 +237,6 @@ struct gcc_debug_hooks vmsdbg_debug_hooks
    : (NUMBYTES(OFFSET) == 2 ? UNALIGNED_SHORT_ASM_OP : ASM_BYTE_OP))
 #endif
 
-/* Pseudo-op for defining a new section.  */
-#ifndef SECTION_ASM_OP
-#define SECTION_ASM_OP ".section"
-#endif
-
 /* Definitions of defaults for formats and names of various special
    (artificial) labels which may be generated within this file (when the -g
    options is used and VMS_DEBUGGING_INFO is in effect.  If necessary, these
@@ -276,37 +268,49 @@ static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
 #endif
 
 #ifndef ASM_OUTPUT_DEBUG_DELTA2
-#define ASM_OUTPUT_DEBUG_DELTA2(FILE,LABEL1,LABEL2)                    \
- do {  fprintf ((FILE), "\t%s\t", UNALIGNED_SHORT_ASM_OP);             \
-       assemble_name (FILE, LABEL1);                                   \
-       fprintf (FILE, "-");                                            \
-       assemble_name (FILE, LABEL2);                                   \
-  } while (0)
+#define ASM_OUTPUT_DEBUG_DELTA2(FILE,LABEL1,LABEL2)                     \
+  do                                                                    \
+    {                                                                   \
+      fprintf ((FILE), "\t%s\t", UNALIGNED_SHORT_ASM_OP);               \
+      assemble_name (FILE, LABEL1);                                     \
+      fprintf (FILE, "-");                                              \
+      assemble_name (FILE, LABEL2);                                     \
+    }                                                                   \
+  while (0)
 #endif
 
 #ifndef ASM_OUTPUT_DEBUG_DELTA4
-#define ASM_OUTPUT_DEBUG_DELTA4(FILE,LABEL1,LABEL2)                    \
- do {  fprintf ((FILE), "\t%s\t", UNALIGNED_INT_ASM_OP);               \
-       assemble_name (FILE, LABEL1);                                   \
-       fprintf (FILE, "-");                                            \
-       assemble_name (FILE, LABEL2);                                   \
-  } while (0)
+#define ASM_OUTPUT_DEBUG_DELTA4(FILE,LABEL1,LABEL2)                     \
+  do                                                                    \
+    {                                                                   \
+      fprintf ((FILE), "\t%s\t", UNALIGNED_INT_ASM_OP);                         \
+      assemble_name (FILE, LABEL1);                                     \
+      fprintf (FILE, "-");                                              \
+      assemble_name (FILE, LABEL2);                                     \
+    }                                                                   \
+  while (0)
 #endif
 
 #ifndef ASM_OUTPUT_DEBUG_ADDR_DELTA
-#define ASM_OUTPUT_DEBUG_ADDR_DELTA(FILE,LABEL1,LABEL2)                        \
- do {  fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP);               \
-       assemble_name (FILE, LABEL1);                                   \
-       fprintf (FILE, "-");                                            \
-       assemble_name (FILE, LABEL2);                                   \
-  } while (0)
+#define ASM_OUTPUT_DEBUG_ADDR_DELTA(FILE,LABEL1,LABEL2)                         \
+  do                                                                    \
+    {                                                                   \
+      fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP);                         \
+      assemble_name (FILE, LABEL1);                                     \
+      fprintf (FILE, "-");                                              \
+      assemble_name (FILE, LABEL2);                                     \
+    }                                                                   \
+  while (0)
 #endif
 
 #ifndef ASM_OUTPUT_DEBUG_ADDR
-#define ASM_OUTPUT_DEBUG_ADDR(FILE,LABEL)                              \
- do {  fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP);               \
-       assemble_name (FILE, LABEL);                                    \
-  } while (0)
+#define ASM_OUTPUT_DEBUG_ADDR(FILE,LABEL)                               \
+  do                                                                    \
+    {                                                                   \
+      fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP);                         \
+      assemble_name (FILE, LABEL);                                      \
+    }                                                                   \
+  while (0)
 #endif
 
 #ifndef ASM_OUTPUT_DEBUG_ADDR_CONST
@@ -348,27 +352,28 @@ static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
 #endif
 
 /* This is similar to the default ASM_OUTPUT_ASCII, except that no trailing
-   newline is produced.  When flag_verbose_asm is asserted, we add commnetary
+   newline is produced.  When flag_verbose_asm is asserted, we add commentary
    at the end of the line, so we must avoid output of a newline here.  */
 #ifndef ASM_OUTPUT_DEBUG_STRING
-#define ASM_OUTPUT_DEBUG_STRING(FILE,P)        \
-  do {                                 \
-    register int slen = strlen(P);      \
-    register char *p = (P);            \
-    register int i;                    \
-    fprintf (FILE, "\t.ascii \"");     \
-    for (i = 0; i < slen; i++)         \
-      {                                        \
-         register int c = p[i];        \
-         if (c == '\"' || c == '\\')   \
-           putc ('\\', FILE);          \
-         if (c >= ' ' && c < 0177)     \
-           putc (c, FILE);             \
-         else                          \
-           fprintf (FILE, "\\%o", c);  \
-      }                                        \
-    fprintf (FILE, "\"");              \
-  }                                    \
+#define ASM_OUTPUT_DEBUG_STRING(FILE,P)                \
+  do                                           \
+    {                                          \
+      register int slen = strlen(P);           \
+      register char *p = (P);                  \
+      register int i;                          \
+      fprintf (FILE, "\t.ascii \"");           \
+      for (i = 0; i < slen; i++)               \
+       {                                       \
+         register int c = p[i];                \
+         if (c == '\"' || c == '\\')           \
+           putc ('\\', FILE);                  \
+         if (c >= ' ' && c < 0177)             \
+           putc (c, FILE);                     \
+         else                                  \
+           fprintf (FILE, "\\%o", c);          \
+       }                                       \
+      fprintf (FILE, "\"");                    \
+    }                                          \
   while (0)
 #endif
 
@@ -376,13 +381,14 @@ static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
    macro has the same effect as ASM_OUTPUT_LABELREF, but copies to
    a string rather than writing to a file.  */
 #ifndef ASM_NAME_TO_STRING
-#define ASM_NAME_TO_STRING(STR, NAME) \
-  do {                                                                       \
-      if ((NAME)[0] == '*')                                                  \
-       strcpy (STR, NAME+1);                                                 \
-      else                                                                   \
-       strcpy (STR, NAME);                                                   \
-  }                                                                           \
+#define ASM_NAME_TO_STRING(STR, NAME)          \
+  do                                           \
+    {                                          \
+      if ((NAME)[0] == '*')                    \
+       strcpy (STR, NAME+1);                   \
+      else                                     \
+       strcpy (STR, NAME);                     \
+    }                                          \
   while (0)
 #endif
 
@@ -437,7 +443,7 @@ restart:
       break;
 
     case CONST:
-      /* This used to output parentheses around the expression, but that does 
+      /* This used to output parentheses around the expression, but that does
          not work on the 386 (either ATT or BSD assembler).  */
       addr_const_to_string (buf1, XEXP (x, 0));
       strcat (str, buf1);
@@ -521,117 +527,145 @@ restart:
     }
 }
 
+/* Output the debug header HEADER.  Also output COMMENT if flag_verbose_asm is
+   set.  Return the header size.  Just return the size if DOSIZEONLY is
+   nonzero.  */
+
 static int
 write_debug_header (header, comment, dosizeonly)
      DST_HEADER *header;
      const char *comment;
      int dosizeonly;
 {
-  if (dosizeonly)
-    return 4;
+  if (!dosizeonly)
+    {
+      ASM_OUTPUT_DEBUG_DATA2 (asm_out_file,
+                             header->dst__header_length.dst_w_length);
+
+      if (flag_verbose_asm)
+       fprintf (asm_out_file, "\t%s record length", ASM_COMMENT_START);
+      fputc ('\n', asm_out_file);
 
-  ASM_OUTPUT_DEBUG_DATA2 (asm_out_file,
-                         header->dst__header_length.dst_w_length);
-  if (flag_verbose_asm)
-    fprintf (asm_out_file, "\t%s record length", ASM_COMMENT_START);
-  fputc ('\n', asm_out_file);
+      ASM_OUTPUT_DEBUG_DATA2 (asm_out_file,
+                             header->dst__header_type.dst_w_type);
 
-  ASM_OUTPUT_DEBUG_DATA2 (asm_out_file,
-                         header->dst__header_type.dst_w_type);
-  if (flag_verbose_asm)
-    fprintf (asm_out_file, "\t%s record type (%s)", ASM_COMMENT_START,
-            comment);
+      if (flag_verbose_asm)
+       fprintf (asm_out_file, "\t%s record type (%s)", ASM_COMMENT_START,
+                comment);
 
-  fputc ('\n', asm_out_file);
+      fputc ('\n', asm_out_file);
+    }
 
   return 4;
 }
 
+/* Output the address of SYMBOL.  Also output COMMENT if flag_verbose_asm is
+   set.  Return the address size.  Just return the size if DOSIZEONLY is
+   nonzero.  */
+
 static int
 write_debug_addr (symbol, comment, dosizeonly)
      char *symbol;
      const char *comment;
      int dosizeonly;
 {
-  if (dosizeonly)
-    return PTR_SIZE;
+  if (!dosizeonly)
+    {
+      ASM_OUTPUT_DEBUG_ADDR (asm_out_file, symbol);
+      if (flag_verbose_asm)
+       fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
+      fputc ('\n', asm_out_file);
+    }
 
-  ASM_OUTPUT_DEBUG_ADDR (asm_out_file, symbol);
-  if (flag_verbose_asm)
-    fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
-  fputc ('\n', asm_out_file);
-  
   return PTR_SIZE;
 }
 
+/* Output the single byte DATA1.  Also output COMMENT if flag_verbose_asm is
+   set.  Return the data size.  Just return the size if DOSIZEONLY is
+   nonzero.  */
+
 static int
 write_debug_data1 (data1, comment, dosizeonly)
      unsigned int data1;
      const char *comment;
      int dosizeonly;
 {
-  if (dosizeonly)
-    return 1;
+  if (!dosizeonly)
+    {
+      ASM_OUTPUT_DEBUG_DATA1 (asm_out_file, data1);
+      if (flag_verbose_asm)
+       fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
+      fputc ('\n', asm_out_file);
+    }
 
-  ASM_OUTPUT_DEBUG_DATA1 (asm_out_file, data1);
-  if (flag_verbose_asm)
-    fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
-  fputc ('\n', asm_out_file);
-  
   return 1;
 }
 
+/* Output the single word DATA2.  Also output COMMENT if flag_verbose_asm is
+   set.  Return the data size.  Just return the size if DOSIZEONLY is
+   nonzero.  */
+
 static int
 write_debug_data2 (data2, comment, dosizeonly)
      unsigned int data2;
      const char *comment;
      int dosizeonly;
 {
-  if (dosizeonly)
-    return 2;
+  if (!dosizeonly)
+    {
+      ASM_OUTPUT_DEBUG_DATA2 (asm_out_file, data2);
+      if (flag_verbose_asm)
+       fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
+      fputc ('\n', asm_out_file);
+    }
 
-  ASM_OUTPUT_DEBUG_DATA2 (asm_out_file, data2);
-  if (flag_verbose_asm)
-    fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
-  fputc ('\n', asm_out_file);
-  
   return 2;
 }
 
+/* Output double word DATA4.  Also output COMMENT if flag_verbose_asm is set.
+   Return the data size.  Just return the size if DOSIZEONLY is nonzero.  */
+
 static int
 write_debug_data4 (data4, comment, dosizeonly)
      unsigned long data4;
      const char *comment;
      int dosizeonly;
 {
-  if (dosizeonly)
-    return 4;
+  if (!dosizeonly)
+    {
+      ASM_OUTPUT_DEBUG_DATA4 (asm_out_file, data4);
+      if (flag_verbose_asm)
+       fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
+      fputc ('\n', asm_out_file);
+    }
 
-  ASM_OUTPUT_DEBUG_DATA4 (asm_out_file, data4);
-  if (flag_verbose_asm)
-    fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
-  fputc ('\n', asm_out_file);
-  
   return 4;
 }
 
+/* Output quad word DATA8.  Also output COMMENT if flag_verbose_asm is set.
+   Return the data size.  Just return the size if DOSIZEONLY is nonzero.  */
+
 static int
 write_debug_data8 (data8, comment, dosizeonly)
      unsigned long long data8;
      const char *comment;
      int dosizeonly;
 {
-  if (dosizeonly)
-    return 8;
+  if (!dosizeonly)
+    {
+      ASM_OUTPUT_DEBUG_DATA8 (asm_out_file, data8);
+      if (flag_verbose_asm)
+       fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
+      fputc ('\n', asm_out_file);
+    }
 
-  ASM_OUTPUT_DEBUG_DATA8 (asm_out_file, data8);
-  if (flag_verbose_asm)
-    fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
-  fputc ('\n', asm_out_file);
-  
   return 8;
 }
 
+/* Output the difference between LABEL1 and LABEL2.  Also output COMMENT if
+   flag_verbose_asm is set.  Return the data size.  Just return the size if
+   DOSIZEONLY is nonzero.  */
+
 static int
 write_debug_delta4 (label1, label2, comment, dosizeonly)
      char *label1;
@@ -639,39 +673,45 @@ write_debug_delta4 (label1, label2, comment, dosizeonly)
      const char *comment;
      int dosizeonly;
 {
-  if (dosizeonly)
-    return 4;
+  if (!dosizeonly)
+    {
+      ASM_OUTPUT_DEBUG_DELTA4 (asm_out_file, label1, label2);
+      if (flag_verbose_asm)
+       fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
+      fputc ('\n', asm_out_file);
+    }
 
-  ASM_OUTPUT_DEBUG_DELTA4(asm_out_file, label1, label2);
-  if (flag_verbose_asm)
-    fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
-  fputc ('\n', asm_out_file);
-  
   return 4;
 }
 
+/* Output a character string STRING.  Also write COMMENT if flag_verbose_asm is
+   set.  Return the string length.  Just return the length if DOSIZEONLY is
+   nonzero.  */
+
 static int
 write_debug_string (string, comment, dosizeonly)
      char *string;
      const char *comment;
      int dosizeonly;
 {
-  if (dosizeonly)
-    return strlen (string);
+  if (!dosizeonly)
+    {
+      ASM_OUTPUT_DEBUG_STRING (asm_out_file, string);
+      if (flag_verbose_asm)
+       fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
+      fputc ('\n', asm_out_file);
+    }
 
-  ASM_OUTPUT_DEBUG_STRING (asm_out_file, string);
-  if (flag_verbose_asm)
-    fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
-  fputc ('\n', asm_out_file);
-  
   return strlen (string);
 }
 
+/* Output a module begin header and return the header size.  Just return the
+   size if DOSIZEONLY is nonzero.  */
+
 static int
 write_modbeg (dosizeonly)
      int dosizeonly;
 {
-
   DST_MODULE_BEGIN modbeg;
   DST_MB_TRLR mb_trlr;
   int i;
@@ -680,7 +720,7 @@ write_modbeg (dosizeonly)
   int prodnamelen;
   int totsize = 0;
 
-  /* Assumes primary filename has Unix syntax file spec. */
+  /* Assumes primary filename has Unix syntax file spec.  */
   module_name = xstrdup (basename ((char *) primary_filename));
 
   m = strrchr (module_name, '.');
@@ -729,6 +769,9 @@ write_modbeg (dosizeonly)
   return totsize;
 }
 
+/* Output a module end trailer and return the trailer size.   Just return
+   the size if DOSIZEONLY is nonzero.  */
+
 static int
 write_modend (dosizeonly)
      int dosizeonly;
@@ -746,13 +789,16 @@ write_modend (dosizeonly)
   return totsize;
 }
 
+/* Output a routine begin header routine RTNNUM and return the header size.
+   Just return the size if DOSIZEONLY is nonzero.  */
+
 static int
 write_rtnbeg (rtnnum, dosizeonly)
      int rtnnum;
      int dosizeonly;
 {
   char *rtnname;
-  int rtnnamelen, rtnentrynamelen;
+  int rtnnamelen;
   char *rtnentryname;
   int totsize = 0;
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
@@ -761,10 +807,7 @@ write_rtnbeg (rtnnum, dosizeonly)
 
   rtnname = func_table[rtnnum];
   rtnnamelen = strlen (rtnname);
-  rtnentrynamelen = rtnnamelen + 4; /* "..en" */
-  rtnentryname = (char *) xmalloc (rtnentrynamelen + 1);
-  strcpy (rtnentryname, rtnname);
-  strcat (rtnentryname, "..en");
+  rtnentryname = concat (rtnname, "..en", NULL);
 
   if (!strcmp (rtnname, "main"))
     {
@@ -777,7 +820,7 @@ write_rtnbeg (rtnnum, dosizeonly)
       /* header size - 1st byte + flag byte + STO_LW size
         + string count byte + string length */
       header.dst__header_length.dst_w_length
-        = DST_K_DST_HEADER_SIZE - 1 + 1 + 4 + 1 + strlen (go);
+       = DST_K_DST_HEADER_SIZE - 1 + 1 + 4 + 1 + strlen (go);
       header.dst__header_type.dst_w_type = 0x17;
 
       totsize += write_debug_header (&header, "transfer", dosizeonly);
@@ -841,6 +884,9 @@ write_rtnbeg (rtnnum, dosizeonly)
   return totsize;
 }
 
+/* Output a routine end trailer for routine RTNNUM and return the header size.
+   Just return the size if DOSIZEONLY is nonzero.  */
+
 static int
 write_rtnend (rtnnum, dosizeonly)
      int rtnnum;
@@ -882,6 +928,9 @@ write_rtnend (rtnnum, dosizeonly)
  ((I) < 256 ? DST_K_INCR_LINUM \
   : (I) < 65536 ? DST_K_INCR_LINUM_W : DST_K_INCR_LINUM_L)
 
+/* Output the PC to line number correlations and return the size.  Just return
+   the size if DOSIZEONLY is nonzero */
+
 static int
 write_pclines (dosizeonly)
      int dosizeonly;
@@ -940,8 +989,8 @@ write_pclines (dosizeonly)
   totsize += write_debug_data1 (pcline.dst_b_pcline_command,
                                "line_num (SET LINUM LONG)", dosizeonly);
 
-  sprintf (buff, "line_num (%d)", ln - 1);
-  totsize += write_debug_data4 (ln - 1, buff, dosizeonly);
+  sprintf (buff, "line_num (%d)", ln ? ln - 1 : 0);
+  totsize += write_debug_data4 (ln ? ln - 1 : 0, buff, dosizeonly);
 
   lastln = ln;
   strcpy (lastlabel, TEXT_SECTION_ASM_OP);
@@ -1009,6 +1058,10 @@ write_pclines (dosizeonly)
   return totsize;
 }
 
+/* Output a source correlation for file FILEID using information saved in
+   FILE_INFO_ENTRY and return the size.  Just return the size if DOSIZEONLY is
+   nonzero.  */
+
 static int
 write_srccorr (fileid, file_info_entry, dosizeonly)
      int fileid;
@@ -1071,7 +1124,7 @@ write_srccorr (fileid, file_info_entry, dosizeonly)
     = DST_K_SOURCE;
 
   src_cmdtrlr.dst_b_src_df_libmodname = 0;
-  
+
   totsize += write_debug_header (&src_header.dst_a_source_corr_header,
                                 "source corr", dosizeonly);
   totsize += write_debug_data1 (src_command.dst_b_src_command,
@@ -1091,7 +1144,7 @@ write_srccorr (fileid, file_info_entry, dosizeonly)
   totsize += write_debug_data8
     (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt,
      "source_corr (creation date)", dosizeonly);
-  
+
   totsize += write_debug_data4
     (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk,
      "source_corr (EOF block number)", dosizeonly);
@@ -1136,67 +1189,74 @@ write_srccorr (fileid, file_info_entry, dosizeonly)
   src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
     = DST_K_SOURCE;
 
-  totsize += write_debug_header (&src_header.dst_a_source_corr_header,
-                                "source corr", dosizeonly);
-
-  totsize += write_debug_data1 (src_command_sf.dst_b_src_command,
-                               "source_corr (src setfile)", dosizeonly);
-
-  totsize += write_debug_data2
-    (src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword,
-     "source_corr (fileid)", dosizeonly);
-
-  totsize += write_debug_data1 (src_command_sr.dst_b_src_command,
-                               "source_corr (setrec)", dosizeonly);
-
-  totsize += write_debug_data2
-    (src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword,
-     "source_corr (recnum)", dosizeonly);
-
-  totsize += write_debug_data1 (src_command_sl.dst_b_src_command,
-                               "source_corr (setlnum)", dosizeonly);
+  if (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword)
+    {
+      totsize += write_debug_header (&src_header.dst_a_source_corr_header,
+                                    "source corr", dosizeonly);
 
-  totsize += write_debug_data4
-    (src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong,
-     "source_corr (linenum)", dosizeonly);
+      totsize += write_debug_data1 (src_command_sf.dst_b_src_command,
+                                   "source_corr (src setfile)", dosizeonly);
 
-  totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
-                               "source_corr (deflines)", dosizeonly);
+      totsize += write_debug_data2
+       (src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword,
+        "source_corr (fileid)", dosizeonly);
 
-  sprintf (buff, "source_corr (%d)",
-          src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
-  totsize += write_debug_data2
-    (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword, buff, dosizeonly);
+      totsize += write_debug_data1 (src_command_sr.dst_b_src_command,
+                                   "source_corr (setrec)", dosizeonly);
 
-  while (linesleft > 0)
-    {
-      src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
-       = DST_K_SOURCE_CORR_HEADER_SIZE + 3 - 1;
-      src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
-       = DST_K_SOURCE;
-      src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W;
+      totsize += write_debug_data2
+       (src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword,
+        "source_corr (recnum)", dosizeonly);
 
-      if (linesleft > 65534)
-       linesleft = linesleft - 65534, linestodo = 65534;
-      else
-       linestodo = linesleft, linesleft = 0;
+      totsize += write_debug_data1 (src_command_sl.dst_b_src_command,
+                                   "source_corr (setlnum)", dosizeonly);
 
-      src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo;
+      totsize += write_debug_data4
+       (src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong,
+        "source_corr (linenum)", dosizeonly);
 
-      totsize += write_debug_header (&src_header.dst_a_source_corr_header,
-                                    "source corr", dosizeonly);
       totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
                                    "source_corr (deflines)", dosizeonly);
+
       sprintf (buff, "source_corr (%d)",
               src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
       totsize += write_debug_data2
        (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword,
         buff, dosizeonly);
+
+      while (linesleft > 0)
+       {
+         src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
+           = DST_K_SOURCE_CORR_HEADER_SIZE + 3 - 1;
+         src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
+           = DST_K_SOURCE;
+         src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W;
+
+         if (linesleft > 65534)
+           linesleft = linesleft - 65534, linestodo = 65534;
+         else
+           linestodo = linesleft, linesleft = 0;
+
+         src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo;
+
+         totsize += write_debug_header (&src_header.dst_a_source_corr_header,
+                                        "source corr", dosizeonly);
+         totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
+                                       "source_corr (deflines)", dosizeonly);
+         sprintf (buff, "source_corr (%d)",
+                  src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
+         totsize += write_debug_data2
+           (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword,
+            buff, dosizeonly);
+       }
     }
 
   return totsize;
 }
 
+/* Output all the source correlation entries and return the size.  Just return
+   the size if DOSIZEONLY is nonzero.  */
+
 static int
 write_srccorrs (dosizeonly)
      int dosizeonly;
@@ -1208,8 +1268,7 @@ write_srccorrs (dosizeonly)
     totsize += write_srccorr (i, file_info_table[i], dosizeonly);
 
   return totsize;
-}     
-
+}
 \f
 /* Output a marker (i.e. a label) for the beginning of a function, before
    the prologue.  */
@@ -1226,9 +1285,8 @@ vmsdbgout_begin_prologue (line, file)
 
   if (debug_info_level > DINFO_LEVEL_NONE)
     {
-      current_funcdef_number++;
       ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL,
-                                  current_funcdef_number);
+                                  current_function_funcdef_no);
       ASM_OUTPUT_LABEL (asm_out_file, label);
     }
 }
@@ -1236,38 +1294,61 @@ vmsdbgout_begin_prologue (line, file)
 /* Output a marker (i.e. a label) for the beginning of a function, after
    the prologue.  */
 
-void
-vmsdbgout_after_prologue ()
+static void
+vmsdbgout_end_prologue (line, file)
+     unsigned int line;
+     const char *file;
 {
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
+  if (write_symbols == VMS_AND_DWARF2_DEBUG)
+    (*dwarf2_debug_hooks.end_prologue) (line, file);
+
   if (debug_info_level > DINFO_LEVEL_TERSE)
     {
       ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL,
-                                  current_funcdef_number);
+                                  current_function_funcdef_no);
       ASM_OUTPUT_LABEL (asm_out_file, label);
+
+      /* VMS PCA expects every PC range to correlate to some line and file */
+      vmsdbgout_source_line (line, file);
     }
 }
 
+/* No output for VMS debug, but make obligatory call to Dwarf2 debug */
+
+static void
+vmsdbgout_end_function (line)
+     unsigned int line;
+{
+  if (write_symbols == VMS_AND_DWARF2_DEBUG)
+    (*dwarf2_debug_hooks.end_function) (line);
+}
+
 /* Output a marker (i.e. a label) for the absolute end of the generated code
    for a function definition.  This gets called *after* the epilogue code has
    been generated.  */
 
 static void
-vmsdbgout_end_epilogue ()
+vmsdbgout_end_epilogue (line, file)
+     unsigned int line;
+     const char *file;
 {
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
   if (write_symbols == VMS_AND_DWARF2_DEBUG)
-    (*dwarf2_debug_hooks.end_epilogue) ();
+    (*dwarf2_debug_hooks.end_epilogue) (line, file);
 
   if (debug_info_level > DINFO_LEVEL_NONE)
     {
       /* Output a label to mark the endpoint of the code generated for this
-         function.        */
+         function.  */
       ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL,
-                                  current_funcdef_number);
+                                  current_function_funcdef_no);
       ASM_OUTPUT_LABEL (asm_out_file, label);
+
+      /* VMS PCA expects every PC range to correlate to some line and file */
+      vmsdbgout_source_line (line, file);
     }
 }
 
@@ -1283,7 +1364,7 @@ vmsdbgout_begin_block (line, blocknum)
     (*dwarf2_debug_hooks.begin_block) (line, blocknum);
 
   if (debug_info_level > DINFO_LEVEL_TERSE)
-    ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BLOCK_BEGIN_LABEL, blocknum);
+    (*targetm.asm_out.internal_label) (asm_out_file, BLOCK_BEGIN_LABEL, blocknum);
 }
 
 /* Output a marker (i.e. a label) for the end of the generated code for a
@@ -1298,9 +1379,11 @@ vmsdbgout_end_block (line, blocknum)
     (*dwarf2_debug_hooks.end_block) (line, blocknum);
 
   if (debug_info_level > DINFO_LEVEL_TERSE)
-    ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BLOCK_END_LABEL, blocknum);
+    (*targetm.asm_out.internal_label) (asm_out_file, BLOCK_END_LABEL, blocknum);
 }
 
+/* Not implemented in VMS Debug.  */
+
 static bool
 vmsdbgout_ignore_block (block)
      tree block;
@@ -1313,6 +1396,8 @@ vmsdbgout_ignore_block (block)
   return retval;
 }
 
+/* Add an entry for function DECL into the func_table.  */
+
 static void
 vmsdbgout_begin_function (decl)
      tree decl;
@@ -1335,6 +1420,9 @@ vmsdbgout_begin_function (decl)
 
 static char fullname_buff [4096];
 
+/* Return the full file specification for FILENAME.  The specification must be
+   in VMS syntax in order to be processed by VMS Debug.  */
+
 static char *
 full_name (filename)
      const char *filename;
@@ -1360,9 +1448,8 @@ full_name (filename)
 /* Lookup a filename (in the list of filenames that we know about here in
    vmsdbgout.c) and return its "index".  The index of each (known) filename is
    just a unique number which is associated with only that one filename.  We
-   need such numbers for the sake of generating labels (in the .debug_sfnames
-   section) and references to those files numbers (in the .debug_srcinfo
-   and.debug_macinfo sections).  If the filename given as an argument is not
+   need such numbers for the sake of generating labels  and references
+   to those files numbers.  If the filename given as an argument is not
    found in our current list, add it to the list and assign it the next
    available unique index number.  In order to speed up searches, we remember
    the index of the filename was looked up last.  This handles the majority of
@@ -1385,15 +1472,26 @@ lookup_filename (file_name)
 
   if (stat (file_name, &statbuf) == 0)
     {
-      cdt = 10000000 * (statbuf.st_ctime + vms_epoch_offset);
-      ebk = statbuf.st_size / 512 + 1;
-      ffb = statbuf.st_size - ((statbuf.st_size / 512) * 512);
+      long gmtoff;
 #ifdef VMS
+      struct tm *ts;
+
+      /* Adjust for GMT */
+      ts = (struct tm *) localtime (&statbuf.st_ctime);
+      gmtoff = ts->tm_gmtoff;
+
+      /* VMS has multiple file format types */
       rfo = statbuf.st_fab_rfm;
 #else
+      /* Is GMT adjustment an issue with a cross-compiler? */
+      gmtoff = 0;
+
       /* Assume stream LF type file */
       rfo = 2;
 #endif
+      cdt = 10000000 * (statbuf.st_ctime + gmtoff + vms_epoch_offset);
+      ebk = statbuf.st_size / 512 + 1;
+      ffb = statbuf.st_size - ((statbuf.st_size / 512) * 512);
       fnam = full_name (file_name);
       flen = strlen (fnam);
     }
@@ -1403,7 +1501,7 @@ lookup_filename (file_name)
       ebk = 0;
       ffb = 0;
       rfo = 0;
-      fnam = (char *) 0;
+      fnam = (char *) "";
       flen = 0;
     }
 
@@ -1427,7 +1525,7 @@ lookup_filename (file_name)
        }
     }
 
-  /* Prepare to add a new table entry by making sure there is enough space in 
+  /* Prepare to add a new table entry by making sure there is enough space in
      the table to do so.  If not, expand the current table.  */
   if (file_info_table_in_use == file_info_table_allocated)
     {
@@ -1468,7 +1566,7 @@ vmsdbgout_source_line (line, filename)
     {
       dst_line_info_ref line_info;
 
-      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, LINE_CODE_LABEL,
+      (*targetm.asm_out.internal_label) (asm_out_file, LINE_CODE_LABEL,
                                 line_info_table_in_use);
 
       /* Expand the line info table if necessary.  */
@@ -1479,7 +1577,7 @@ vmsdbgout_source_line (line, filename)
            = (dst_line_info_ref) xrealloc (line_info_table,
                                            (line_info_table_allocated
                                             * sizeof (dst_line_info_entry)));
-         }
+       }
 
       /* Add the new entry at the end of the line_info_table.  */
       line_info = &line_info_table[line_info_table_in_use++];
@@ -1564,15 +1662,14 @@ vmsdbgout_init (main_input_filename)
   else
     module_language = DST_K_UNKNOWN;
 
-  module_producer
-    = (char *) xmalloc (strlen (language_string) + 1
-                       + strlen (version_string + 1));
-  sprintf (module_producer, "%s %s", language_string, version_string);
+  module_producer = concat (language_string, " ", version_string, NULL);
 
   ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
 
 }
 
+/* Not implemented in VMS Debug.  */
+
 static void
 vmsdbgout_define (lineno, buffer)
      unsigned int lineno;
@@ -1582,6 +1679,8 @@ vmsdbgout_define (lineno, buffer)
     (*dwarf2_debug_hooks.define) (lineno, buffer);
 }
 
+/* Not implemented in VMS Debug.  */
+
 static void
 vmsdbgout_undef (lineno, buffer)
      unsigned int lineno;
@@ -1591,6 +1690,8 @@ vmsdbgout_undef (lineno, buffer)
     (*dwarf2_debug_hooks.undef) (lineno, buffer);
 }
 
+/* Not implemented in VMS Debug.  */
+
 static void
 vmsdbgout_decl (decl)
      tree decl;
@@ -1599,6 +1700,8 @@ vmsdbgout_decl (decl)
     (*dwarf2_debug_hooks.function_decl) (decl);
 }
 
+/* Not implemented in VMS Debug.  */
+
 static void
 vmsdbgout_global_decl (decl)
      tree decl;
@@ -1607,6 +1710,8 @@ vmsdbgout_global_decl (decl)
     (*dwarf2_debug_hooks.global_decl) (decl);
 }
 
+/* Not implemented in VMS Debug.  */
+
 static void
 vmsdbgout_abstract_function (decl)
      tree decl;
@@ -1615,8 +1720,8 @@ vmsdbgout_abstract_function (decl)
     (*dwarf2_debug_hooks.outlining_inline_function) (decl);
 }
 
-/* Output stuff that Debug requires at the end of every file,
-   and generate the VMS Debug debugging info.  */
+/* Output stuff that Debug requires at the end of every file and generate the
+   VMS Debug debugging info.  */
 
 static void
 vmsdbgout_finish (input_filename)
@@ -1633,11 +1738,11 @@ vmsdbgout_finish (input_filename)
 
   /* Output a terminator label for the .text section.  */
   text_section ();
-  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, TEXT_END_LABEL, 0);
+  (*targetm.asm_out.internal_label) (asm_out_file, TEXT_END_LABEL, 0);
 
   /* Output debugging information.
      Warning! Do not change the name of the .vmsdebug section without
-     changing it in the assembler also. */
+     changing it in the assembler also.  */
   named_section (NULL_TREE, ".vmsdebug", 0);
   ASM_OUTPUT_ALIGN (asm_out_file, 0);