1132718Skan/* Output VMS debug format symbol table information from GCC.
290075Sobrien   Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3169689Skan   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
490075Sobrien   Contributed by Douglas B. Rupp (rupp@gnat.com).
5169689Skan   Updated by Bernard W. Giroud (bgiroud@users.sourceforge.net).
690075Sobrien
7132718SkanThis file is part of GCC.
890075Sobrien
990075SobrienGCC is free software; you can redistribute it and/or modify it under
1090075Sobrienthe terms of the GNU General Public License as published by the Free
1190075SobrienSoftware Foundation; either version 2, or (at your option) any later
1290075Sobrienversion.
1390075Sobrien
1490075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1590075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1690075SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1790075Sobrienfor more details.
1890075Sobrien
1990075SobrienYou should have received a copy of the GNU General Public License
2090075Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
21169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
22169689Skan02110-1301, USA.  */
2390075Sobrien
2490075Sobrien#include "config.h"
25132718Skan#include "system.h"
26132718Skan#include "coretypes.h"
27132718Skan#include "tm.h"
2890075Sobrien
2990075Sobrien#ifdef VMS_DEBUGGING_INFO
3090075Sobrien#include "tree.h"
31169689Skan#include "version.h"
3290075Sobrien#include "flags.h"
3390075Sobrien#include "rtl.h"
3490075Sobrien#include "output.h"
3590075Sobrien#include "vmsdbg.h"
3690075Sobrien#include "debug.h"
3790075Sobrien#include "langhooks.h"
38117395Skan#include "function.h"
39132718Skan#include "target.h"
4090075Sobrien
4190075Sobrien/* Difference in seconds between the VMS Epoch and the Unix Epoch */
4290075Sobrienstatic const long long vms_epoch_offset = 3506716800ll;
4390075Sobrien
4490075Sobrien/* NOTE: In the comments in this file, many references are made to "Debug
4590075Sobrien   Symbol Table".  This term is abbreviated as `DST' throughout the remainder
4690075Sobrien   of this file.  */
4790075Sobrien
4890075Sobrientypedef struct dst_line_info_struct *dst_line_info_ref;
4990075Sobrien
5090075Sobrien/* Each entry in the line_info_table maintains the file and
5190075Sobrien   line number associated with the label generated for that
5290075Sobrien   entry.  The label gives the PC value associated with
5390075Sobrien   the line number entry.  */
5490075Sobrientypedef struct dst_line_info_struct
5590075Sobrien{
5690075Sobrien  unsigned long dst_file_num;
5790075Sobrien  unsigned long dst_line_num;
5890075Sobrien}
5990075Sobriendst_line_info_entry;
6090075Sobrien
6190075Sobrientypedef struct dst_file_info_struct *dst_file_info_ref;
6290075Sobrien
6390075Sobrientypedef struct dst_file_info_struct
6490075Sobrien{
6590075Sobrien  char *file_name;
6690075Sobrien  unsigned int max_line;
6790075Sobrien  unsigned int listing_line_start;
6890075Sobrien  long long cdt;
6990075Sobrien  long ebk;
7090075Sobrien  short ffb;
7190075Sobrien  char rfo;
7290075Sobrien  char flen;
7390075Sobrien}
7490075Sobriendst_file_info_entry;
7590075Sobrien
7690075Sobrien/* How to start an assembler comment.  */
7790075Sobrien#ifndef ASM_COMMENT_START
7890075Sobrien#define ASM_COMMENT_START ";#"
7990075Sobrien#endif
8090075Sobrien
8190075Sobrien/* Maximum size (in bytes) of an artificially generated label.  */
8290075Sobrien#define MAX_ARTIFICIAL_LABEL_BYTES	30
8390075Sobrien
8490075Sobrien/* Make sure we know the sizes of the various types debug can describe. These
8590075Sobrien   are only defaults.  If the sizes are different for your target, you should
8690075Sobrien   override these values by defining the appropriate symbols in your tm.h
8790075Sobrien   file.  */
8890075Sobrien#ifndef PTR_SIZE
8990075Sobrien#define PTR_SIZE 4 /* Must be 32 bits for VMS debug info */
9090075Sobrien#endif
9190075Sobrien
92117395Skan/* Pointer to a structure of filenames referenced by this compilation unit.  */
9390075Sobrienstatic dst_file_info_ref file_info_table;
9490075Sobrien
9590075Sobrien/* Total number of entries in the table (i.e. array) pointed to by
9690075Sobrien   `file_info_table'.  This is the *total* and includes both used and unused
9790075Sobrien   slots.  */
9890075Sobrienstatic unsigned int file_info_table_allocated;
9990075Sobrien
10090075Sobrien/* Number of entries in the file_info_table which are actually in use.  */
10190075Sobrienstatic unsigned int file_info_table_in_use;
10290075Sobrien
10390075Sobrien/* Size (in elements) of increments by which we may expand the filename
10490075Sobrien   table.  */
10590075Sobrien#define FILE_TABLE_INCREMENT 64
10690075Sobrien
107169689Skan/* A structure to hold basic information for the VMS end
108169689Skan   routine.  */
109169689Skan
110169689Skantypedef struct vms_func_struct
111169689Skan{
112169689Skan  const char *vms_func_name;
113169689Skan  unsigned funcdef_number;
114169689Skan}
115169689Skanvms_func_node;
116169689Skan
117169689Skantypedef struct vms_func_struct *vms_func_ref;
118169689Skan
11990075Sobrienstatic unsigned int func_table_allocated;
12090075Sobrienstatic unsigned int func_table_in_use;
12190075Sobrien#define FUNC_TABLE_INCREMENT 256
12290075Sobrien
123169689Skan/* A pointer to the base of a table that contains frame description
124169689Skan   information for each routine.  */
125169689Skanstatic vms_func_ref func_table;
126169689Skan
12790075Sobrien/* Local pointer to the name of the main input file.  Initialized in
12890075Sobrien   avmdbgout_init.  */
12990075Sobrienstatic const char *primary_filename;
13090075Sobrien
13190075Sobrienstatic char *module_producer;
13290075Sobrienstatic unsigned int module_language;
13390075Sobrien
13490075Sobrien/* A pointer to the base of a table that contains line information
13590075Sobrien   for each source code line in .text in the compilation unit.  */
13690075Sobrienstatic dst_line_info_ref line_info_table;
13790075Sobrien
13890075Sobrien/* Number of elements currently allocated for line_info_table.  */
13990075Sobrienstatic unsigned int line_info_table_allocated;
14090075Sobrien
14190075Sobrien/* Number of elements in line_info_table currently in use.  */
14290075Sobrienstatic unsigned int line_info_table_in_use;
14390075Sobrien
14490075Sobrien/* Size (in elements) of increments by which we may expand line_info_table.  */
14590075Sobrien#define LINE_INFO_TABLE_INCREMENT 1024
14690075Sobrien
14790075Sobrien/* Forward declarations for functions defined in this file.  */
148132718Skanstatic char *full_name (const char *);
149132718Skanstatic unsigned int lookup_filename (const char *);
150132718Skanstatic void addr_const_to_string (char *, rtx);
151132718Skanstatic int write_debug_header (DST_HEADER *, const char *, int);
152132718Skanstatic int write_debug_addr (char *, const char *, int);
153132718Skanstatic int write_debug_data1 (unsigned int, const char *, int);
154132718Skanstatic int write_debug_data2 (unsigned int, const char *, int);
155132718Skanstatic int write_debug_data4 (unsigned long, const char *, int);
156132718Skanstatic int write_debug_data8 (unsigned long long, const char *, int);
157132718Skanstatic int write_debug_delta4 (char *, char *, const char *, int);
158132718Skanstatic int write_debug_string (char *, const char *, int);
159132718Skanstatic int write_modbeg (int);
160132718Skanstatic int write_modend (int);
161132718Skanstatic int write_rtnbeg (int, int);
162132718Skanstatic int write_rtnend (int, int);
163132718Skanstatic int write_pclines (int);
164132718Skanstatic int write_srccorr (int, dst_file_info_entry, int);
165132718Skanstatic int write_srccorrs (int);
16690075Sobrien
167132718Skanstatic void vmsdbgout_init (const char *);
168132718Skanstatic void vmsdbgout_finish (const char *);
169132718Skanstatic void vmsdbgout_define (unsigned int, const char *);
170132718Skanstatic void vmsdbgout_undef (unsigned int, const char *);
171132718Skanstatic void vmsdbgout_start_source_file (unsigned int, const char *);
172132718Skanstatic void vmsdbgout_end_source_file (unsigned int);
173132718Skanstatic void vmsdbgout_begin_block (unsigned int, unsigned int);
174132718Skanstatic void vmsdbgout_end_block (unsigned int, unsigned int);
175132718Skanstatic bool vmsdbgout_ignore_block (tree);
176132718Skanstatic void vmsdbgout_source_line (unsigned int, const char *);
177132718Skanstatic void vmsdbgout_begin_prologue (unsigned int, const char *);
178132718Skanstatic void vmsdbgout_end_prologue (unsigned int, const char *);
179132718Skanstatic void vmsdbgout_end_function (unsigned int);
180132718Skanstatic void vmsdbgout_end_epilogue (unsigned int, const char *);
181132718Skanstatic void vmsdbgout_begin_function (tree);
182132718Skanstatic void vmsdbgout_decl (tree);
183132718Skanstatic void vmsdbgout_global_decl (tree);
184132718Skanstatic void vmsdbgout_abstract_function (tree);
18590075Sobrien
18690075Sobrien/* The debug hooks structure.  */
18790075Sobrien
188117395Skanconst struct gcc_debug_hooks vmsdbg_debug_hooks
18990075Sobrien= {vmsdbgout_init,
19090075Sobrien   vmsdbgout_finish,
19190075Sobrien   vmsdbgout_define,
19290075Sobrien   vmsdbgout_undef,
19390075Sobrien   vmsdbgout_start_source_file,
19490075Sobrien   vmsdbgout_end_source_file,
19590075Sobrien   vmsdbgout_begin_block,
19690075Sobrien   vmsdbgout_end_block,
19790075Sobrien   vmsdbgout_ignore_block,
19890075Sobrien   vmsdbgout_source_line,
19990075Sobrien   vmsdbgout_begin_prologue,
200117395Skan   vmsdbgout_end_prologue,
201117395Skan   vmsdbgout_end_epilogue,
202117395Skan   vmsdbgout_begin_function,
203117395Skan   vmsdbgout_end_function,
20490075Sobrien   vmsdbgout_decl,
20590075Sobrien   vmsdbgout_global_decl,
206169689Skan   debug_nothing_tree_int,	  /* type_decl */
207169689Skan   debug_nothing_tree_tree,       /* imported_module_or_decl */
208169689Skan   debug_nothing_tree,		  /* deferred_inline_function */
20990075Sobrien   vmsdbgout_abstract_function,
210169689Skan   debug_nothing_rtx,		  /* label */
211169689Skan   debug_nothing_int,		  /* handle_pch */
212169689Skan   debug_nothing_rtx,		  /* var_location */
213169689Skan   debug_nothing_void,            /* switch_text_section */
214169689Skan   0                              /* start_end_main_source_file */
21590075Sobrien};
21690075Sobrien
21790075Sobrien/* Definitions of defaults for assembler-dependent names of various
21890075Sobrien   pseudo-ops and section names.
21990075Sobrien   Theses may be overridden in the tm.h file (if necessary) for a particular
22090075Sobrien   assembler.  */
22190075Sobrien#ifdef UNALIGNED_SHORT_ASM_OP
22290075Sobrien#undef UNALIGNED_SHORT_ASM_OP
22390075Sobrien#endif
22490075Sobrien#define UNALIGNED_SHORT_ASM_OP	".word"
22590075Sobrien
22690075Sobrien#ifdef UNALIGNED_INT_ASM_OP
22790075Sobrien#undef UNALIGNED_INT_ASM_OP
22890075Sobrien#endif
22990075Sobrien#define UNALIGNED_INT_ASM_OP	".long"
23090075Sobrien
23190075Sobrien#ifdef UNALIGNED_LONG_ASM_OP
23290075Sobrien#undef UNALIGNED_LONG_ASM_OP
23390075Sobrien#endif
23490075Sobrien#define UNALIGNED_LONG_ASM_OP	".long"
23590075Sobrien
23690075Sobrien#ifdef UNALIGNED_DOUBLE_INT_ASM_OP
23790075Sobrien#undef UNALIGNED_DOUBLE_INT_ASM_OP
23890075Sobrien#endif
23990075Sobrien#define UNALIGNED_DOUBLE_INT_ASM_OP	".quad"
24090075Sobrien
24190075Sobrien#ifdef ASM_BYTE_OP
24290075Sobrien#undef ASM_BYTE_OP
24390075Sobrien#endif
24490075Sobrien#define ASM_BYTE_OP	".byte"
24590075Sobrien
24690075Sobrien#define NUMBYTES(I) ((I) < 256 ? 1 : (I) < 65536 ? 2 : 4)
24790075Sobrien
24890075Sobrien#define NUMBYTES0(I) ((I) < 128 ? 0 : (I) < 65536 ? 2 : 4)
24990075Sobrien
25090075Sobrien#ifndef UNALIGNED_PTR_ASM_OP
25190075Sobrien#define UNALIGNED_PTR_ASM_OP \
25290075Sobrien  (PTR_SIZE == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP : UNALIGNED_INT_ASM_OP)
25390075Sobrien#endif
25490075Sobrien
25590075Sobrien#ifndef UNALIGNED_OFFSET_ASM_OP
25690075Sobrien#define UNALIGNED_OFFSET_ASM_OP(OFFSET) \
25790075Sobrien  (NUMBYTES(OFFSET) == 4 \
25890075Sobrien   ? UNALIGNED_LONG_ASM_OP \
25990075Sobrien   : (NUMBYTES(OFFSET) == 2 ? UNALIGNED_SHORT_ASM_OP : ASM_BYTE_OP))
26090075Sobrien#endif
26190075Sobrien
26290075Sobrien/* Definitions of defaults for formats and names of various special
26390075Sobrien   (artificial) labels which may be generated within this file (when the -g
26490075Sobrien   options is used and VMS_DEBUGGING_INFO is in effect.  If necessary, these
26590075Sobrien   may be overridden from within the tm.h file, but typically, overriding these
26690075Sobrien   defaults is unnecessary.  */
26790075Sobrien
26890075Sobrienstatic char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
26990075Sobrien
27090075Sobrien#ifndef TEXT_END_LABEL
27190075Sobrien#define TEXT_END_LABEL		"Lvetext"
27290075Sobrien#endif
27390075Sobrien#ifndef FUNC_BEGIN_LABEL
27490075Sobrien#define FUNC_BEGIN_LABEL	"LVFB"
27590075Sobrien#endif
27690075Sobrien#ifndef FUNC_PROLOG_LABEL
27790075Sobrien#define FUNC_PROLOG_LABEL	"LVFP"
27890075Sobrien#endif
27990075Sobrien#ifndef FUNC_END_LABEL
28090075Sobrien#define FUNC_END_LABEL		"LVFE"
28190075Sobrien#endif
28290075Sobrien#ifndef BLOCK_BEGIN_LABEL
28390075Sobrien#define BLOCK_BEGIN_LABEL	"LVBB"
28490075Sobrien#endif
28590075Sobrien#ifndef BLOCK_END_LABEL
28690075Sobrien#define BLOCK_END_LABEL		"LVBE"
28790075Sobrien#endif
28890075Sobrien#ifndef LINE_CODE_LABEL
28990075Sobrien#define LINE_CODE_LABEL		"LVM"
29090075Sobrien#endif
29190075Sobrien
29290075Sobrien#ifndef ASM_OUTPUT_DEBUG_DELTA2
29390075Sobrien#define ASM_OUTPUT_DEBUG_DELTA2(FILE,LABEL1,LABEL2)			 \
29490075Sobrien  do									 \
29590075Sobrien    {									 \
29690075Sobrien      fprintf ((FILE), "\t%s\t", UNALIGNED_SHORT_ASM_OP);		 \
29790075Sobrien      assemble_name (FILE, LABEL1);					 \
29890075Sobrien      fprintf (FILE, "-");						 \
29990075Sobrien      assemble_name (FILE, LABEL2);					 \
30090075Sobrien    }									 \
30190075Sobrien  while (0)
30290075Sobrien#endif
30390075Sobrien
30490075Sobrien#ifndef ASM_OUTPUT_DEBUG_DELTA4
30590075Sobrien#define ASM_OUTPUT_DEBUG_DELTA4(FILE,LABEL1,LABEL2)			 \
30690075Sobrien  do									 \
30790075Sobrien    {									 \
30890075Sobrien      fprintf ((FILE), "\t%s\t", UNALIGNED_INT_ASM_OP);			 \
30990075Sobrien      assemble_name (FILE, LABEL1);					 \
31090075Sobrien      fprintf (FILE, "-");						 \
31190075Sobrien      assemble_name (FILE, LABEL2);					 \
31290075Sobrien    }									 \
31390075Sobrien  while (0)
31490075Sobrien#endif
31590075Sobrien
31690075Sobrien#ifndef ASM_OUTPUT_DEBUG_ADDR_DELTA
31790075Sobrien#define ASM_OUTPUT_DEBUG_ADDR_DELTA(FILE,LABEL1,LABEL2)			 \
31890075Sobrien  do									 \
31990075Sobrien    {									 \
32090075Sobrien      fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP);			 \
32190075Sobrien      assemble_name (FILE, LABEL1);					 \
32290075Sobrien      fprintf (FILE, "-");						 \
32390075Sobrien      assemble_name (FILE, LABEL2);					 \
32490075Sobrien    }									 \
32590075Sobrien  while (0)
32690075Sobrien#endif
32790075Sobrien
32890075Sobrien#ifndef ASM_OUTPUT_DEBUG_ADDR
32990075Sobrien#define ASM_OUTPUT_DEBUG_ADDR(FILE,LABEL)				 \
33090075Sobrien  do									 \
33190075Sobrien    {									 \
33290075Sobrien      fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP);			 \
33390075Sobrien      assemble_name (FILE, LABEL);					 \
33490075Sobrien    }									 \
33590075Sobrien  while (0)
33690075Sobrien#endif
33790075Sobrien
33890075Sobrien#ifndef ASM_OUTPUT_DEBUG_ADDR_CONST
33990075Sobrien#define ASM_OUTPUT_DEBUG_ADDR_CONST(FILE,ADDR)				\
34090075Sobrien  fprintf ((FILE), "\t%s\t%s", UNALIGNED_PTR_ASM_OP, (ADDR))
34190075Sobrien#endif
34290075Sobrien
34390075Sobrien#ifndef ASM_OUTPUT_DEBUG_DATA1
34490075Sobrien#define ASM_OUTPUT_DEBUG_DATA1(FILE,VALUE) \
34590075Sobrien  fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, (unsigned char) VALUE)
34690075Sobrien#endif
34790075Sobrien
34890075Sobrien#ifndef ASM_OUTPUT_DEBUG_DATA2
34990075Sobrien#define ASM_OUTPUT_DEBUG_DATA2(FILE,VALUE) \
35090075Sobrien  fprintf ((FILE), "\t%s\t0x%x", UNALIGNED_SHORT_ASM_OP, \
35190075Sobrien	   (unsigned short) VALUE)
35290075Sobrien#endif
35390075Sobrien
35490075Sobrien#ifndef ASM_OUTPUT_DEBUG_DATA4
35590075Sobrien#define ASM_OUTPUT_DEBUG_DATA4(FILE,VALUE) \
35690075Sobrien  fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_INT_ASM_OP, (unsigned long) VALUE)
35790075Sobrien#endif
35890075Sobrien
35990075Sobrien#ifndef ASM_OUTPUT_DEBUG_DATA
36090075Sobrien#define ASM_OUTPUT_DEBUG_DATA(FILE,VALUE) \
36190075Sobrien  fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_OFFSET_ASM_OP(VALUE), VALUE)
36290075Sobrien#endif
36390075Sobrien
36490075Sobrien#ifndef ASM_OUTPUT_DEBUG_ADDR_DATA
36590075Sobrien#define ASM_OUTPUT_DEBUG_ADDR_DATA(FILE,VALUE) \
36690075Sobrien  fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_PTR_ASM_OP, \
36790075Sobrien	   (unsigned long) VALUE)
36890075Sobrien#endif
36990075Sobrien
37090075Sobrien#ifndef ASM_OUTPUT_DEBUG_DATA8
37190075Sobrien#define ASM_OUTPUT_DEBUG_DATA8(FILE,VALUE) \
37290075Sobrien  fprintf ((FILE), "\t%s\t0x%llx", UNALIGNED_DOUBLE_INT_ASM_OP, \
37390075Sobrien                                 (unsigned long long) VALUE)
37490075Sobrien#endif
37590075Sobrien
37690075Sobrien/* This is similar to the default ASM_OUTPUT_ASCII, except that no trailing
377132718Skan   newline is produced.  When flag_verbose_asm is asserted, we add commentary
37890075Sobrien   at the end of the line, so we must avoid output of a newline here.  */
37990075Sobrien#ifndef ASM_OUTPUT_DEBUG_STRING
38090075Sobrien#define ASM_OUTPUT_DEBUG_STRING(FILE,P)		\
38190075Sobrien  do						\
38290075Sobrien    {						\
38390075Sobrien      register int slen = strlen(P);		\
38490075Sobrien      register char *p = (P);			\
38590075Sobrien      register int i;				\
38690075Sobrien      fprintf (FILE, "\t.ascii \"");		\
38790075Sobrien      for (i = 0; i < slen; i++)		\
38890075Sobrien	{					\
38990075Sobrien	  register int c = p[i];		\
39090075Sobrien	  if (c == '\"' || c == '\\')		\
39190075Sobrien	    putc ('\\', FILE);			\
39290075Sobrien	  if (c >= ' ' && c < 0177)		\
39390075Sobrien	    putc (c, FILE);			\
39490075Sobrien	  else					\
39590075Sobrien	    fprintf (FILE, "\\%o", c);		\
39690075Sobrien	}					\
39790075Sobrien      fprintf (FILE, "\"");			\
39890075Sobrien    }						\
39990075Sobrien  while (0)
40090075Sobrien#endif
40190075Sobrien
40290075Sobrien/* Convert a reference to the assembler name of a C-level name.  This
40390075Sobrien   macro has the same effect as ASM_OUTPUT_LABELREF, but copies to
40490075Sobrien   a string rather than writing to a file.  */
40590075Sobrien#ifndef ASM_NAME_TO_STRING
406132718Skan#define ASM_NAME_TO_STRING(STR, NAME)		\
40790075Sobrien  do						\
40890075Sobrien    {						\
40990075Sobrien      if ((NAME)[0] == '*')			\
41090075Sobrien	strcpy (STR, NAME+1);			\
41190075Sobrien      else					\
41290075Sobrien	strcpy (STR, NAME);			\
41390075Sobrien    }						\
41490075Sobrien  while (0)
41590075Sobrien#endif
41690075Sobrien
41790075Sobrien
41890075Sobrien/* General utility functions.  */
41990075Sobrien
42090075Sobrien/* Convert an integer constant expression into assembler syntax.  Addition and
42190075Sobrien   subtraction are the only arithmetic that may appear in these expressions.
42290075Sobrien   This is an adaptation of output_addr_const in final.c.  Here, the target
42390075Sobrien   of the conversion is a string buffer.  We can't use output_addr_const
42490075Sobrien   directly, because it writes to a file.  */
42590075Sobrien
42690075Sobrienstatic void
427132718Skanaddr_const_to_string (char *str, rtx x)
42890075Sobrien{
42990075Sobrien  char buf1[256];
43090075Sobrien  char buf2[256];
43190075Sobrien
432169689Skan restart:
43390075Sobrien  str[0] = '\0';
43490075Sobrien  switch (GET_CODE (x))
43590075Sobrien    {
43690075Sobrien    case PC:
437169689Skan      gcc_assert (flag_pic);
438169689Skan      strcat (str, ",");
43990075Sobrien      break;
44090075Sobrien
44190075Sobrien    case SYMBOL_REF:
44290075Sobrien      ASM_NAME_TO_STRING (buf1, XSTR (x, 0));
44390075Sobrien      strcat (str, buf1);
44490075Sobrien      break;
44590075Sobrien
44690075Sobrien    case LABEL_REF:
44790075Sobrien      ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
44890075Sobrien      ASM_NAME_TO_STRING (buf2, buf1);
44990075Sobrien      strcat (str, buf2);
45090075Sobrien      break;
45190075Sobrien
45290075Sobrien    case CODE_LABEL:
45390075Sobrien      ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (x));
45490075Sobrien      ASM_NAME_TO_STRING (buf2, buf1);
45590075Sobrien      strcat (str, buf2);
45690075Sobrien      break;
45790075Sobrien
45890075Sobrien    case CONST_INT:
45990075Sobrien      sprintf (buf1, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
46090075Sobrien      strcat (str, buf1);
46190075Sobrien      break;
46290075Sobrien
46390075Sobrien    case CONST:
464117395Skan      /* This used to output parentheses around the expression, but that does
46590075Sobrien         not work on the 386 (either ATT or BSD assembler).  */
46690075Sobrien      addr_const_to_string (buf1, XEXP (x, 0));
46790075Sobrien      strcat (str, buf1);
46890075Sobrien      break;
46990075Sobrien
47090075Sobrien    case CONST_DOUBLE:
47190075Sobrien      if (GET_MODE (x) == VOIDmode)
47290075Sobrien	{
47390075Sobrien	  /* We can use %d if the number is one word and positive.  */
47490075Sobrien	  if (CONST_DOUBLE_HIGH (x))
47590075Sobrien	    sprintf (buf1, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
47690075Sobrien		     CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
47790075Sobrien	  else if (CONST_DOUBLE_LOW (x) < 0)
47890075Sobrien	    sprintf (buf1, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (x));
47990075Sobrien	  else
48090075Sobrien	    sprintf (buf1, HOST_WIDE_INT_PRINT_DEC,
48190075Sobrien		     CONST_DOUBLE_LOW (x));
48290075Sobrien	  strcat (str, buf1);
48390075Sobrien	}
48490075Sobrien      else
48590075Sobrien	/* We can't handle floating point constants; PRINT_OPERAND must
48690075Sobrien	   handle them.  */
48790075Sobrien	output_operand_lossage ("floating constant misused");
48890075Sobrien      break;
48990075Sobrien
49090075Sobrien    case PLUS:
49190075Sobrien      /* Some assemblers need integer constants to appear last (eg masm).  */
49290075Sobrien      if (GET_CODE (XEXP (x, 0)) == CONST_INT)
49390075Sobrien	{
49490075Sobrien	  addr_const_to_string (buf1, XEXP (x, 1));
49590075Sobrien	  strcat (str, buf1);
49690075Sobrien	  if (INTVAL (XEXP (x, 0)) >= 0)
49790075Sobrien	    strcat (str, "+");
49890075Sobrien	  addr_const_to_string (buf1, XEXP (x, 0));
49990075Sobrien	  strcat (str, buf1);
50090075Sobrien	}
50190075Sobrien      else
50290075Sobrien	{
50390075Sobrien	  addr_const_to_string (buf1, XEXP (x, 0));
50490075Sobrien	  strcat (str, buf1);
50590075Sobrien	  if (INTVAL (XEXP (x, 1)) >= 0)
50690075Sobrien	    strcat (str, "+");
50790075Sobrien	  addr_const_to_string (buf1, XEXP (x, 1));
50890075Sobrien	  strcat (str, buf1);
50990075Sobrien	}
51090075Sobrien      break;
51190075Sobrien
51290075Sobrien    case MINUS:
51390075Sobrien      /* Avoid outputting things like x-x or x+5-x, since some assemblers
51490075Sobrien         can't handle that.  */
51590075Sobrien      x = simplify_subtraction (x);
51690075Sobrien      if (GET_CODE (x) != MINUS)
51790075Sobrien	goto restart;
51890075Sobrien
51990075Sobrien      addr_const_to_string (buf1, XEXP (x, 0));
52090075Sobrien      strcat (str, buf1);
52190075Sobrien      strcat (str, "-");
52290075Sobrien      if (GET_CODE (XEXP (x, 1)) == CONST_INT
52390075Sobrien	  && INTVAL (XEXP (x, 1)) < 0)
52490075Sobrien	{
52590075Sobrien	  strcat (str, "(");
52690075Sobrien	  addr_const_to_string (buf1, XEXP (x, 1));
52790075Sobrien	  strcat (str, buf1);
52890075Sobrien	  strcat (str, ")");
52990075Sobrien	}
53090075Sobrien      else
53190075Sobrien	{
53290075Sobrien	  addr_const_to_string (buf1, XEXP (x, 1));
53390075Sobrien	  strcat (str, buf1);
53490075Sobrien	}
53590075Sobrien      break;
53690075Sobrien
53790075Sobrien    case ZERO_EXTEND:
53890075Sobrien    case SIGN_EXTEND:
53990075Sobrien      addr_const_to_string (buf1, XEXP (x, 0));
54090075Sobrien      strcat (str, buf1);
54190075Sobrien      break;
54290075Sobrien
54390075Sobrien    default:
54490075Sobrien      output_operand_lossage ("invalid expression as operand");
54590075Sobrien    }
54690075Sobrien}
54790075Sobrien
54890075Sobrien/* Output the debug header HEADER.  Also output COMMENT if flag_verbose_asm is
54990075Sobrien   set.  Return the header size.  Just return the size if DOSIZEONLY is
550117395Skan   nonzero.  */
55190075Sobrien
55290075Sobrienstatic int
553132718Skanwrite_debug_header (DST_HEADER *header, const char *comment, int dosizeonly)
55490075Sobrien{
55590075Sobrien  if (!dosizeonly)
55690075Sobrien    {
55790075Sobrien      ASM_OUTPUT_DEBUG_DATA2 (asm_out_file,
55890075Sobrien			      header->dst__header_length.dst_w_length);
55990075Sobrien
56090075Sobrien      if (flag_verbose_asm)
56190075Sobrien	fprintf (asm_out_file, "\t%s record length", ASM_COMMENT_START);
56290075Sobrien      fputc ('\n', asm_out_file);
56390075Sobrien
56490075Sobrien      ASM_OUTPUT_DEBUG_DATA2 (asm_out_file,
56590075Sobrien			      header->dst__header_type.dst_w_type);
56690075Sobrien
56790075Sobrien      if (flag_verbose_asm)
56890075Sobrien	fprintf (asm_out_file, "\t%s record type (%s)", ASM_COMMENT_START,
56990075Sobrien		 comment);
57090075Sobrien
57190075Sobrien      fputc ('\n', asm_out_file);
57290075Sobrien    }
57390075Sobrien
57490075Sobrien  return 4;
57590075Sobrien}
57690075Sobrien
57790075Sobrien/* Output the address of SYMBOL.  Also output COMMENT if flag_verbose_asm is
57890075Sobrien   set.  Return the address size.  Just return the size if DOSIZEONLY is
579117395Skan   nonzero.  */
58090075Sobrien
58190075Sobrienstatic int
582132718Skanwrite_debug_addr (char *symbol, const char *comment, int dosizeonly)
58390075Sobrien{
58490075Sobrien  if (!dosizeonly)
58590075Sobrien    {
58690075Sobrien      ASM_OUTPUT_DEBUG_ADDR (asm_out_file, symbol);
58790075Sobrien      if (flag_verbose_asm)
58890075Sobrien	fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
58990075Sobrien      fputc ('\n', asm_out_file);
59090075Sobrien    }
59190075Sobrien
59290075Sobrien  return PTR_SIZE;
59390075Sobrien}
59490075Sobrien
59590075Sobrien/* Output the single byte DATA1.  Also output COMMENT if flag_verbose_asm is
59690075Sobrien   set.  Return the data size.  Just return the size if DOSIZEONLY is
597117395Skan   nonzero.  */
59890075Sobrien
59990075Sobrienstatic int
600132718Skanwrite_debug_data1 (unsigned int data1, const char *comment, int dosizeonly)
60190075Sobrien{
60290075Sobrien  if (!dosizeonly)
60390075Sobrien    {
60490075Sobrien      ASM_OUTPUT_DEBUG_DATA1 (asm_out_file, data1);
60590075Sobrien      if (flag_verbose_asm)
60690075Sobrien	fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
60790075Sobrien      fputc ('\n', asm_out_file);
60890075Sobrien    }
60990075Sobrien
61090075Sobrien  return 1;
61190075Sobrien}
61290075Sobrien
61390075Sobrien/* Output the single word DATA2.  Also output COMMENT if flag_verbose_asm is
61490075Sobrien   set.  Return the data size.  Just return the size if DOSIZEONLY is
615117395Skan   nonzero.  */
61690075Sobrien
61790075Sobrienstatic int
618132718Skanwrite_debug_data2 (unsigned int data2, const char *comment, int dosizeonly)
61990075Sobrien{
62090075Sobrien  if (!dosizeonly)
62190075Sobrien    {
62290075Sobrien      ASM_OUTPUT_DEBUG_DATA2 (asm_out_file, data2);
62390075Sobrien      if (flag_verbose_asm)
62490075Sobrien	fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
62590075Sobrien      fputc ('\n', asm_out_file);
62690075Sobrien    }
62790075Sobrien
62890075Sobrien  return 2;
62990075Sobrien}
63090075Sobrien
63190075Sobrien/* Output double word DATA4.  Also output COMMENT if flag_verbose_asm is set.
632117395Skan   Return the data size.  Just return the size if DOSIZEONLY is nonzero.  */
63390075Sobrien
63490075Sobrienstatic int
635132718Skanwrite_debug_data4 (unsigned long data4, const char *comment, int dosizeonly)
63690075Sobrien{
63790075Sobrien  if (!dosizeonly)
63890075Sobrien    {
63990075Sobrien      ASM_OUTPUT_DEBUG_DATA4 (asm_out_file, data4);
64090075Sobrien      if (flag_verbose_asm)
64190075Sobrien	fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
64290075Sobrien      fputc ('\n', asm_out_file);
64390075Sobrien    }
644117395Skan
64590075Sobrien  return 4;
64690075Sobrien}
64790075Sobrien
64890075Sobrien/* Output quad word DATA8.  Also output COMMENT if flag_verbose_asm is set.
649117395Skan   Return the data size.  Just return the size if DOSIZEONLY is nonzero.  */
65090075Sobrien
65190075Sobrienstatic int
652132718Skanwrite_debug_data8 (unsigned long long data8, const char *comment,
653132718Skan		   int dosizeonly)
65490075Sobrien{
65590075Sobrien  if (!dosizeonly)
65690075Sobrien    {
65790075Sobrien      ASM_OUTPUT_DEBUG_DATA8 (asm_out_file, data8);
65890075Sobrien      if (flag_verbose_asm)
65990075Sobrien	fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
66090075Sobrien      fputc ('\n', asm_out_file);
66190075Sobrien    }
66290075Sobrien
66390075Sobrien  return 8;
66490075Sobrien}
66590075Sobrien
66690075Sobrien/* Output the difference between LABEL1 and LABEL2.  Also output COMMENT if
66790075Sobrien   flag_verbose_asm is set.  Return the data size.  Just return the size if
668117395Skan   DOSIZEONLY is nonzero.  */
66990075Sobrien
67090075Sobrienstatic int
671132718Skanwrite_debug_delta4 (char *label1, char *label2, const char *comment,
672132718Skan		    int dosizeonly)
67390075Sobrien{
67490075Sobrien  if (!dosizeonly)
67590075Sobrien    {
67690075Sobrien      ASM_OUTPUT_DEBUG_DELTA4 (asm_out_file, label1, label2);
67790075Sobrien      if (flag_verbose_asm)
67890075Sobrien	fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
67990075Sobrien      fputc ('\n', asm_out_file);
68090075Sobrien    }
68190075Sobrien
68290075Sobrien  return 4;
68390075Sobrien}
68490075Sobrien
68590075Sobrien/* Output a character string STRING.  Also write COMMENT if flag_verbose_asm is
68690075Sobrien   set.  Return the string length.  Just return the length if DOSIZEONLY is
687117395Skan   nonzero.  */
68890075Sobrien
68990075Sobrienstatic int
690132718Skanwrite_debug_string (char *string, const char *comment, int dosizeonly)
69190075Sobrien{
69290075Sobrien  if (!dosizeonly)
69390075Sobrien    {
69490075Sobrien      ASM_OUTPUT_DEBUG_STRING (asm_out_file, string);
69590075Sobrien      if (flag_verbose_asm)
69690075Sobrien	fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
69790075Sobrien      fputc ('\n', asm_out_file);
69890075Sobrien    }
699117395Skan
70090075Sobrien  return strlen (string);
70190075Sobrien}
70290075Sobrien
70390075Sobrien/* Output a module begin header and return the header size.  Just return the
704117395Skan   size if DOSIZEONLY is nonzero.  */
70590075Sobrien
70690075Sobrienstatic int
707132718Skanwrite_modbeg (int dosizeonly)
70890075Sobrien{
70990075Sobrien  DST_MODULE_BEGIN modbeg;
71090075Sobrien  DST_MB_TRLR mb_trlr;
71190075Sobrien  int i;
71290075Sobrien  char *module_name, *m;
71390075Sobrien  int modnamelen;
71490075Sobrien  int prodnamelen;
71590075Sobrien  int totsize = 0;
71690075Sobrien
71790075Sobrien  /* Assumes primary filename has Unix syntax file spec.  */
71890075Sobrien  module_name = xstrdup (basename ((char *) primary_filename));
71990075Sobrien
72090075Sobrien  m = strrchr (module_name, '.');
72190075Sobrien  if (m)
72290075Sobrien    *m = 0;
72390075Sobrien
72490075Sobrien  modnamelen = strlen (module_name);
72590075Sobrien  for (i = 0; i < modnamelen; i++)
72690075Sobrien    module_name[i] = TOUPPER (module_name[i]);
72790075Sobrien
72890075Sobrien  prodnamelen = strlen (module_producer);
72990075Sobrien
73090075Sobrien  modbeg.dst_a_modbeg_header.dst__header_length.dst_w_length
73190075Sobrien    = DST_K_MODBEG_SIZE + modnamelen + DST_K_MB_TRLR_SIZE + prodnamelen - 1;
73290075Sobrien  modbeg.dst_a_modbeg_header.dst__header_type.dst_w_type = DST_K_MODBEG;
73390075Sobrien  modbeg.dst_b_modbeg_flags.dst_v_modbeg_hide = 0;
73490075Sobrien  modbeg.dst_b_modbeg_flags.dst_v_modbeg_version = 1;
73590075Sobrien  modbeg.dst_b_modbeg_flags.dst_v_modbeg_unused = 0;
73690075Sobrien  modbeg.dst_b_modbeg_unused = 0;
73790075Sobrien  modbeg.dst_l_modbeg_language = module_language;
73890075Sobrien  modbeg.dst_w_version_major = DST_K_VERSION_MAJOR;
73990075Sobrien  modbeg.dst_w_version_minor = DST_K_VERSION_MINOR;
74090075Sobrien  modbeg.dst_b_modbeg_name = strlen (module_name);
74190075Sobrien
74290075Sobrien  mb_trlr.dst_b_compiler = strlen (module_producer);
74390075Sobrien
74490075Sobrien  totsize += write_debug_header (&modbeg.dst_a_modbeg_header,
74590075Sobrien				 "modbeg", dosizeonly);
74690075Sobrien  totsize += write_debug_data1 (*((char *) &modbeg.dst_b_modbeg_flags),
74790075Sobrien				"flags", dosizeonly);
74890075Sobrien  totsize += write_debug_data1 (modbeg.dst_b_modbeg_unused,
74990075Sobrien				"unused", dosizeonly);
75090075Sobrien  totsize += write_debug_data4 (modbeg.dst_l_modbeg_language,
75190075Sobrien				"language", dosizeonly);
75290075Sobrien  totsize += write_debug_data2 (modbeg.dst_w_version_major,
75390075Sobrien				"DST major version", dosizeonly);
75490075Sobrien  totsize += write_debug_data2 (modbeg.dst_w_version_minor,
75590075Sobrien				"DST minor version", dosizeonly);
75690075Sobrien  totsize += write_debug_data1 (modbeg.dst_b_modbeg_name,
75790075Sobrien				"length of module name", dosizeonly);
75890075Sobrien  totsize += write_debug_string (module_name, "module name", dosizeonly);
75990075Sobrien  totsize += write_debug_data1 (mb_trlr.dst_b_compiler,
76090075Sobrien				"length of compiler name", dosizeonly);
76190075Sobrien  totsize += write_debug_string (module_producer, "compiler name", dosizeonly);
76290075Sobrien
76390075Sobrien  return totsize;
76490075Sobrien}
76590075Sobrien
76690075Sobrien/* Output a module end trailer and return the trailer size.   Just return
767117395Skan   the size if DOSIZEONLY is nonzero.  */
76890075Sobrien
76990075Sobrienstatic int
770132718Skanwrite_modend (int dosizeonly)
77190075Sobrien{
77290075Sobrien  DST_MODULE_END modend;
77390075Sobrien  int totsize = 0;
77490075Sobrien
77590075Sobrien  modend.dst_a_modend_header.dst__header_length.dst_w_length
77690075Sobrien   = DST_K_MODEND_SIZE - 1;
77790075Sobrien  modend.dst_a_modend_header.dst__header_type.dst_w_type = DST_K_MODEND;
77890075Sobrien
77990075Sobrien  totsize += write_debug_header (&modend.dst_a_modend_header, "modend",
78090075Sobrien				 dosizeonly);
78190075Sobrien
78290075Sobrien  return totsize;
78390075Sobrien}
78490075Sobrien
78590075Sobrien/* Output a routine begin header routine RTNNUM and return the header size.
786117395Skan   Just return the size if DOSIZEONLY is nonzero.  */
78790075Sobrien
78890075Sobrienstatic int
789132718Skanwrite_rtnbeg (int rtnnum, int dosizeonly)
79090075Sobrien{
79190075Sobrien  char *rtnname;
792117395Skan  int rtnnamelen;
79390075Sobrien  char *rtnentryname;
79490075Sobrien  int totsize = 0;
79590075Sobrien  char label[MAX_ARTIFICIAL_LABEL_BYTES];
79690075Sobrien  DST_ROUTINE_BEGIN rtnbeg;
79790075Sobrien  DST_PROLOG prolog;
798169689Skan  vms_func_ref fde = &func_table[rtnnum];
79990075Sobrien
800169689Skan  rtnname = (char *)fde->vms_func_name;
80190075Sobrien  rtnnamelen = strlen (rtnname);
802117395Skan  rtnentryname = concat (rtnname, "..en", NULL);
80390075Sobrien
80490075Sobrien  if (!strcmp (rtnname, "main"))
80590075Sobrien    {
80690075Sobrien      DST_HEADER header;
80790075Sobrien      const char *go = "TRANSFER$BREAK$GO";
80890075Sobrien
80990075Sobrien      /* This command isn't documented in DSTRECORDS, so it's made to
81090075Sobrien	 look like what DEC C does */
81190075Sobrien
81290075Sobrien      /* header size - 1st byte + flag byte + STO_LW size
81390075Sobrien	 + string count byte + string length */
81490075Sobrien      header.dst__header_length.dst_w_length
815117395Skan	= DST_K_DST_HEADER_SIZE - 1 + 1 + 4 + 1 + strlen (go);
81690075Sobrien      header.dst__header_type.dst_w_type = 0x17;
81790075Sobrien
81890075Sobrien      totsize += write_debug_header (&header, "transfer", dosizeonly);
81990075Sobrien
82090075Sobrien      /* I think this is a flag byte, but I don't know what this flag means */
82190075Sobrien      totsize += write_debug_data1 (0x1, "flags ???", dosizeonly);
82290075Sobrien
82390075Sobrien      /* Routine Begin PD Address */
82490075Sobrien      totsize += write_debug_addr (rtnname, "main procedure descriptor",
82590075Sobrien				   dosizeonly);
82690075Sobrien      totsize += write_debug_data1 (strlen (go), "length of main_name",
82790075Sobrien				    dosizeonly);
82890075Sobrien      totsize += write_debug_string ((char *) go, "main name", dosizeonly);
82990075Sobrien    }
83090075Sobrien
831132718Skan  /* The header length never includes the length byte.  */
83290075Sobrien  rtnbeg.dst_a_rtnbeg_header.dst__header_length.dst_w_length
83390075Sobrien   = DST_K_RTNBEG_SIZE + rtnnamelen - 1;
83490075Sobrien  rtnbeg.dst_a_rtnbeg_header.dst__header_type.dst_w_type = DST_K_RTNBEG;
83590075Sobrien  rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_unused = 0;
83690075Sobrien  rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_unalloc = 0;
83790075Sobrien  rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_prototype = 0;
83890075Sobrien  rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_inlined = 0;
83990075Sobrien  rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_no_call = 1;
84090075Sobrien  rtnbeg.dst_b_rtnbeg_name = rtnnamelen;
84190075Sobrien
84290075Sobrien  totsize += write_debug_header (&rtnbeg.dst_a_rtnbeg_header, "rtnbeg",
84390075Sobrien				 dosizeonly);
84490075Sobrien  totsize += write_debug_data1 (*((char *) &rtnbeg.dst_b_rtnbeg_flags),
84590075Sobrien				"flags", dosizeonly);
84690075Sobrien
84790075Sobrien  /* Routine Begin Address */
84890075Sobrien  totsize += write_debug_addr (rtnentryname, "routine entry name", dosizeonly);
84990075Sobrien
85090075Sobrien  /* Routine Begin PD Address */
85190075Sobrien  totsize += write_debug_addr (rtnname, "routine procedure descriptor",
85290075Sobrien			       dosizeonly);
85390075Sobrien
85490075Sobrien  /* Routine Begin Name */
85590075Sobrien  totsize += write_debug_data1 (rtnbeg.dst_b_rtnbeg_name,
85690075Sobrien				"length of routine name", dosizeonly);
85790075Sobrien
85890075Sobrien  totsize += write_debug_string (rtnname, "routine name", dosizeonly);
85990075Sobrien
86090075Sobrien  free (rtnentryname);
86190075Sobrien
86290075Sobrien  if (debug_info_level > DINFO_LEVEL_TERSE)
86390075Sobrien    {
86490075Sobrien      prolog.dst_a_prolog_header.dst__header_length.dst_w_length
86590075Sobrien	= DST_K_PROLOG_SIZE - 1;
86690075Sobrien      prolog.dst_a_prolog_header.dst__header_type.dst_w_type = DST_K_PROLOG;
86790075Sobrien
86890075Sobrien      totsize += write_debug_header (&prolog.dst_a_prolog_header, "prolog",
86990075Sobrien				     dosizeonly);
87090075Sobrien
871169689Skan      ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL, fde->funcdef_number);
87290075Sobrien      totsize += write_debug_addr (label, "prolog breakpoint addr",
87390075Sobrien				   dosizeonly);
87490075Sobrien    }
87590075Sobrien
87690075Sobrien  return totsize;
87790075Sobrien}
87890075Sobrien
87990075Sobrien/* Output a routine end trailer for routine RTNNUM and return the header size.
880117395Skan   Just return the size if DOSIZEONLY is nonzero.  */
88190075Sobrien
88290075Sobrienstatic int
883132718Skanwrite_rtnend (int rtnnum, int dosizeonly)
88490075Sobrien{
88590075Sobrien  DST_ROUTINE_END rtnend;
88690075Sobrien  char label1[MAX_ARTIFICIAL_LABEL_BYTES];
88790075Sobrien  char label2[MAX_ARTIFICIAL_LABEL_BYTES];
88890075Sobrien  int totsize;
889169689Skan  vms_func_ref fde = &func_table[rtnnum];
890169689Skan  int corrected_rtnnum = fde->funcdef_number;
89190075Sobrien
89290075Sobrien  totsize = 0;
89390075Sobrien
89490075Sobrien  rtnend.dst_a_rtnend_header.dst__header_length.dst_w_length
89590075Sobrien   = DST_K_RTNEND_SIZE - 1;
89690075Sobrien  rtnend.dst_a_rtnend_header.dst__header_type.dst_w_type = DST_K_RTNEND;
89790075Sobrien  rtnend.dst_b_rtnend_unused = 0;
89890075Sobrien  rtnend.dst_l_rtnend_size = 0; /* Calculated below.  */
89990075Sobrien
90090075Sobrien  totsize += write_debug_header (&rtnend.dst_a_rtnend_header, "rtnend",
90190075Sobrien				 dosizeonly);
90290075Sobrien  totsize += write_debug_data1 (rtnend.dst_b_rtnend_unused, "unused",
90390075Sobrien				dosizeonly);
90490075Sobrien
905169689Skan  ASM_GENERATE_INTERNAL_LABEL (label1, FUNC_BEGIN_LABEL, corrected_rtnnum);
906169689Skan  ASM_GENERATE_INTERNAL_LABEL (label2, FUNC_END_LABEL, corrected_rtnnum);
90790075Sobrien  totsize += write_debug_delta4 (label2, label1, "routine size", dosizeonly);
90890075Sobrien
90990075Sobrien  return totsize;
91090075Sobrien}
91190075Sobrien
91290075Sobrien#define K_DELTA_PC(I) \
91390075Sobrien ((I) < 128 ? -(I) : (I) < 65536 ? DST_K_DELTA_PC_W : DST_K_DELTA_PC_L)
91490075Sobrien
91590075Sobrien#define K_SET_LINUM(I) \
91690075Sobrien ((I) < 256 ? DST_K_SET_LINUM_B \
91790075Sobrien  : (I) < 65536 ? DST_K_SET_LINUM : DST_K_SET_LINUM_L)
91890075Sobrien
91990075Sobrien#define K_INCR_LINUM(I) \
92090075Sobrien ((I) < 256 ? DST_K_INCR_LINUM \
92190075Sobrien  : (I) < 65536 ? DST_K_INCR_LINUM_W : DST_K_INCR_LINUM_L)
92290075Sobrien
92390075Sobrien/* Output the PC to line number correlations and return the size.  Just return
924117395Skan   the size if DOSIZEONLY is nonzero */
92590075Sobrien
92690075Sobrienstatic int
927132718Skanwrite_pclines (int dosizeonly)
92890075Sobrien{
92990075Sobrien  unsigned i;
93090075Sobrien  int fn;
93190075Sobrien  int ln, lastln;
93290075Sobrien  int linestart = 0;
93390075Sobrien  int max_line;
93490075Sobrien  DST_LINE_NUM_HEADER line_num;
93590075Sobrien  DST_PCLINE_COMMANDS pcline;
93690075Sobrien  char label[MAX_ARTIFICIAL_LABEL_BYTES];
93790075Sobrien  char lastlabel[MAX_ARTIFICIAL_LABEL_BYTES];
93890075Sobrien  int totsize = 0;
93990075Sobrien  char buff[256];
94090075Sobrien
94190075Sobrien  max_line = file_info_table[1].max_line;
94290075Sobrien  file_info_table[1].listing_line_start = linestart;
94390075Sobrien  linestart = linestart + ((max_line / 100000) + 1) * 100000;
94490075Sobrien
94590075Sobrien  for (i = 2; i < file_info_table_in_use; i++)
94690075Sobrien    {
94790075Sobrien      max_line = file_info_table[i].max_line;
94890075Sobrien      file_info_table[i].listing_line_start = linestart;
94990075Sobrien      linestart = linestart + ((max_line / 10000) + 1) * 10000;
95090075Sobrien    }
95190075Sobrien
952132718Skan  /* Set starting address to beginning of text section.  */
95390075Sobrien  line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 8;
95490075Sobrien  line_num.dst_a_line_num_header.dst__header_type.dst_w_type = DST_K_LINE_NUM;
95590075Sobrien  pcline.dst_b_pcline_command = DST_K_SET_ABS_PC;
95690075Sobrien
95790075Sobrien  totsize += write_debug_header (&line_num.dst_a_line_num_header,
95890075Sobrien				 "line_num", dosizeonly);
95990075Sobrien  totsize += write_debug_data1 (pcline.dst_b_pcline_command,
96090075Sobrien				"line_num (SET ABS PC)", dosizeonly);
96190075Sobrien
96290075Sobrien  if (dosizeonly)
96390075Sobrien    totsize += 4;
96490075Sobrien  else
96590075Sobrien    {
96690075Sobrien      ASM_OUTPUT_DEBUG_ADDR (asm_out_file, TEXT_SECTION_ASM_OP);
96790075Sobrien      if (flag_verbose_asm)
96890075Sobrien	fprintf (asm_out_file, "\t%s line_num", ASM_COMMENT_START);
96990075Sobrien      fputc ('\n', asm_out_file);
97090075Sobrien    }
97190075Sobrien
97290075Sobrien  fn = line_info_table[1].dst_file_num;
97390075Sobrien  ln = (file_info_table[fn].listing_line_start
97490075Sobrien	+ line_info_table[1].dst_line_num);
97590075Sobrien  line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 4 + 4;
97690075Sobrien  pcline.dst_b_pcline_command = DST_K_SET_LINUM_L;
97790075Sobrien
97890075Sobrien  totsize += write_debug_header (&line_num.dst_a_line_num_header,
97990075Sobrien				 "line_num", dosizeonly);
98090075Sobrien  totsize += write_debug_data1 (pcline.dst_b_pcline_command,
98190075Sobrien				"line_num (SET LINUM LONG)", dosizeonly);
98290075Sobrien
983117395Skan  sprintf (buff, "line_num (%d)", ln ? ln - 1 : 0);
984117395Skan  totsize += write_debug_data4 (ln ? ln - 1 : 0, buff, dosizeonly);
98590075Sobrien
98690075Sobrien  lastln = ln;
98790075Sobrien  strcpy (lastlabel, TEXT_SECTION_ASM_OP);
98890075Sobrien  for (i = 1; i < line_info_table_in_use; i++)
98990075Sobrien    {
99090075Sobrien      int extrabytes;
99190075Sobrien
99290075Sobrien      fn = line_info_table[i].dst_file_num;
99390075Sobrien      ln = (file_info_table[fn].listing_line_start
99490075Sobrien	    + line_info_table[i].dst_line_num);
99590075Sobrien
99690075Sobrien      if (ln - lastln > 1)
99790075Sobrien	extrabytes = 5; /* NUMBYTES (ln - lastln - 1) + 1; */
99890075Sobrien      else if (ln <= lastln)
99990075Sobrien	extrabytes = 5; /* NUMBYTES (ln - 1) + 1; */
100090075Sobrien      else
100190075Sobrien	extrabytes = 0;
100290075Sobrien
100390075Sobrien      line_num.dst_a_line_num_header.dst__header_length.dst_w_length
100490075Sobrien	= 8 + extrabytes;
100590075Sobrien
100690075Sobrien      totsize += write_debug_header
100790075Sobrien	(&line_num.dst_a_line_num_header, "line_num", dosizeonly);
100890075Sobrien
100990075Sobrien      if (ln - lastln > 1)
101090075Sobrien	{
101190075Sobrien	  int lndif = ln - lastln - 1;
101290075Sobrien
101390075Sobrien	  /* K_INCR_LINUM (lndif); */
101490075Sobrien	  pcline.dst_b_pcline_command = DST_K_INCR_LINUM_L;
101590075Sobrien
101690075Sobrien	  totsize += write_debug_data1 (pcline.dst_b_pcline_command,
101790075Sobrien					"line_num (INCR LINUM LONG)",
101890075Sobrien					dosizeonly);
101990075Sobrien
102090075Sobrien	  sprintf (buff, "line_num (%d)", lndif);
102190075Sobrien	  totsize += write_debug_data4 (lndif, buff, dosizeonly);
102290075Sobrien	}
102390075Sobrien      else if (ln <= lastln)
102490075Sobrien	{
102590075Sobrien	  /* K_SET_LINUM (ln-1); */
102690075Sobrien	  pcline.dst_b_pcline_command = DST_K_SET_LINUM_L;
102790075Sobrien
102890075Sobrien	  totsize += write_debug_data1 (pcline.dst_b_pcline_command,
102990075Sobrien					"line_num (SET LINUM LONG)",
103090075Sobrien					dosizeonly);
103190075Sobrien
103290075Sobrien	  sprintf (buff, "line_num (%d)", ln - 1);
103390075Sobrien	  totsize += write_debug_data4 (ln - 1, buff, dosizeonly);
103490075Sobrien	}
103590075Sobrien
103690075Sobrien      pcline.dst_b_pcline_command = DST_K_DELTA_PC_L;
103790075Sobrien
103890075Sobrien      totsize += write_debug_data1 (pcline.dst_b_pcline_command,
103990075Sobrien				    "line_num (DELTA PC LONG)", dosizeonly);
104090075Sobrien
104190075Sobrien      ASM_GENERATE_INTERNAL_LABEL (label, LINE_CODE_LABEL, i);
104290075Sobrien      totsize += write_debug_delta4 (label, lastlabel, "increment line_num",
104390075Sobrien				     dosizeonly);
104490075Sobrien
104590075Sobrien      lastln = ln;
104690075Sobrien      strcpy (lastlabel, label);
104790075Sobrien    }
104890075Sobrien
104990075Sobrien  return totsize;
105090075Sobrien}
105190075Sobrien
105290075Sobrien/* Output a source correlation for file FILEID using information saved in
105390075Sobrien   FILE_INFO_ENTRY and return the size.  Just return the size if DOSIZEONLY is
1054117395Skan   nonzero.  */
105590075Sobrien
105690075Sobrienstatic int
1057132718Skanwrite_srccorr (int fileid, dst_file_info_entry file_info_entry,
1058132718Skan	       int dosizeonly)
105990075Sobrien{
106090075Sobrien  int src_command_size;
106190075Sobrien  int linesleft = file_info_entry.max_line;
106290075Sobrien  int linestart = file_info_entry.listing_line_start;
106390075Sobrien  int flen = file_info_entry.flen;
106490075Sobrien  int linestodo = 0;
106590075Sobrien  DST_SOURCE_CORR src_header;
106690075Sobrien  DST_SRC_COMMAND src_command;
106790075Sobrien  DST_SRC_COMMAND src_command_sf;
106890075Sobrien  DST_SRC_COMMAND src_command_sl;
106990075Sobrien  DST_SRC_COMMAND src_command_sr;
107090075Sobrien  DST_SRC_COMMAND src_command_dl;
107190075Sobrien  DST_SRC_CMDTRLR src_cmdtrlr;
107290075Sobrien  char buff[256];
107390075Sobrien  int totsize = 0;
107490075Sobrien
107590075Sobrien  if (fileid == 1)
107690075Sobrien    {
107790075Sobrien      src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
107890075Sobrien	= DST_K_SOURCE_CORR_HEADER_SIZE + 1 - 1;
107990075Sobrien      src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
108090075Sobrien	= DST_K_SOURCE;
108190075Sobrien      src_command.dst_b_src_command = DST_K_SRC_FORMFEED;
108290075Sobrien
108390075Sobrien      totsize += write_debug_header (&src_header.dst_a_source_corr_header,
108490075Sobrien				     "source corr", dosizeonly);
108590075Sobrien
108690075Sobrien      totsize += write_debug_data1 (src_command.dst_b_src_command,
108790075Sobrien				    "source_corr (SRC FORMFEED)",
108890075Sobrien				    dosizeonly);
108990075Sobrien    }
109090075Sobrien
109190075Sobrien  src_command_size
109290075Sobrien    = DST_K_SRC_COMMAND_SIZE + flen + DST_K_SRC_CMDTRLR_SIZE;
109390075Sobrien  src_command.dst_b_src_command = DST_K_SRC_DECLFILE;
109490075Sobrien  src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_length
109590075Sobrien    = src_command_size - 2;
109690075Sobrien  src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_flags = 0;
109790075Sobrien  src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_fileid
109890075Sobrien    = fileid;
109990075Sobrien  src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt
110090075Sobrien    = file_info_entry.cdt;
110190075Sobrien  src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk
110290075Sobrien    = file_info_entry.ebk;
110390075Sobrien  src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_rms_ffb
110490075Sobrien    = file_info_entry.ffb;
110590075Sobrien  src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_rms_rfo
110690075Sobrien    = file_info_entry.rfo;
110790075Sobrien  src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename
110890075Sobrien    = file_info_entry.flen;
110990075Sobrien
111090075Sobrien  src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
111190075Sobrien    = DST_K_SOURCE_CORR_HEADER_SIZE + src_command_size - 1;
111290075Sobrien  src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
111390075Sobrien    = DST_K_SOURCE;
111490075Sobrien
111590075Sobrien  src_cmdtrlr.dst_b_src_df_libmodname = 0;
1116117395Skan
111790075Sobrien  totsize += write_debug_header (&src_header.dst_a_source_corr_header,
111890075Sobrien				 "source corr", dosizeonly);
111990075Sobrien  totsize += write_debug_data1 (src_command.dst_b_src_command,
112090075Sobrien				"source_corr (DECL SRC FILE)", dosizeonly);
112190075Sobrien  totsize += write_debug_data1
112290075Sobrien    (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_length,
112390075Sobrien     "source_corr (length)", dosizeonly);
112490075Sobrien
112590075Sobrien  totsize += write_debug_data1
112690075Sobrien    (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_flags,
112790075Sobrien     "source_corr (flags)", dosizeonly);
112890075Sobrien
112990075Sobrien  totsize += write_debug_data2
113090075Sobrien    (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_fileid,
113190075Sobrien     "source_corr (fileid)", dosizeonly);
113290075Sobrien
113390075Sobrien  totsize += write_debug_data8
113490075Sobrien    (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt,
113590075Sobrien     "source_corr (creation date)", dosizeonly);
1136117395Skan
113790075Sobrien  totsize += write_debug_data4
113890075Sobrien    (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk,
113990075Sobrien     "source_corr (EOF block number)", dosizeonly);
114090075Sobrien
114190075Sobrien  totsize += write_debug_data2
114290075Sobrien    (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_rms_ffb,
114390075Sobrien     "source_corr (first free byte)", dosizeonly);
114490075Sobrien
114590075Sobrien  totsize += write_debug_data1
114690075Sobrien    (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_rms_rfo,
114790075Sobrien     "source_corr (record and file organization)", dosizeonly);
114890075Sobrien
114990075Sobrien  totsize += write_debug_data1
115090075Sobrien    (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename,
115190075Sobrien     "source_corr (filename length)", dosizeonly);
115290075Sobrien
115390075Sobrien  totsize += write_debug_string (file_info_entry.file_name,
115490075Sobrien				 "source file name", dosizeonly);
115590075Sobrien  totsize += write_debug_data1 (src_cmdtrlr.dst_b_src_df_libmodname,
115690075Sobrien				"source_corr (libmodname)", dosizeonly);
115790075Sobrien
115890075Sobrien  src_command_sf.dst_b_src_command = DST_K_SRC_SETFILE;
115990075Sobrien  src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword = fileid;
116090075Sobrien
116190075Sobrien  src_command_sr.dst_b_src_command = DST_K_SRC_SETREC_W;
116290075Sobrien  src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword = 1;
116390075Sobrien
116490075Sobrien  src_command_sl.dst_b_src_command = DST_K_SRC_SETLNUM_L;
116590075Sobrien  src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong = linestart + 1;
116690075Sobrien
116790075Sobrien  src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W;
116890075Sobrien
116990075Sobrien  if (linesleft > 65534)
117090075Sobrien    linesleft = linesleft - 65534, linestodo = 65534;
117190075Sobrien  else
117290075Sobrien    linestodo = linesleft, linesleft = 0;
117390075Sobrien
117490075Sobrien  src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo;
117590075Sobrien
117690075Sobrien  src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
117790075Sobrien    = DST_K_SOURCE_CORR_HEADER_SIZE + 3 + 3 + 5 + 3 - 1;
117890075Sobrien  src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
117990075Sobrien    = DST_K_SOURCE;
118090075Sobrien
1181117395Skan  if (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword)
1182117395Skan    {
1183117395Skan      totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1184117395Skan				     "source corr", dosizeonly);
118590075Sobrien
1186117395Skan      totsize += write_debug_data1 (src_command_sf.dst_b_src_command,
1187117395Skan				    "source_corr (src setfile)", dosizeonly);
118890075Sobrien
1189117395Skan      totsize += write_debug_data2
1190117395Skan	(src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword,
1191117395Skan	 "source_corr (fileid)", dosizeonly);
119290075Sobrien
1193117395Skan      totsize += write_debug_data1 (src_command_sr.dst_b_src_command,
1194117395Skan				    "source_corr (setrec)", dosizeonly);
119590075Sobrien
1196117395Skan      totsize += write_debug_data2
1197117395Skan	(src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword,
1198117395Skan	 "source_corr (recnum)", dosizeonly);
119990075Sobrien
1200117395Skan      totsize += write_debug_data1 (src_command_sl.dst_b_src_command,
1201117395Skan				    "source_corr (setlnum)", dosizeonly);
120290075Sobrien
1203117395Skan      totsize += write_debug_data4
1204117395Skan	(src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong,
1205117395Skan	 "source_corr (linenum)", dosizeonly);
120690075Sobrien
120790075Sobrien      totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
120890075Sobrien				    "source_corr (deflines)", dosizeonly);
1209117395Skan
121090075Sobrien      sprintf (buff, "source_corr (%d)",
121190075Sobrien	       src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
121290075Sobrien      totsize += write_debug_data2
121390075Sobrien	(src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword,
121490075Sobrien	 buff, dosizeonly);
1215117395Skan
1216117395Skan      while (linesleft > 0)
1217117395Skan	{
1218117395Skan	  src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1219117395Skan	    = DST_K_SOURCE_CORR_HEADER_SIZE + 3 - 1;
1220117395Skan	  src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1221117395Skan	    = DST_K_SOURCE;
1222117395Skan	  src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W;
1223117395Skan
1224117395Skan	  if (linesleft > 65534)
1225117395Skan	    linesleft = linesleft - 65534, linestodo = 65534;
1226117395Skan	  else
1227117395Skan	    linestodo = linesleft, linesleft = 0;
1228117395Skan
1229117395Skan	  src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo;
1230117395Skan
1231117395Skan	  totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1232117395Skan					 "source corr", dosizeonly);
1233117395Skan	  totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
1234117395Skan					"source_corr (deflines)", dosizeonly);
1235117395Skan	  sprintf (buff, "source_corr (%d)",
1236117395Skan		   src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
1237117395Skan	  totsize += write_debug_data2
1238117395Skan	    (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword,
1239117395Skan	     buff, dosizeonly);
1240117395Skan	}
124190075Sobrien    }
124290075Sobrien
124390075Sobrien  return totsize;
124490075Sobrien}
124590075Sobrien
124690075Sobrien/* Output all the source correlation entries and return the size.  Just return
1247117395Skan   the size if DOSIZEONLY is nonzero.  */
124890075Sobrien
124990075Sobrienstatic int
1250132718Skanwrite_srccorrs (int dosizeonly)
125190075Sobrien{
125290075Sobrien  unsigned int i;
125390075Sobrien  int totsize = 0;
125490075Sobrien
125590075Sobrien  for (i = 1; i < file_info_table_in_use; i++)
125690075Sobrien    totsize += write_srccorr (i, file_info_table[i], dosizeonly);
125790075Sobrien
125890075Sobrien  return totsize;
1259117395Skan}
126090075Sobrien
126190075Sobrien/* Output a marker (i.e. a label) for the beginning of a function, before
126290075Sobrien   the prologue.  */
126390075Sobrien
126490075Sobrienstatic void
1265132718Skanvmsdbgout_begin_prologue (unsigned int line, const char *file)
126690075Sobrien{
126790075Sobrien  char label[MAX_ARTIFICIAL_LABEL_BYTES];
126890075Sobrien
126990075Sobrien  if (write_symbols == VMS_AND_DWARF2_DEBUG)
127090075Sobrien    (*dwarf2_debug_hooks.begin_prologue) (line, file);
127190075Sobrien
127290075Sobrien  if (debug_info_level > DINFO_LEVEL_NONE)
127390075Sobrien    {
127490075Sobrien      ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL,
1275117395Skan				   current_function_funcdef_no);
127690075Sobrien      ASM_OUTPUT_LABEL (asm_out_file, label);
127790075Sobrien    }
127890075Sobrien}
127990075Sobrien
128090075Sobrien/* Output a marker (i.e. a label) for the beginning of a function, after
128190075Sobrien   the prologue.  */
128290075Sobrien
1283117395Skanstatic void
1284132718Skanvmsdbgout_end_prologue (unsigned int line, const char *file)
128590075Sobrien{
128690075Sobrien  char label[MAX_ARTIFICIAL_LABEL_BYTES];
128790075Sobrien
1288117395Skan  if (write_symbols == VMS_AND_DWARF2_DEBUG)
1289117395Skan    (*dwarf2_debug_hooks.end_prologue) (line, file);
1290117395Skan
129190075Sobrien  if (debug_info_level > DINFO_LEVEL_TERSE)
129290075Sobrien    {
129390075Sobrien      ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL,
1294117395Skan				   current_function_funcdef_no);
129590075Sobrien      ASM_OUTPUT_LABEL (asm_out_file, label);
1296117395Skan
1297132718Skan      /* VMS PCA expects every PC range to correlate to some line and file.  */
1298117395Skan      vmsdbgout_source_line (line, file);
129990075Sobrien    }
130090075Sobrien}
130190075Sobrien
1302117395Skan/* No output for VMS debug, but make obligatory call to Dwarf2 debug */
1303117395Skan
1304117395Skanstatic void
1305132718Skanvmsdbgout_end_function (unsigned int line)
1306117395Skan{
1307117395Skan  if (write_symbols == VMS_AND_DWARF2_DEBUG)
1308117395Skan    (*dwarf2_debug_hooks.end_function) (line);
1309117395Skan}
1310117395Skan
131190075Sobrien/* Output a marker (i.e. a label) for the absolute end of the generated code
131290075Sobrien   for a function definition.  This gets called *after* the epilogue code has
131390075Sobrien   been generated.  */
131490075Sobrien
131590075Sobrienstatic void
1316132718Skanvmsdbgout_end_epilogue (unsigned int line, const char *file)
131790075Sobrien{
131890075Sobrien  char label[MAX_ARTIFICIAL_LABEL_BYTES];
131990075Sobrien
132090075Sobrien  if (write_symbols == VMS_AND_DWARF2_DEBUG)
1321117395Skan    (*dwarf2_debug_hooks.end_epilogue) (line, file);
132290075Sobrien
132390075Sobrien  if (debug_info_level > DINFO_LEVEL_NONE)
132490075Sobrien    {
132590075Sobrien      /* Output a label to mark the endpoint of the code generated for this
132690075Sobrien         function.  */
132790075Sobrien      ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL,
1328117395Skan				   current_function_funcdef_no);
132990075Sobrien      ASM_OUTPUT_LABEL (asm_out_file, label);
1330117395Skan
1331132718Skan      /* VMS PCA expects every PC range to correlate to some line and file.  */
1332117395Skan      vmsdbgout_source_line (line, file);
133390075Sobrien    }
133490075Sobrien}
133590075Sobrien
133690075Sobrien/* Output a marker (i.e. a label) for the beginning of the generated code for
133790075Sobrien   a lexical block.  */
133890075Sobrien
133990075Sobrienstatic void
1340132718Skanvmsdbgout_begin_block (register unsigned line, register unsigned blocknum)
134190075Sobrien{
134290075Sobrien  if (write_symbols == VMS_AND_DWARF2_DEBUG)
134390075Sobrien    (*dwarf2_debug_hooks.begin_block) (line, blocknum);
134490075Sobrien
134590075Sobrien  if (debug_info_level > DINFO_LEVEL_TERSE)
1346169689Skan    targetm.asm_out.internal_label (asm_out_file, BLOCK_BEGIN_LABEL, blocknum);
134790075Sobrien}
134890075Sobrien
134990075Sobrien/* Output a marker (i.e. a label) for the end of the generated code for a
135090075Sobrien   lexical block.  */
135190075Sobrien
135290075Sobrienstatic void
1353132718Skanvmsdbgout_end_block (register unsigned line, register unsigned blocknum)
135490075Sobrien{
135590075Sobrien  if (write_symbols == VMS_AND_DWARF2_DEBUG)
135690075Sobrien    (*dwarf2_debug_hooks.end_block) (line, blocknum);
135790075Sobrien
135890075Sobrien  if (debug_info_level > DINFO_LEVEL_TERSE)
1359169689Skan    targetm.asm_out.internal_label (asm_out_file, BLOCK_END_LABEL, blocknum);
136090075Sobrien}
136190075Sobrien
136290075Sobrien/* Not implemented in VMS Debug.  */
136390075Sobrien
136490075Sobrienstatic bool
1365132718Skanvmsdbgout_ignore_block (tree block)
136690075Sobrien{
136790075Sobrien  bool retval = 0;
136890075Sobrien
136990075Sobrien  if (write_symbols == VMS_AND_DWARF2_DEBUG)
137090075Sobrien    retval = (*dwarf2_debug_hooks.ignore_block) (block);
137190075Sobrien
137290075Sobrien  return retval;
137390075Sobrien}
137490075Sobrien
137590075Sobrien/* Add an entry for function DECL into the func_table.  */
137690075Sobrien
137790075Sobrienstatic void
1378132718Skanvmsdbgout_begin_function (tree decl)
137990075Sobrien{
138090075Sobrien  const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
1381169689Skan  vms_func_ref fde;
138290075Sobrien
138390075Sobrien  if (write_symbols == VMS_AND_DWARF2_DEBUG)
138490075Sobrien    (*dwarf2_debug_hooks.begin_function) (decl);
138590075Sobrien
138690075Sobrien  if (func_table_in_use == func_table_allocated)
138790075Sobrien    {
138890075Sobrien      func_table_allocated += FUNC_TABLE_INCREMENT;
1389169689Skan      func_table
1390169689Skan        = (vms_func_ref) xrealloc (func_table,
1391169689Skan				   func_table_allocated * sizeof (vms_func_node));
139290075Sobrien    }
139390075Sobrien
139490075Sobrien  /* Add the new entry to the end of the function name table.  */
1395169689Skan  fde = &func_table[func_table_in_use++];
1396169689Skan  fde->vms_func_name = xstrdup (name);
1397169689Skan  fde->funcdef_number = current_function_funcdef_no;
1398169689Skan
139990075Sobrien}
140090075Sobrien
140190075Sobrienstatic char fullname_buff [4096];
140290075Sobrien
140390075Sobrien/* Return the full file specification for FILENAME.  The specification must be
140490075Sobrien   in VMS syntax in order to be processed by VMS Debug.  */
140590075Sobrien
140690075Sobrienstatic char *
1407132718Skanfull_name (const char *filename)
140890075Sobrien{
140990075Sobrien#ifdef VMS
141090075Sobrien  FILE *fp = fopen (filename, "r");
141190075Sobrien
141290075Sobrien  fgetname (fp, fullname_buff, 1);
141390075Sobrien  fclose (fp);
141490075Sobrien#else
141590075Sobrien  getcwd (fullname_buff, sizeof (fullname_buff));
141690075Sobrien
141790075Sobrien  strcat (fullname_buff, "/");
141890075Sobrien  strcat (fullname_buff, filename);
141990075Sobrien
142090075Sobrien  /* ??? Insert hairy code here to translate Unix style file specification
142190075Sobrien     to VMS style.  */
142290075Sobrien#endif
142390075Sobrien
142490075Sobrien  return fullname_buff;
142590075Sobrien}
142690075Sobrien
142790075Sobrien/* Lookup a filename (in the list of filenames that we know about here in
142890075Sobrien   vmsdbgout.c) and return its "index".  The index of each (known) filename is
142990075Sobrien   just a unique number which is associated with only that one filename.  We
143090075Sobrien   need such numbers for the sake of generating labels  and references
143190075Sobrien   to those files numbers.  If the filename given as an argument is not
143290075Sobrien   found in our current list, add it to the list and assign it the next
143390075Sobrien   available unique index number.  In order to speed up searches, we remember
143490075Sobrien   the index of the filename was looked up last.  This handles the majority of
143590075Sobrien   all searches.  */
143690075Sobrien
143790075Sobrienstatic unsigned int
1438132718Skanlookup_filename (const char *file_name)
143990075Sobrien{
144090075Sobrien  static unsigned int last_file_lookup_index = 0;
144190075Sobrien  register char *fn;
144290075Sobrien  register unsigned i;
144390075Sobrien  char *fnam;
144490075Sobrien  long long cdt;
144590075Sobrien  long ebk;
144690075Sobrien  short ffb;
144790075Sobrien  char rfo;
144890075Sobrien  char flen;
144990075Sobrien  struct stat statbuf;
145090075Sobrien
145190075Sobrien  if (stat (file_name, &statbuf) == 0)
145290075Sobrien    {
145396263Sobrien      long gmtoff;
145490075Sobrien#ifdef VMS
145596263Sobrien      struct tm *ts;
145696263Sobrien
1457132718Skan      /* Adjust for GMT.  */
145896263Sobrien      ts = (struct tm *) localtime (&statbuf.st_ctime);
145996263Sobrien      gmtoff = ts->tm_gmtoff;
146096263Sobrien
1461132718Skan      /* VMS has multiple file format types.  */
146290075Sobrien      rfo = statbuf.st_fab_rfm;
146390075Sobrien#else
146496263Sobrien      /* Is GMT adjustment an issue with a cross-compiler? */
146596263Sobrien      gmtoff = 0;
146696263Sobrien
1467132718Skan      /* Assume stream LF type file.  */
146890075Sobrien      rfo = 2;
146990075Sobrien#endif
147096263Sobrien      cdt = 10000000 * (statbuf.st_ctime + gmtoff + vms_epoch_offset);
147196263Sobrien      ebk = statbuf.st_size / 512 + 1;
147296263Sobrien      ffb = statbuf.st_size - ((statbuf.st_size / 512) * 512);
147390075Sobrien      fnam = full_name (file_name);
147490075Sobrien      flen = strlen (fnam);
147590075Sobrien    }
147690075Sobrien  else
147790075Sobrien    {
147890075Sobrien      cdt = 0;
147990075Sobrien      ebk = 0;
148090075Sobrien      ffb = 0;
148190075Sobrien      rfo = 0;
148290075Sobrien      fnam = (char *) "";
148390075Sobrien      flen = 0;
148490075Sobrien    }
148590075Sobrien
148690075Sobrien  /* Check to see if the file name that was searched on the previous call
148790075Sobrien     matches this file name. If so, return the index.  */
148890075Sobrien  if (last_file_lookup_index != 0)
148990075Sobrien    {
149090075Sobrien      fn = file_info_table[last_file_lookup_index].file_name;
149190075Sobrien      if (strcmp (fnam, fn) == 0)
149290075Sobrien	return last_file_lookup_index;
149390075Sobrien    }
149490075Sobrien
149590075Sobrien  /* Didn't match the previous lookup, search the table */
149690075Sobrien  for (i = 1; i < file_info_table_in_use; ++i)
149790075Sobrien    {
149890075Sobrien      fn = file_info_table[i].file_name;
149990075Sobrien      if (strcmp (fnam, fn) == 0)
150090075Sobrien	{
150190075Sobrien	  last_file_lookup_index = i;
150290075Sobrien	  return i;
150390075Sobrien	}
150490075Sobrien    }
150590075Sobrien
1506117395Skan  /* Prepare to add a new table entry by making sure there is enough space in
150790075Sobrien     the table to do so.  If not, expand the current table.  */
150890075Sobrien  if (file_info_table_in_use == file_info_table_allocated)
150990075Sobrien    {
151090075Sobrien
151190075Sobrien      file_info_table_allocated += FILE_TABLE_INCREMENT;
1512132718Skan      file_info_table = xrealloc (file_info_table,
1513132718Skan				  (file_info_table_allocated
1514132718Skan				   * sizeof (dst_file_info_entry)));
151590075Sobrien    }
151690075Sobrien
151790075Sobrien  /* Add the new entry to the end of the filename table.  */
151890075Sobrien  file_info_table[file_info_table_in_use].file_name = xstrdup (fnam);
151990075Sobrien  file_info_table[file_info_table_in_use].max_line = 0;
152090075Sobrien  file_info_table[file_info_table_in_use].cdt = cdt;
152190075Sobrien  file_info_table[file_info_table_in_use].ebk = ebk;
152290075Sobrien  file_info_table[file_info_table_in_use].ffb = ffb;
152390075Sobrien  file_info_table[file_info_table_in_use].rfo = rfo;
152490075Sobrien  file_info_table[file_info_table_in_use].flen = flen;
152590075Sobrien
152690075Sobrien  last_file_lookup_index = file_info_table_in_use++;
152790075Sobrien  return last_file_lookup_index;
152890075Sobrien}
152990075Sobrien
153090075Sobrien/* Output a label to mark the beginning of a source code line entry
153190075Sobrien   and record information relating to this source line, in
153290075Sobrien   'line_info_table' for later output of the .debug_line section.  */
153390075Sobrien
153490075Sobrienstatic void
1535132718Skanvmsdbgout_source_line (register unsigned line, register const char *filename)
153690075Sobrien{
153790075Sobrien  if (write_symbols == VMS_AND_DWARF2_DEBUG)
153890075Sobrien    (*dwarf2_debug_hooks.source_line) (line, filename);
153990075Sobrien
154090075Sobrien  if (debug_info_level >= DINFO_LEVEL_TERSE)
154190075Sobrien    {
154290075Sobrien      dst_line_info_ref line_info;
154390075Sobrien
1544169689Skan      targetm.asm_out.internal_label (asm_out_file, LINE_CODE_LABEL,
1545169689Skan				      line_info_table_in_use);
154690075Sobrien
154790075Sobrien      /* Expand the line info table if necessary.  */
154890075Sobrien      if (line_info_table_in_use == line_info_table_allocated)
154990075Sobrien	{
155090075Sobrien	  line_info_table_allocated += LINE_INFO_TABLE_INCREMENT;
1551132718Skan	  line_info_table = xrealloc (line_info_table,
1552132718Skan				      (line_info_table_allocated
1553132718Skan				       * sizeof (dst_line_info_entry)));
1554117395Skan	}
155590075Sobrien
155690075Sobrien      /* Add the new entry at the end of the line_info_table.  */
155790075Sobrien      line_info = &line_info_table[line_info_table_in_use++];
155890075Sobrien      line_info->dst_file_num = lookup_filename (filename);
155990075Sobrien      line_info->dst_line_num = line;
156090075Sobrien      if (line > file_info_table[line_info->dst_file_num].max_line)
156190075Sobrien	file_info_table[line_info->dst_file_num].max_line = line;
156290075Sobrien    }
156390075Sobrien}
156490075Sobrien
156590075Sobrien/* Record the beginning of a new source file, for later output.
156690075Sobrien   At present, unimplemented.  */
156790075Sobrien
156890075Sobrienstatic void
1569132718Skanvmsdbgout_start_source_file (unsigned int lineno, const char *filename)
157090075Sobrien{
157190075Sobrien  if (write_symbols == VMS_AND_DWARF2_DEBUG)
157290075Sobrien    (*dwarf2_debug_hooks.start_source_file) (lineno, filename);
157390075Sobrien}
157490075Sobrien
157590075Sobrien/* Record the end of a source file, for later output.
157690075Sobrien   At present, unimplemented.  */
157790075Sobrien
157890075Sobrienstatic void
1579132718Skanvmsdbgout_end_source_file (unsigned int lineno ATTRIBUTE_UNUSED)
158090075Sobrien{
158190075Sobrien  if (write_symbols == VMS_AND_DWARF2_DEBUG)
158290075Sobrien    (*dwarf2_debug_hooks.end_source_file) (lineno);
158390075Sobrien}
158490075Sobrien
158590075Sobrien/* Set up for Debug output at the start of compilation.  */
158690075Sobrien
158790075Sobrienstatic void
1588132718Skanvmsdbgout_init (const char *main_input_filename)
158990075Sobrien{
159090075Sobrien  const char *language_string = lang_hooks.name;
159190075Sobrien
159290075Sobrien  if (write_symbols == VMS_AND_DWARF2_DEBUG)
159390075Sobrien    (*dwarf2_debug_hooks.init) (main_input_filename);
159490075Sobrien
159590075Sobrien  if (debug_info_level == DINFO_LEVEL_NONE)
159690075Sobrien    return;
159790075Sobrien
159890075Sobrien  /* Remember the name of the primary input file.  */
159990075Sobrien  primary_filename = main_input_filename;
160090075Sobrien
160190075Sobrien  /* Allocate the initial hunk of the file_info_table.  */
160290075Sobrien  file_info_table
1603132718Skan    = xcalloc (FILE_TABLE_INCREMENT, sizeof (dst_file_info_entry));
160490075Sobrien  file_info_table_allocated = FILE_TABLE_INCREMENT;
160590075Sobrien
160690075Sobrien  /* Skip the first entry - file numbers begin at 1 */
160790075Sobrien  file_info_table_in_use = 1;
160890075Sobrien
1609169689Skan  func_table = (vms_func_ref) xcalloc (FUNC_TABLE_INCREMENT, sizeof (vms_func_node));
161090075Sobrien  func_table_allocated = FUNC_TABLE_INCREMENT;
161190075Sobrien  func_table_in_use = 1;
161290075Sobrien
161390075Sobrien  /* Allocate the initial hunk of the line_info_table.  */
161490075Sobrien  line_info_table
1615132718Skan    = xcalloc (LINE_INFO_TABLE_INCREMENT, sizeof (dst_line_info_entry));
161690075Sobrien  line_info_table_allocated = LINE_INFO_TABLE_INCREMENT;
161790075Sobrien  /* zero-th entry is allocated, but unused */
161890075Sobrien  line_info_table_in_use = 1;
161990075Sobrien
162090075Sobrien  lookup_filename (primary_filename);
162190075Sobrien
162290075Sobrien  if (!strcmp (language_string, "GNU C"))
162390075Sobrien    module_language = DST_K_C;
162490075Sobrien  else if (!strcmp (language_string, "GNU C++"))
162590075Sobrien    module_language = DST_K_CXX;
162690075Sobrien  else if (!strcmp (language_string, "GNU Ada"))
162790075Sobrien    module_language = DST_K_ADA;
162890075Sobrien  else if (!strcmp (language_string, "GNU F77"))
162990075Sobrien    module_language = DST_K_FORTRAN;
163090075Sobrien  else
163190075Sobrien    module_language = DST_K_UNKNOWN;
163290075Sobrien
1633117395Skan  module_producer = concat (language_string, " ", version_string, NULL);
163490075Sobrien
163590075Sobrien  ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
163690075Sobrien
163790075Sobrien}
163890075Sobrien
163990075Sobrien/* Not implemented in VMS Debug.  */
164090075Sobrien
164190075Sobrienstatic void
1642132718Skanvmsdbgout_define (unsigned int lineno, const char *buffer)
164390075Sobrien{
164490075Sobrien  if (write_symbols == VMS_AND_DWARF2_DEBUG)
164590075Sobrien    (*dwarf2_debug_hooks.define) (lineno, buffer);
164690075Sobrien}
164790075Sobrien
164890075Sobrien/* Not implemented in VMS Debug.  */
164990075Sobrien
165090075Sobrienstatic void
1651132718Skanvmsdbgout_undef (unsigned int lineno, const char *buffer)
165290075Sobrien{
165390075Sobrien  if (write_symbols == VMS_AND_DWARF2_DEBUG)
165490075Sobrien    (*dwarf2_debug_hooks.undef) (lineno, buffer);
165590075Sobrien}
165690075Sobrien
165790075Sobrien/* Not implemented in VMS Debug.  */
165890075Sobrien
165990075Sobrienstatic void
1660132718Skanvmsdbgout_decl (tree decl)
166190075Sobrien{
166290075Sobrien  if (write_symbols == VMS_AND_DWARF2_DEBUG)
166390075Sobrien    (*dwarf2_debug_hooks.function_decl) (decl);
166490075Sobrien}
166590075Sobrien
166690075Sobrien/* Not implemented in VMS Debug.  */
166790075Sobrien
166890075Sobrienstatic void
1669132718Skanvmsdbgout_global_decl (tree decl)
167090075Sobrien{
167190075Sobrien  if (write_symbols == VMS_AND_DWARF2_DEBUG)
167290075Sobrien    (*dwarf2_debug_hooks.global_decl) (decl);
167390075Sobrien}
167490075Sobrien
167590075Sobrien/* Not implemented in VMS Debug.  */
167690075Sobrien
167790075Sobrienstatic void
1678132718Skanvmsdbgout_abstract_function (tree decl)
167990075Sobrien{
168090075Sobrien  if (write_symbols == VMS_AND_DWARF2_DEBUG)
168190075Sobrien    (*dwarf2_debug_hooks.outlining_inline_function) (decl);
168290075Sobrien}
168390075Sobrien
168490075Sobrien/* Output stuff that Debug requires at the end of every file and generate the
168590075Sobrien   VMS Debug debugging info.  */
168690075Sobrien
168790075Sobrienstatic void
1688132718Skanvmsdbgout_finish (const char *main_input_filename ATTRIBUTE_UNUSED)
168990075Sobrien{
169090075Sobrien  unsigned int i;
169190075Sobrien  int totsize;
169290075Sobrien
169390075Sobrien  if (write_symbols == VMS_AND_DWARF2_DEBUG)
1694132718Skan    (*dwarf2_debug_hooks.finish) (main_input_filename);
169590075Sobrien
169690075Sobrien  if (debug_info_level == DINFO_LEVEL_NONE)
169790075Sobrien    return;
169890075Sobrien
169990075Sobrien  /* Output a terminator label for the .text section.  */
1700169689Skan  switch_to_section (text_section);
1701169689Skan  targetm.asm_out.internal_label (asm_out_file, TEXT_END_LABEL, 0);
170290075Sobrien
170390075Sobrien  /* Output debugging information.
170490075Sobrien     Warning! Do not change the name of the .vmsdebug section without
170590075Sobrien     changing it in the assembler also.  */
1706169689Skan  switch_to_section (get_named_section (NULL, ".vmsdebug", 0));
170790075Sobrien  ASM_OUTPUT_ALIGN (asm_out_file, 0);
170890075Sobrien
170990075Sobrien  totsize = write_modbeg (1);
171090075Sobrien  for (i = 1; i < func_table_in_use; i++)
171190075Sobrien    {
171290075Sobrien      totsize += write_rtnbeg (i, 1);
171390075Sobrien      totsize += write_rtnend (i, 1);
171490075Sobrien    }
171590075Sobrien  totsize += write_pclines (1);
171690075Sobrien
171790075Sobrien  write_modbeg (0);
171890075Sobrien  for (i = 1; i < func_table_in_use; i++)
171990075Sobrien    {
172090075Sobrien      write_rtnbeg (i, 0);
172190075Sobrien      write_rtnend (i, 0);
172290075Sobrien    }
172390075Sobrien  write_pclines (0);
172490075Sobrien
172590075Sobrien  if (debug_info_level > DINFO_LEVEL_TERSE)
172690075Sobrien    {
172790075Sobrien      totsize = write_srccorrs (1);
172890075Sobrien      write_srccorrs (0);
172990075Sobrien    }
173090075Sobrien
173190075Sobrien  totsize = write_modend (1);
173290075Sobrien  write_modend (0);
173390075Sobrien}
173490075Sobrien#endif /* VMS_DEBUGGING_INFO */
1735