* config/arm/arm.h (REG_CLASS_NAMES): Add missing comma.
[official-gcc.git] / gcc / vmsdbgout.c
blob2a963d99bc67f97a82a2b77420d913e5be8f25e3
1 /* Output VMS debug format symbol table information from GCC.
2 Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
4 Contributed by Douglas B. Rupp (rupp@gnat.com).
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
11 version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING. If not, write to the Free
20 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
21 02111-1307, USA. */
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
28 #ifdef VMS_DEBUGGING_INFO
29 #include "tree.h"
30 #include "flags.h"
31 #include "rtl.h"
32 #include "output.h"
33 #include "vmsdbg.h"
34 #include "debug.h"
35 #include "langhooks.h"
36 #include "function.h"
37 #include "target.h"
39 /* Difference in seconds between the VMS Epoch and the Unix Epoch */
40 static const long long vms_epoch_offset = 3506716800ll;
42 /* NOTE: In the comments in this file, many references are made to "Debug
43 Symbol Table". This term is abbreviated as `DST' throughout the remainder
44 of this file. */
46 typedef struct dst_line_info_struct *dst_line_info_ref;
48 /* Each entry in the line_info_table maintains the file and
49 line number associated with the label generated for that
50 entry. The label gives the PC value associated with
51 the line number entry. */
52 typedef struct dst_line_info_struct
54 unsigned long dst_file_num;
55 unsigned long dst_line_num;
57 dst_line_info_entry;
59 typedef struct dst_file_info_struct *dst_file_info_ref;
61 typedef struct dst_file_info_struct
63 char *file_name;
64 unsigned int max_line;
65 unsigned int listing_line_start;
66 long long cdt;
67 long ebk;
68 short ffb;
69 char rfo;
70 char flen;
72 dst_file_info_entry;
74 /* How to start an assembler comment. */
75 #ifndef ASM_COMMENT_START
76 #define ASM_COMMENT_START ";#"
77 #endif
79 /* Maximum size (in bytes) of an artificially generated label. */
80 #define MAX_ARTIFICIAL_LABEL_BYTES 30
82 /* Make sure we know the sizes of the various types debug can describe. These
83 are only defaults. If the sizes are different for your target, you should
84 override these values by defining the appropriate symbols in your tm.h
85 file. */
86 #ifndef PTR_SIZE
87 #define PTR_SIZE 4 /* Must be 32 bits for VMS debug info */
88 #endif
90 /* Pointer to a structure of filenames referenced by this compilation unit. */
91 static dst_file_info_ref file_info_table;
93 /* Total number of entries in the table (i.e. array) pointed to by
94 `file_info_table'. This is the *total* and includes both used and unused
95 slots. */
96 static unsigned int file_info_table_allocated;
98 /* Number of entries in the file_info_table which are actually in use. */
99 static unsigned int file_info_table_in_use;
101 /* Size (in elements) of increments by which we may expand the filename
102 table. */
103 #define FILE_TABLE_INCREMENT 64
105 static char **func_table;
106 static unsigned int func_table_allocated;
107 static unsigned int func_table_in_use;
108 #define FUNC_TABLE_INCREMENT 256
110 /* Local pointer to the name of the main input file. Initialized in
111 avmdbgout_init. */
112 static const char *primary_filename;
114 static char *module_producer;
115 static unsigned int module_language;
117 /* A pointer to the base of a table that contains line information
118 for each source code line in .text in the compilation unit. */
119 static dst_line_info_ref line_info_table;
121 /* Number of elements currently allocated for line_info_table. */
122 static unsigned int line_info_table_allocated;
124 /* Number of elements in line_info_table currently in use. */
125 static unsigned int line_info_table_in_use;
127 /* Size (in elements) of increments by which we may expand line_info_table. */
128 #define LINE_INFO_TABLE_INCREMENT 1024
130 /* Forward declarations for functions defined in this file. */
131 static char *full_name (const char *);
132 static unsigned int lookup_filename (const char *);
133 static void addr_const_to_string (char *, rtx);
134 static int write_debug_header (DST_HEADER *, const char *, int);
135 static int write_debug_addr (char *, const char *, int);
136 static int write_debug_data1 (unsigned int, const char *, int);
137 static int write_debug_data2 (unsigned int, const char *, int);
138 static int write_debug_data4 (unsigned long, const char *, int);
139 static int write_debug_data8 (unsigned long long, const char *, int);
140 static int write_debug_delta4 (char *, char *, const char *, int);
141 static int write_debug_string (char *, const char *, int);
142 static int write_modbeg (int);
143 static int write_modend (int);
144 static int write_rtnbeg (int, int);
145 static int write_rtnend (int, int);
146 static int write_pclines (int);
147 static int write_srccorr (int, dst_file_info_entry, int);
148 static int write_srccorrs (int);
150 static void vmsdbgout_init (const char *);
151 static void vmsdbgout_finish (const char *);
152 static void vmsdbgout_define (unsigned int, const char *);
153 static void vmsdbgout_undef (unsigned int, const char *);
154 static void vmsdbgout_start_source_file (unsigned int, const char *);
155 static void vmsdbgout_end_source_file (unsigned int);
156 static void vmsdbgout_begin_block (unsigned int, unsigned int);
157 static void vmsdbgout_end_block (unsigned int, unsigned int);
158 static bool vmsdbgout_ignore_block (tree);
159 static void vmsdbgout_source_line (unsigned int, const char *);
160 static void vmsdbgout_begin_prologue (unsigned int, const char *);
161 static void vmsdbgout_end_prologue (unsigned int, const char *);
162 static void vmsdbgout_end_function (unsigned int);
163 static void vmsdbgout_end_epilogue (unsigned int, const char *);
164 static void vmsdbgout_begin_function (tree);
165 static void vmsdbgout_decl (tree);
166 static void vmsdbgout_global_decl (tree);
167 static void vmsdbgout_abstract_function (tree);
169 /* The debug hooks structure. */
171 const struct gcc_debug_hooks vmsdbg_debug_hooks
172 = {vmsdbgout_init,
173 vmsdbgout_finish,
174 vmsdbgout_define,
175 vmsdbgout_undef,
176 vmsdbgout_start_source_file,
177 vmsdbgout_end_source_file,
178 vmsdbgout_begin_block,
179 vmsdbgout_end_block,
180 vmsdbgout_ignore_block,
181 vmsdbgout_source_line,
182 vmsdbgout_begin_prologue,
183 vmsdbgout_end_prologue,
184 vmsdbgout_end_epilogue,
185 vmsdbgout_begin_function,
186 vmsdbgout_end_function,
187 vmsdbgout_decl,
188 vmsdbgout_global_decl,
189 debug_nothing_tree_tree, /* imported_module_or_decl */
190 debug_nothing_tree, /* deferred_inline_function */
191 vmsdbgout_abstract_function,
192 debug_nothing_rtx, /* label */
193 debug_nothing_int /* handle_pch */
196 /* Definitions of defaults for assembler-dependent names of various
197 pseudo-ops and section names.
198 Theses may be overridden in the tm.h file (if necessary) for a particular
199 assembler. */
200 #ifdef UNALIGNED_SHORT_ASM_OP
201 #undef UNALIGNED_SHORT_ASM_OP
202 #endif
203 #define UNALIGNED_SHORT_ASM_OP ".word"
205 #ifdef UNALIGNED_INT_ASM_OP
206 #undef UNALIGNED_INT_ASM_OP
207 #endif
208 #define UNALIGNED_INT_ASM_OP ".long"
210 #ifdef UNALIGNED_LONG_ASM_OP
211 #undef UNALIGNED_LONG_ASM_OP
212 #endif
213 #define UNALIGNED_LONG_ASM_OP ".long"
215 #ifdef UNALIGNED_DOUBLE_INT_ASM_OP
216 #undef UNALIGNED_DOUBLE_INT_ASM_OP
217 #endif
218 #define UNALIGNED_DOUBLE_INT_ASM_OP ".quad"
220 #ifdef ASM_BYTE_OP
221 #undef ASM_BYTE_OP
222 #endif
223 #define ASM_BYTE_OP ".byte"
225 #define NUMBYTES(I) ((I) < 256 ? 1 : (I) < 65536 ? 2 : 4)
227 #define NUMBYTES0(I) ((I) < 128 ? 0 : (I) < 65536 ? 2 : 4)
229 #ifndef UNALIGNED_PTR_ASM_OP
230 #define UNALIGNED_PTR_ASM_OP \
231 (PTR_SIZE == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP : UNALIGNED_INT_ASM_OP)
232 #endif
234 #ifndef UNALIGNED_OFFSET_ASM_OP
235 #define UNALIGNED_OFFSET_ASM_OP(OFFSET) \
236 (NUMBYTES(OFFSET) == 4 \
237 ? UNALIGNED_LONG_ASM_OP \
238 : (NUMBYTES(OFFSET) == 2 ? UNALIGNED_SHORT_ASM_OP : ASM_BYTE_OP))
239 #endif
241 /* Definitions of defaults for formats and names of various special
242 (artificial) labels which may be generated within this file (when the -g
243 options is used and VMS_DEBUGGING_INFO is in effect. If necessary, these
244 may be overridden from within the tm.h file, but typically, overriding these
245 defaults is unnecessary. */
247 static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
249 #ifndef TEXT_END_LABEL
250 #define TEXT_END_LABEL "Lvetext"
251 #endif
252 #ifndef FUNC_BEGIN_LABEL
253 #define FUNC_BEGIN_LABEL "LVFB"
254 #endif
255 #ifndef FUNC_PROLOG_LABEL
256 #define FUNC_PROLOG_LABEL "LVFP"
257 #endif
258 #ifndef FUNC_END_LABEL
259 #define FUNC_END_LABEL "LVFE"
260 #endif
261 #ifndef BLOCK_BEGIN_LABEL
262 #define BLOCK_BEGIN_LABEL "LVBB"
263 #endif
264 #ifndef BLOCK_END_LABEL
265 #define BLOCK_END_LABEL "LVBE"
266 #endif
267 #ifndef LINE_CODE_LABEL
268 #define LINE_CODE_LABEL "LVM"
269 #endif
271 #ifndef ASM_OUTPUT_DEBUG_DELTA2
272 #define ASM_OUTPUT_DEBUG_DELTA2(FILE,LABEL1,LABEL2) \
273 do \
275 fprintf ((FILE), "\t%s\t", UNALIGNED_SHORT_ASM_OP); \
276 assemble_name (FILE, LABEL1); \
277 fprintf (FILE, "-"); \
278 assemble_name (FILE, LABEL2); \
280 while (0)
281 #endif
283 #ifndef ASM_OUTPUT_DEBUG_DELTA4
284 #define ASM_OUTPUT_DEBUG_DELTA4(FILE,LABEL1,LABEL2) \
285 do \
287 fprintf ((FILE), "\t%s\t", UNALIGNED_INT_ASM_OP); \
288 assemble_name (FILE, LABEL1); \
289 fprintf (FILE, "-"); \
290 assemble_name (FILE, LABEL2); \
292 while (0)
293 #endif
295 #ifndef ASM_OUTPUT_DEBUG_ADDR_DELTA
296 #define ASM_OUTPUT_DEBUG_ADDR_DELTA(FILE,LABEL1,LABEL2) \
297 do \
299 fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP); \
300 assemble_name (FILE, LABEL1); \
301 fprintf (FILE, "-"); \
302 assemble_name (FILE, LABEL2); \
304 while (0)
305 #endif
307 #ifndef ASM_OUTPUT_DEBUG_ADDR
308 #define ASM_OUTPUT_DEBUG_ADDR(FILE,LABEL) \
309 do \
311 fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP); \
312 assemble_name (FILE, LABEL); \
314 while (0)
315 #endif
317 #ifndef ASM_OUTPUT_DEBUG_ADDR_CONST
318 #define ASM_OUTPUT_DEBUG_ADDR_CONST(FILE,ADDR) \
319 fprintf ((FILE), "\t%s\t%s", UNALIGNED_PTR_ASM_OP, (ADDR))
320 #endif
322 #ifndef ASM_OUTPUT_DEBUG_DATA1
323 #define ASM_OUTPUT_DEBUG_DATA1(FILE,VALUE) \
324 fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, (unsigned char) VALUE)
325 #endif
327 #ifndef ASM_OUTPUT_DEBUG_DATA2
328 #define ASM_OUTPUT_DEBUG_DATA2(FILE,VALUE) \
329 fprintf ((FILE), "\t%s\t0x%x", UNALIGNED_SHORT_ASM_OP, \
330 (unsigned short) VALUE)
331 #endif
333 #ifndef ASM_OUTPUT_DEBUG_DATA4
334 #define ASM_OUTPUT_DEBUG_DATA4(FILE,VALUE) \
335 fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_INT_ASM_OP, (unsigned long) VALUE)
336 #endif
338 #ifndef ASM_OUTPUT_DEBUG_DATA
339 #define ASM_OUTPUT_DEBUG_DATA(FILE,VALUE) \
340 fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_OFFSET_ASM_OP(VALUE), VALUE)
341 #endif
343 #ifndef ASM_OUTPUT_DEBUG_ADDR_DATA
344 #define ASM_OUTPUT_DEBUG_ADDR_DATA(FILE,VALUE) \
345 fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_PTR_ASM_OP, \
346 (unsigned long) VALUE)
347 #endif
349 #ifndef ASM_OUTPUT_DEBUG_DATA8
350 #define ASM_OUTPUT_DEBUG_DATA8(FILE,VALUE) \
351 fprintf ((FILE), "\t%s\t0x%llx", UNALIGNED_DOUBLE_INT_ASM_OP, \
352 (unsigned long long) VALUE)
353 #endif
355 /* This is similar to the default ASM_OUTPUT_ASCII, except that no trailing
356 newline is produced. When flag_verbose_asm is asserted, we add commentary
357 at the end of the line, so we must avoid output of a newline here. */
358 #ifndef ASM_OUTPUT_DEBUG_STRING
359 #define ASM_OUTPUT_DEBUG_STRING(FILE,P) \
360 do \
362 register int slen = strlen(P); \
363 register char *p = (P); \
364 register int i; \
365 fprintf (FILE, "\t.ascii \""); \
366 for (i = 0; i < slen; i++) \
368 register int c = p[i]; \
369 if (c == '\"' || c == '\\') \
370 putc ('\\', FILE); \
371 if (c >= ' ' && c < 0177) \
372 putc (c, FILE); \
373 else \
374 fprintf (FILE, "\\%o", c); \
376 fprintf (FILE, "\""); \
378 while (0)
379 #endif
381 /* Convert a reference to the assembler name of a C-level name. This
382 macro has the same effect as ASM_OUTPUT_LABELREF, but copies to
383 a string rather than writing to a file. */
384 #ifndef ASM_NAME_TO_STRING
385 #define ASM_NAME_TO_STRING(STR, NAME) \
386 do \
388 if ((NAME)[0] == '*') \
389 strcpy (STR, NAME+1); \
390 else \
391 strcpy (STR, NAME); \
393 while (0)
394 #endif
397 /* General utility functions. */
399 /* Convert an integer constant expression into assembler syntax. Addition and
400 subtraction are the only arithmetic that may appear in these expressions.
401 This is an adaptation of output_addr_const in final.c. Here, the target
402 of the conversion is a string buffer. We can't use output_addr_const
403 directly, because it writes to a file. */
405 static void
406 addr_const_to_string (char *str, rtx x)
408 char buf1[256];
409 char buf2[256];
411 restart:
412 str[0] = '\0';
413 switch (GET_CODE (x))
415 case PC:
416 if (flag_pic)
417 strcat (str, ",");
418 else
419 abort ();
420 break;
422 case SYMBOL_REF:
423 ASM_NAME_TO_STRING (buf1, XSTR (x, 0));
424 strcat (str, buf1);
425 break;
427 case LABEL_REF:
428 ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
429 ASM_NAME_TO_STRING (buf2, buf1);
430 strcat (str, buf2);
431 break;
433 case CODE_LABEL:
434 ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (x));
435 ASM_NAME_TO_STRING (buf2, buf1);
436 strcat (str, buf2);
437 break;
439 case CONST_INT:
440 sprintf (buf1, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
441 strcat (str, buf1);
442 break;
444 case CONST:
445 /* This used to output parentheses around the expression, but that does
446 not work on the 386 (either ATT or BSD assembler). */
447 addr_const_to_string (buf1, XEXP (x, 0));
448 strcat (str, buf1);
449 break;
451 case CONST_DOUBLE:
452 if (GET_MODE (x) == VOIDmode)
454 /* We can use %d if the number is one word and positive. */
455 if (CONST_DOUBLE_HIGH (x))
456 sprintf (buf1, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
457 CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
458 else if (CONST_DOUBLE_LOW (x) < 0)
459 sprintf (buf1, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (x));
460 else
461 sprintf (buf1, HOST_WIDE_INT_PRINT_DEC,
462 CONST_DOUBLE_LOW (x));
463 strcat (str, buf1);
465 else
466 /* We can't handle floating point constants; PRINT_OPERAND must
467 handle them. */
468 output_operand_lossage ("floating constant misused");
469 break;
471 case PLUS:
472 /* Some assemblers need integer constants to appear last (eg masm). */
473 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
475 addr_const_to_string (buf1, XEXP (x, 1));
476 strcat (str, buf1);
477 if (INTVAL (XEXP (x, 0)) >= 0)
478 strcat (str, "+");
479 addr_const_to_string (buf1, XEXP (x, 0));
480 strcat (str, buf1);
482 else
484 addr_const_to_string (buf1, XEXP (x, 0));
485 strcat (str, buf1);
486 if (INTVAL (XEXP (x, 1)) >= 0)
487 strcat (str, "+");
488 addr_const_to_string (buf1, XEXP (x, 1));
489 strcat (str, buf1);
491 break;
493 case MINUS:
494 /* Avoid outputting things like x-x or x+5-x, since some assemblers
495 can't handle that. */
496 x = simplify_subtraction (x);
497 if (GET_CODE (x) != MINUS)
498 goto restart;
500 addr_const_to_string (buf1, XEXP (x, 0));
501 strcat (str, buf1);
502 strcat (str, "-");
503 if (GET_CODE (XEXP (x, 1)) == CONST_INT
504 && INTVAL (XEXP (x, 1)) < 0)
506 strcat (str, "(");
507 addr_const_to_string (buf1, XEXP (x, 1));
508 strcat (str, buf1);
509 strcat (str, ")");
511 else
513 addr_const_to_string (buf1, XEXP (x, 1));
514 strcat (str, buf1);
516 break;
518 case ZERO_EXTEND:
519 case SIGN_EXTEND:
520 addr_const_to_string (buf1, XEXP (x, 0));
521 strcat (str, buf1);
522 break;
524 default:
525 output_operand_lossage ("invalid expression as operand");
529 /* Output the debug header HEADER. Also output COMMENT if flag_verbose_asm is
530 set. Return the header size. Just return the size if DOSIZEONLY is
531 nonzero. */
533 static int
534 write_debug_header (DST_HEADER *header, const char *comment, int dosizeonly)
536 if (!dosizeonly)
538 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file,
539 header->dst__header_length.dst_w_length);
541 if (flag_verbose_asm)
542 fprintf (asm_out_file, "\t%s record length", ASM_COMMENT_START);
543 fputc ('\n', asm_out_file);
545 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file,
546 header->dst__header_type.dst_w_type);
548 if (flag_verbose_asm)
549 fprintf (asm_out_file, "\t%s record type (%s)", ASM_COMMENT_START,
550 comment);
552 fputc ('\n', asm_out_file);
555 return 4;
558 /* Output the address of SYMBOL. Also output COMMENT if flag_verbose_asm is
559 set. Return the address size. Just return the size if DOSIZEONLY is
560 nonzero. */
562 static int
563 write_debug_addr (char *symbol, const char *comment, int dosizeonly)
565 if (!dosizeonly)
567 ASM_OUTPUT_DEBUG_ADDR (asm_out_file, symbol);
568 if (flag_verbose_asm)
569 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
570 fputc ('\n', asm_out_file);
573 return PTR_SIZE;
576 /* Output the single byte DATA1. Also output COMMENT if flag_verbose_asm is
577 set. Return the data size. Just return the size if DOSIZEONLY is
578 nonzero. */
580 static int
581 write_debug_data1 (unsigned int data1, const char *comment, int dosizeonly)
583 if (!dosizeonly)
585 ASM_OUTPUT_DEBUG_DATA1 (asm_out_file, data1);
586 if (flag_verbose_asm)
587 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
588 fputc ('\n', asm_out_file);
591 return 1;
594 /* Output the single word DATA2. Also output COMMENT if flag_verbose_asm is
595 set. Return the data size. Just return the size if DOSIZEONLY is
596 nonzero. */
598 static int
599 write_debug_data2 (unsigned int data2, const char *comment, int dosizeonly)
601 if (!dosizeonly)
603 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file, data2);
604 if (flag_verbose_asm)
605 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
606 fputc ('\n', asm_out_file);
609 return 2;
612 /* Output double word DATA4. Also output COMMENT if flag_verbose_asm is set.
613 Return the data size. Just return the size if DOSIZEONLY is nonzero. */
615 static int
616 write_debug_data4 (unsigned long data4, const char *comment, int dosizeonly)
618 if (!dosizeonly)
620 ASM_OUTPUT_DEBUG_DATA4 (asm_out_file, data4);
621 if (flag_verbose_asm)
622 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
623 fputc ('\n', asm_out_file);
626 return 4;
629 /* Output quad word DATA8. Also output COMMENT if flag_verbose_asm is set.
630 Return the data size. Just return the size if DOSIZEONLY is nonzero. */
632 static int
633 write_debug_data8 (unsigned long long data8, const char *comment,
634 int dosizeonly)
636 if (!dosizeonly)
638 ASM_OUTPUT_DEBUG_DATA8 (asm_out_file, data8);
639 if (flag_verbose_asm)
640 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
641 fputc ('\n', asm_out_file);
644 return 8;
647 /* Output the difference between LABEL1 and LABEL2. Also output COMMENT if
648 flag_verbose_asm is set. Return the data size. Just return the size if
649 DOSIZEONLY is nonzero. */
651 static int
652 write_debug_delta4 (char *label1, char *label2, const char *comment,
653 int dosizeonly)
655 if (!dosizeonly)
657 ASM_OUTPUT_DEBUG_DELTA4 (asm_out_file, label1, label2);
658 if (flag_verbose_asm)
659 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
660 fputc ('\n', asm_out_file);
663 return 4;
666 /* Output a character string STRING. Also write COMMENT if flag_verbose_asm is
667 set. Return the string length. Just return the length if DOSIZEONLY is
668 nonzero. */
670 static int
671 write_debug_string (char *string, const char *comment, int dosizeonly)
673 if (!dosizeonly)
675 ASM_OUTPUT_DEBUG_STRING (asm_out_file, string);
676 if (flag_verbose_asm)
677 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
678 fputc ('\n', asm_out_file);
681 return strlen (string);
684 /* Output a module begin header and return the header size. Just return the
685 size if DOSIZEONLY is nonzero. */
687 static int
688 write_modbeg (int dosizeonly)
690 DST_MODULE_BEGIN modbeg;
691 DST_MB_TRLR mb_trlr;
692 int i;
693 char *module_name, *m;
694 int modnamelen;
695 int prodnamelen;
696 int totsize = 0;
698 /* Assumes primary filename has Unix syntax file spec. */
699 module_name = xstrdup (basename ((char *) primary_filename));
701 m = strrchr (module_name, '.');
702 if (m)
703 *m = 0;
705 modnamelen = strlen (module_name);
706 for (i = 0; i < modnamelen; i++)
707 module_name[i] = TOUPPER (module_name[i]);
709 prodnamelen = strlen (module_producer);
711 modbeg.dst_a_modbeg_header.dst__header_length.dst_w_length
712 = DST_K_MODBEG_SIZE + modnamelen + DST_K_MB_TRLR_SIZE + prodnamelen - 1;
713 modbeg.dst_a_modbeg_header.dst__header_type.dst_w_type = DST_K_MODBEG;
714 modbeg.dst_b_modbeg_flags.dst_v_modbeg_hide = 0;
715 modbeg.dst_b_modbeg_flags.dst_v_modbeg_version = 1;
716 modbeg.dst_b_modbeg_flags.dst_v_modbeg_unused = 0;
717 modbeg.dst_b_modbeg_unused = 0;
718 modbeg.dst_l_modbeg_language = module_language;
719 modbeg.dst_w_version_major = DST_K_VERSION_MAJOR;
720 modbeg.dst_w_version_minor = DST_K_VERSION_MINOR;
721 modbeg.dst_b_modbeg_name = strlen (module_name);
723 mb_trlr.dst_b_compiler = strlen (module_producer);
725 totsize += write_debug_header (&modbeg.dst_a_modbeg_header,
726 "modbeg", dosizeonly);
727 totsize += write_debug_data1 (*((char *) &modbeg.dst_b_modbeg_flags),
728 "flags", dosizeonly);
729 totsize += write_debug_data1 (modbeg.dst_b_modbeg_unused,
730 "unused", dosizeonly);
731 totsize += write_debug_data4 (modbeg.dst_l_modbeg_language,
732 "language", dosizeonly);
733 totsize += write_debug_data2 (modbeg.dst_w_version_major,
734 "DST major version", dosizeonly);
735 totsize += write_debug_data2 (modbeg.dst_w_version_minor,
736 "DST minor version", dosizeonly);
737 totsize += write_debug_data1 (modbeg.dst_b_modbeg_name,
738 "length of module name", dosizeonly);
739 totsize += write_debug_string (module_name, "module name", dosizeonly);
740 totsize += write_debug_data1 (mb_trlr.dst_b_compiler,
741 "length of compiler name", dosizeonly);
742 totsize += write_debug_string (module_producer, "compiler name", dosizeonly);
744 return totsize;
747 /* Output a module end trailer and return the trailer size. Just return
748 the size if DOSIZEONLY is nonzero. */
750 static int
751 write_modend (int dosizeonly)
753 DST_MODULE_END modend;
754 int totsize = 0;
756 modend.dst_a_modend_header.dst__header_length.dst_w_length
757 = DST_K_MODEND_SIZE - 1;
758 modend.dst_a_modend_header.dst__header_type.dst_w_type = DST_K_MODEND;
760 totsize += write_debug_header (&modend.dst_a_modend_header, "modend",
761 dosizeonly);
763 return totsize;
766 /* Output a routine begin header routine RTNNUM and return the header size.
767 Just return the size if DOSIZEONLY is nonzero. */
769 static int
770 write_rtnbeg (int rtnnum, int dosizeonly)
772 char *rtnname;
773 int rtnnamelen;
774 char *rtnentryname;
775 int totsize = 0;
776 char label[MAX_ARTIFICIAL_LABEL_BYTES];
777 DST_ROUTINE_BEGIN rtnbeg;
778 DST_PROLOG prolog;
780 rtnname = func_table[rtnnum];
781 rtnnamelen = strlen (rtnname);
782 rtnentryname = concat (rtnname, "..en", NULL);
784 if (!strcmp (rtnname, "main"))
786 DST_HEADER header;
787 const char *go = "TRANSFER$BREAK$GO";
789 /* This command isn't documented in DSTRECORDS, so it's made to
790 look like what DEC C does */
792 /* header size - 1st byte + flag byte + STO_LW size
793 + string count byte + string length */
794 header.dst__header_length.dst_w_length
795 = DST_K_DST_HEADER_SIZE - 1 + 1 + 4 + 1 + strlen (go);
796 header.dst__header_type.dst_w_type = 0x17;
798 totsize += write_debug_header (&header, "transfer", dosizeonly);
800 /* I think this is a flag byte, but I don't know what this flag means */
801 totsize += write_debug_data1 (0x1, "flags ???", dosizeonly);
803 /* Routine Begin PD Address */
804 totsize += write_debug_addr (rtnname, "main procedure descriptor",
805 dosizeonly);
806 totsize += write_debug_data1 (strlen (go), "length of main_name",
807 dosizeonly);
808 totsize += write_debug_string ((char *) go, "main name", dosizeonly);
811 /* The header length never includes the length byte. */
812 rtnbeg.dst_a_rtnbeg_header.dst__header_length.dst_w_length
813 = DST_K_RTNBEG_SIZE + rtnnamelen - 1;
814 rtnbeg.dst_a_rtnbeg_header.dst__header_type.dst_w_type = DST_K_RTNBEG;
815 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_unused = 0;
816 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_unalloc = 0;
817 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_prototype = 0;
818 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_inlined = 0;
819 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_no_call = 1;
820 rtnbeg.dst_b_rtnbeg_name = rtnnamelen;
822 totsize += write_debug_header (&rtnbeg.dst_a_rtnbeg_header, "rtnbeg",
823 dosizeonly);
824 totsize += write_debug_data1 (*((char *) &rtnbeg.dst_b_rtnbeg_flags),
825 "flags", dosizeonly);
827 /* Routine Begin Address */
828 totsize += write_debug_addr (rtnentryname, "routine entry name", dosizeonly);
830 /* Routine Begin PD Address */
831 totsize += write_debug_addr (rtnname, "routine procedure descriptor",
832 dosizeonly);
834 /* Routine Begin Name */
835 totsize += write_debug_data1 (rtnbeg.dst_b_rtnbeg_name,
836 "length of routine name", dosizeonly);
838 totsize += write_debug_string (rtnname, "routine name", dosizeonly);
840 free (rtnentryname);
842 if (debug_info_level > DINFO_LEVEL_TERSE)
844 prolog.dst_a_prolog_header.dst__header_length.dst_w_length
845 = DST_K_PROLOG_SIZE - 1;
846 prolog.dst_a_prolog_header.dst__header_type.dst_w_type = DST_K_PROLOG;
848 totsize += write_debug_header (&prolog.dst_a_prolog_header, "prolog",
849 dosizeonly);
851 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL, rtnnum);
852 totsize += write_debug_addr (label, "prolog breakpoint addr",
853 dosizeonly);
856 return totsize;
859 /* Output a routine end trailer for routine RTNNUM and return the header size.
860 Just return the size if DOSIZEONLY is nonzero. */
862 static int
863 write_rtnend (int rtnnum, int dosizeonly)
865 DST_ROUTINE_END rtnend;
866 char label1[MAX_ARTIFICIAL_LABEL_BYTES];
867 char label2[MAX_ARTIFICIAL_LABEL_BYTES];
868 int totsize;
870 totsize = 0;
872 rtnend.dst_a_rtnend_header.dst__header_length.dst_w_length
873 = DST_K_RTNEND_SIZE - 1;
874 rtnend.dst_a_rtnend_header.dst__header_type.dst_w_type = DST_K_RTNEND;
875 rtnend.dst_b_rtnend_unused = 0;
876 rtnend.dst_l_rtnend_size = 0; /* Calculated below. */
878 totsize += write_debug_header (&rtnend.dst_a_rtnend_header, "rtnend",
879 dosizeonly);
880 totsize += write_debug_data1 (rtnend.dst_b_rtnend_unused, "unused",
881 dosizeonly);
883 ASM_GENERATE_INTERNAL_LABEL (label1, FUNC_BEGIN_LABEL, rtnnum);
884 ASM_GENERATE_INTERNAL_LABEL (label2, FUNC_END_LABEL, rtnnum);
885 totsize += write_debug_delta4 (label2, label1, "routine size", dosizeonly);
887 return totsize;
890 #define K_DELTA_PC(I) \
891 ((I) < 128 ? -(I) : (I) < 65536 ? DST_K_DELTA_PC_W : DST_K_DELTA_PC_L)
893 #define K_SET_LINUM(I) \
894 ((I) < 256 ? DST_K_SET_LINUM_B \
895 : (I) < 65536 ? DST_K_SET_LINUM : DST_K_SET_LINUM_L)
897 #define K_INCR_LINUM(I) \
898 ((I) < 256 ? DST_K_INCR_LINUM \
899 : (I) < 65536 ? DST_K_INCR_LINUM_W : DST_K_INCR_LINUM_L)
901 /* Output the PC to line number correlations and return the size. Just return
902 the size if DOSIZEONLY is nonzero */
904 static int
905 write_pclines (int dosizeonly)
907 unsigned i;
908 int fn;
909 int ln, lastln;
910 int linestart = 0;
911 int max_line;
912 DST_LINE_NUM_HEADER line_num;
913 DST_PCLINE_COMMANDS pcline;
914 char label[MAX_ARTIFICIAL_LABEL_BYTES];
915 char lastlabel[MAX_ARTIFICIAL_LABEL_BYTES];
916 int totsize = 0;
917 char buff[256];
919 max_line = file_info_table[1].max_line;
920 file_info_table[1].listing_line_start = linestart;
921 linestart = linestart + ((max_line / 100000) + 1) * 100000;
923 for (i = 2; i < file_info_table_in_use; i++)
925 max_line = file_info_table[i].max_line;
926 file_info_table[i].listing_line_start = linestart;
927 linestart = linestart + ((max_line / 10000) + 1) * 10000;
930 /* Set starting address to beginning of text section. */
931 line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 8;
932 line_num.dst_a_line_num_header.dst__header_type.dst_w_type = DST_K_LINE_NUM;
933 pcline.dst_b_pcline_command = DST_K_SET_ABS_PC;
935 totsize += write_debug_header (&line_num.dst_a_line_num_header,
936 "line_num", dosizeonly);
937 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
938 "line_num (SET ABS PC)", dosizeonly);
940 if (dosizeonly)
941 totsize += 4;
942 else
944 ASM_OUTPUT_DEBUG_ADDR (asm_out_file, TEXT_SECTION_ASM_OP);
945 if (flag_verbose_asm)
946 fprintf (asm_out_file, "\t%s line_num", ASM_COMMENT_START);
947 fputc ('\n', asm_out_file);
950 fn = line_info_table[1].dst_file_num;
951 ln = (file_info_table[fn].listing_line_start
952 + line_info_table[1].dst_line_num);
953 line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 4 + 4;
954 pcline.dst_b_pcline_command = DST_K_SET_LINUM_L;
956 totsize += write_debug_header (&line_num.dst_a_line_num_header,
957 "line_num", dosizeonly);
958 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
959 "line_num (SET LINUM LONG)", dosizeonly);
961 sprintf (buff, "line_num (%d)", ln ? ln - 1 : 0);
962 totsize += write_debug_data4 (ln ? ln - 1 : 0, buff, dosizeonly);
964 lastln = ln;
965 strcpy (lastlabel, TEXT_SECTION_ASM_OP);
966 for (i = 1; i < line_info_table_in_use; i++)
968 int extrabytes;
970 fn = line_info_table[i].dst_file_num;
971 ln = (file_info_table[fn].listing_line_start
972 + line_info_table[i].dst_line_num);
974 if (ln - lastln > 1)
975 extrabytes = 5; /* NUMBYTES (ln - lastln - 1) + 1; */
976 else if (ln <= lastln)
977 extrabytes = 5; /* NUMBYTES (ln - 1) + 1; */
978 else
979 extrabytes = 0;
981 line_num.dst_a_line_num_header.dst__header_length.dst_w_length
982 = 8 + extrabytes;
984 totsize += write_debug_header
985 (&line_num.dst_a_line_num_header, "line_num", dosizeonly);
987 if (ln - lastln > 1)
989 int lndif = ln - lastln - 1;
991 /* K_INCR_LINUM (lndif); */
992 pcline.dst_b_pcline_command = DST_K_INCR_LINUM_L;
994 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
995 "line_num (INCR LINUM LONG)",
996 dosizeonly);
998 sprintf (buff, "line_num (%d)", lndif);
999 totsize += write_debug_data4 (lndif, buff, dosizeonly);
1001 else if (ln <= lastln)
1003 /* K_SET_LINUM (ln-1); */
1004 pcline.dst_b_pcline_command = DST_K_SET_LINUM_L;
1006 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
1007 "line_num (SET LINUM LONG)",
1008 dosizeonly);
1010 sprintf (buff, "line_num (%d)", ln - 1);
1011 totsize += write_debug_data4 (ln - 1, buff, dosizeonly);
1014 pcline.dst_b_pcline_command = DST_K_DELTA_PC_L;
1016 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
1017 "line_num (DELTA PC LONG)", dosizeonly);
1019 ASM_GENERATE_INTERNAL_LABEL (label, LINE_CODE_LABEL, i);
1020 totsize += write_debug_delta4 (label, lastlabel, "increment line_num",
1021 dosizeonly);
1023 lastln = ln;
1024 strcpy (lastlabel, label);
1027 return totsize;
1030 /* Output a source correlation for file FILEID using information saved in
1031 FILE_INFO_ENTRY and return the size. Just return the size if DOSIZEONLY is
1032 nonzero. */
1034 static int
1035 write_srccorr (int fileid, dst_file_info_entry file_info_entry,
1036 int dosizeonly)
1038 int src_command_size;
1039 int linesleft = file_info_entry.max_line;
1040 int linestart = file_info_entry.listing_line_start;
1041 int flen = file_info_entry.flen;
1042 int linestodo = 0;
1043 DST_SOURCE_CORR src_header;
1044 DST_SRC_COMMAND src_command;
1045 DST_SRC_COMMAND src_command_sf;
1046 DST_SRC_COMMAND src_command_sl;
1047 DST_SRC_COMMAND src_command_sr;
1048 DST_SRC_COMMAND src_command_dl;
1049 DST_SRC_CMDTRLR src_cmdtrlr;
1050 char buff[256];
1051 int totsize = 0;
1053 if (fileid == 1)
1055 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1056 = DST_K_SOURCE_CORR_HEADER_SIZE + 1 - 1;
1057 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1058 = DST_K_SOURCE;
1059 src_command.dst_b_src_command = DST_K_SRC_FORMFEED;
1061 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1062 "source corr", dosizeonly);
1064 totsize += write_debug_data1 (src_command.dst_b_src_command,
1065 "source_corr (SRC FORMFEED)",
1066 dosizeonly);
1069 src_command_size
1070 = DST_K_SRC_COMMAND_SIZE + flen + DST_K_SRC_CMDTRLR_SIZE;
1071 src_command.dst_b_src_command = DST_K_SRC_DECLFILE;
1072 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_length
1073 = src_command_size - 2;
1074 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_flags = 0;
1075 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_fileid
1076 = fileid;
1077 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt
1078 = file_info_entry.cdt;
1079 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk
1080 = file_info_entry.ebk;
1081 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_rms_ffb
1082 = file_info_entry.ffb;
1083 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_rms_rfo
1084 = file_info_entry.rfo;
1085 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename
1086 = file_info_entry.flen;
1088 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1089 = DST_K_SOURCE_CORR_HEADER_SIZE + src_command_size - 1;
1090 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1091 = DST_K_SOURCE;
1093 src_cmdtrlr.dst_b_src_df_libmodname = 0;
1095 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1096 "source corr", dosizeonly);
1097 totsize += write_debug_data1 (src_command.dst_b_src_command,
1098 "source_corr (DECL SRC FILE)", dosizeonly);
1099 totsize += write_debug_data1
1100 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_length,
1101 "source_corr (length)", dosizeonly);
1103 totsize += write_debug_data1
1104 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_flags,
1105 "source_corr (flags)", dosizeonly);
1107 totsize += write_debug_data2
1108 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_fileid,
1109 "source_corr (fileid)", dosizeonly);
1111 totsize += write_debug_data8
1112 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt,
1113 "source_corr (creation date)", dosizeonly);
1115 totsize += write_debug_data4
1116 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk,
1117 "source_corr (EOF block number)", dosizeonly);
1119 totsize += write_debug_data2
1120 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_rms_ffb,
1121 "source_corr (first free byte)", dosizeonly);
1123 totsize += write_debug_data1
1124 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_rms_rfo,
1125 "source_corr (record and file organization)", dosizeonly);
1127 totsize += write_debug_data1
1128 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename,
1129 "source_corr (filename length)", dosizeonly);
1131 totsize += write_debug_string (file_info_entry.file_name,
1132 "source file name", dosizeonly);
1133 totsize += write_debug_data1 (src_cmdtrlr.dst_b_src_df_libmodname,
1134 "source_corr (libmodname)", dosizeonly);
1136 src_command_sf.dst_b_src_command = DST_K_SRC_SETFILE;
1137 src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword = fileid;
1139 src_command_sr.dst_b_src_command = DST_K_SRC_SETREC_W;
1140 src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword = 1;
1142 src_command_sl.dst_b_src_command = DST_K_SRC_SETLNUM_L;
1143 src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong = linestart + 1;
1145 src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W;
1147 if (linesleft > 65534)
1148 linesleft = linesleft - 65534, linestodo = 65534;
1149 else
1150 linestodo = linesleft, linesleft = 0;
1152 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo;
1154 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1155 = DST_K_SOURCE_CORR_HEADER_SIZE + 3 + 3 + 5 + 3 - 1;
1156 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1157 = DST_K_SOURCE;
1159 if (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword)
1161 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1162 "source corr", dosizeonly);
1164 totsize += write_debug_data1 (src_command_sf.dst_b_src_command,
1165 "source_corr (src setfile)", dosizeonly);
1167 totsize += write_debug_data2
1168 (src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword,
1169 "source_corr (fileid)", dosizeonly);
1171 totsize += write_debug_data1 (src_command_sr.dst_b_src_command,
1172 "source_corr (setrec)", dosizeonly);
1174 totsize += write_debug_data2
1175 (src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword,
1176 "source_corr (recnum)", dosizeonly);
1178 totsize += write_debug_data1 (src_command_sl.dst_b_src_command,
1179 "source_corr (setlnum)", dosizeonly);
1181 totsize += write_debug_data4
1182 (src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong,
1183 "source_corr (linenum)", dosizeonly);
1185 totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
1186 "source_corr (deflines)", dosizeonly);
1188 sprintf (buff, "source_corr (%d)",
1189 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
1190 totsize += write_debug_data2
1191 (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword,
1192 buff, dosizeonly);
1194 while (linesleft > 0)
1196 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1197 = DST_K_SOURCE_CORR_HEADER_SIZE + 3 - 1;
1198 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1199 = DST_K_SOURCE;
1200 src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W;
1202 if (linesleft > 65534)
1203 linesleft = linesleft - 65534, linestodo = 65534;
1204 else
1205 linestodo = linesleft, linesleft = 0;
1207 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo;
1209 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1210 "source corr", dosizeonly);
1211 totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
1212 "source_corr (deflines)", dosizeonly);
1213 sprintf (buff, "source_corr (%d)",
1214 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
1215 totsize += write_debug_data2
1216 (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword,
1217 buff, dosizeonly);
1221 return totsize;
1224 /* Output all the source correlation entries and return the size. Just return
1225 the size if DOSIZEONLY is nonzero. */
1227 static int
1228 write_srccorrs (int dosizeonly)
1230 unsigned int i;
1231 int totsize = 0;
1233 for (i = 1; i < file_info_table_in_use; i++)
1234 totsize += write_srccorr (i, file_info_table[i], dosizeonly);
1236 return totsize;
1239 /* Output a marker (i.e. a label) for the beginning of a function, before
1240 the prologue. */
1242 static void
1243 vmsdbgout_begin_prologue (unsigned int line, const char *file)
1245 char label[MAX_ARTIFICIAL_LABEL_BYTES];
1247 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1248 (*dwarf2_debug_hooks.begin_prologue) (line, file);
1250 if (debug_info_level > DINFO_LEVEL_NONE)
1252 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL,
1253 current_function_funcdef_no);
1254 ASM_OUTPUT_LABEL (asm_out_file, label);
1258 /* Output a marker (i.e. a label) for the beginning of a function, after
1259 the prologue. */
1261 static void
1262 vmsdbgout_end_prologue (unsigned int line, const char *file)
1264 char label[MAX_ARTIFICIAL_LABEL_BYTES];
1266 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1267 (*dwarf2_debug_hooks.end_prologue) (line, file);
1269 if (debug_info_level > DINFO_LEVEL_TERSE)
1271 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL,
1272 current_function_funcdef_no);
1273 ASM_OUTPUT_LABEL (asm_out_file, label);
1275 /* VMS PCA expects every PC range to correlate to some line and file. */
1276 vmsdbgout_source_line (line, file);
1280 /* No output for VMS debug, but make obligatory call to Dwarf2 debug */
1282 static void
1283 vmsdbgout_end_function (unsigned int line)
1285 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1286 (*dwarf2_debug_hooks.end_function) (line);
1289 /* Output a marker (i.e. a label) for the absolute end of the generated code
1290 for a function definition. This gets called *after* the epilogue code has
1291 been generated. */
1293 static void
1294 vmsdbgout_end_epilogue (unsigned int line, const char *file)
1296 char label[MAX_ARTIFICIAL_LABEL_BYTES];
1298 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1299 (*dwarf2_debug_hooks.end_epilogue) (line, file);
1301 if (debug_info_level > DINFO_LEVEL_NONE)
1303 /* Output a label to mark the endpoint of the code generated for this
1304 function. */
1305 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL,
1306 current_function_funcdef_no);
1307 ASM_OUTPUT_LABEL (asm_out_file, label);
1309 /* VMS PCA expects every PC range to correlate to some line and file. */
1310 vmsdbgout_source_line (line, file);
1314 /* Output a marker (i.e. a label) for the beginning of the generated code for
1315 a lexical block. */
1317 static void
1318 vmsdbgout_begin_block (register unsigned line, register unsigned blocknum)
1320 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1321 (*dwarf2_debug_hooks.begin_block) (line, blocknum);
1323 if (debug_info_level > DINFO_LEVEL_TERSE)
1324 (*targetm.asm_out.internal_label) (asm_out_file, BLOCK_BEGIN_LABEL, blocknum);
1327 /* Output a marker (i.e. a label) for the end of the generated code for a
1328 lexical block. */
1330 static void
1331 vmsdbgout_end_block (register unsigned line, register unsigned blocknum)
1333 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1334 (*dwarf2_debug_hooks.end_block) (line, blocknum);
1336 if (debug_info_level > DINFO_LEVEL_TERSE)
1337 (*targetm.asm_out.internal_label) (asm_out_file, BLOCK_END_LABEL, blocknum);
1340 /* Not implemented in VMS Debug. */
1342 static bool
1343 vmsdbgout_ignore_block (tree block)
1345 bool retval = 0;
1347 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1348 retval = (*dwarf2_debug_hooks.ignore_block) (block);
1350 return retval;
1353 /* Add an entry for function DECL into the func_table. */
1355 static void
1356 vmsdbgout_begin_function (tree decl)
1358 const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
1360 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1361 (*dwarf2_debug_hooks.begin_function) (decl);
1363 if (func_table_in_use == func_table_allocated)
1365 func_table_allocated += FUNC_TABLE_INCREMENT;
1366 func_table = xrealloc (func_table,
1367 func_table_allocated * sizeof (char *));
1370 /* Add the new entry to the end of the function name table. */
1371 func_table[func_table_in_use++] = xstrdup (name);
1374 static char fullname_buff [4096];
1376 /* Return the full file specification for FILENAME. The specification must be
1377 in VMS syntax in order to be processed by VMS Debug. */
1379 static char *
1380 full_name (const char *filename)
1382 #ifdef VMS
1383 FILE *fp = fopen (filename, "r");
1385 fgetname (fp, fullname_buff, 1);
1386 fclose (fp);
1387 #else
1388 getcwd (fullname_buff, sizeof (fullname_buff));
1390 strcat (fullname_buff, "/");
1391 strcat (fullname_buff, filename);
1393 /* ??? Insert hairy code here to translate Unix style file specification
1394 to VMS style. */
1395 #endif
1397 return fullname_buff;
1400 /* Lookup a filename (in the list of filenames that we know about here in
1401 vmsdbgout.c) and return its "index". The index of each (known) filename is
1402 just a unique number which is associated with only that one filename. We
1403 need such numbers for the sake of generating labels and references
1404 to those files numbers. If the filename given as an argument is not
1405 found in our current list, add it to the list and assign it the next
1406 available unique index number. In order to speed up searches, we remember
1407 the index of the filename was looked up last. This handles the majority of
1408 all searches. */
1410 static unsigned int
1411 lookup_filename (const char *file_name)
1413 static unsigned int last_file_lookup_index = 0;
1414 register char *fn;
1415 register unsigned i;
1416 char *fnam;
1417 long long cdt;
1418 long ebk;
1419 short ffb;
1420 char rfo;
1421 char flen;
1422 struct stat statbuf;
1424 if (stat (file_name, &statbuf) == 0)
1426 long gmtoff;
1427 #ifdef VMS
1428 struct tm *ts;
1430 /* Adjust for GMT. */
1431 ts = (struct tm *) localtime (&statbuf.st_ctime);
1432 gmtoff = ts->tm_gmtoff;
1434 /* VMS has multiple file format types. */
1435 rfo = statbuf.st_fab_rfm;
1436 #else
1437 /* Is GMT adjustment an issue with a cross-compiler? */
1438 gmtoff = 0;
1440 /* Assume stream LF type file. */
1441 rfo = 2;
1442 #endif
1443 cdt = 10000000 * (statbuf.st_ctime + gmtoff + vms_epoch_offset);
1444 ebk = statbuf.st_size / 512 + 1;
1445 ffb = statbuf.st_size - ((statbuf.st_size / 512) * 512);
1446 fnam = full_name (file_name);
1447 flen = strlen (fnam);
1449 else
1451 cdt = 0;
1452 ebk = 0;
1453 ffb = 0;
1454 rfo = 0;
1455 fnam = (char *) "";
1456 flen = 0;
1459 /* Check to see if the file name that was searched on the previous call
1460 matches this file name. If so, return the index. */
1461 if (last_file_lookup_index != 0)
1463 fn = file_info_table[last_file_lookup_index].file_name;
1464 if (strcmp (fnam, fn) == 0)
1465 return last_file_lookup_index;
1468 /* Didn't match the previous lookup, search the table */
1469 for (i = 1; i < file_info_table_in_use; ++i)
1471 fn = file_info_table[i].file_name;
1472 if (strcmp (fnam, fn) == 0)
1474 last_file_lookup_index = i;
1475 return i;
1479 /* Prepare to add a new table entry by making sure there is enough space in
1480 the table to do so. If not, expand the current table. */
1481 if (file_info_table_in_use == file_info_table_allocated)
1484 file_info_table_allocated += FILE_TABLE_INCREMENT;
1485 file_info_table = xrealloc (file_info_table,
1486 (file_info_table_allocated
1487 * sizeof (dst_file_info_entry)));
1490 /* Add the new entry to the end of the filename table. */
1491 file_info_table[file_info_table_in_use].file_name = xstrdup (fnam);
1492 file_info_table[file_info_table_in_use].max_line = 0;
1493 file_info_table[file_info_table_in_use].cdt = cdt;
1494 file_info_table[file_info_table_in_use].ebk = ebk;
1495 file_info_table[file_info_table_in_use].ffb = ffb;
1496 file_info_table[file_info_table_in_use].rfo = rfo;
1497 file_info_table[file_info_table_in_use].flen = flen;
1499 last_file_lookup_index = file_info_table_in_use++;
1500 return last_file_lookup_index;
1503 /* Output a label to mark the beginning of a source code line entry
1504 and record information relating to this source line, in
1505 'line_info_table' for later output of the .debug_line section. */
1507 static void
1508 vmsdbgout_source_line (register unsigned line, register const char *filename)
1510 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1511 (*dwarf2_debug_hooks.source_line) (line, filename);
1513 if (debug_info_level >= DINFO_LEVEL_TERSE)
1515 dst_line_info_ref line_info;
1517 (*targetm.asm_out.internal_label) (asm_out_file, LINE_CODE_LABEL,
1518 line_info_table_in_use);
1520 /* Expand the line info table if necessary. */
1521 if (line_info_table_in_use == line_info_table_allocated)
1523 line_info_table_allocated += LINE_INFO_TABLE_INCREMENT;
1524 line_info_table = xrealloc (line_info_table,
1525 (line_info_table_allocated
1526 * sizeof (dst_line_info_entry)));
1529 /* Add the new entry at the end of the line_info_table. */
1530 line_info = &line_info_table[line_info_table_in_use++];
1531 line_info->dst_file_num = lookup_filename (filename);
1532 line_info->dst_line_num = line;
1533 if (line > file_info_table[line_info->dst_file_num].max_line)
1534 file_info_table[line_info->dst_file_num].max_line = line;
1538 /* Record the beginning of a new source file, for later output.
1539 At present, unimplemented. */
1541 static void
1542 vmsdbgout_start_source_file (unsigned int lineno, const char *filename)
1544 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1545 (*dwarf2_debug_hooks.start_source_file) (lineno, filename);
1548 /* Record the end of a source file, for later output.
1549 At present, unimplemented. */
1551 static void
1552 vmsdbgout_end_source_file (unsigned int lineno ATTRIBUTE_UNUSED)
1554 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1555 (*dwarf2_debug_hooks.end_source_file) (lineno);
1558 /* Set up for Debug output at the start of compilation. */
1560 static void
1561 vmsdbgout_init (const char *main_input_filename)
1563 const char *language_string = lang_hooks.name;
1565 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1566 (*dwarf2_debug_hooks.init) (main_input_filename);
1568 if (debug_info_level == DINFO_LEVEL_NONE)
1569 return;
1571 /* Remember the name of the primary input file. */
1572 primary_filename = main_input_filename;
1574 /* Allocate the initial hunk of the file_info_table. */
1575 file_info_table
1576 = xcalloc (FILE_TABLE_INCREMENT, sizeof (dst_file_info_entry));
1577 file_info_table_allocated = FILE_TABLE_INCREMENT;
1579 /* Skip the first entry - file numbers begin at 1 */
1580 file_info_table_in_use = 1;
1582 func_table = xcalloc (FUNC_TABLE_INCREMENT, sizeof (char *));
1583 func_table_allocated = FUNC_TABLE_INCREMENT;
1584 func_table_in_use = 1;
1586 /* Allocate the initial hunk of the line_info_table. */
1587 line_info_table
1588 = xcalloc (LINE_INFO_TABLE_INCREMENT, sizeof (dst_line_info_entry));
1589 line_info_table_allocated = LINE_INFO_TABLE_INCREMENT;
1590 /* zero-th entry is allocated, but unused */
1591 line_info_table_in_use = 1;
1593 lookup_filename (primary_filename);
1595 if (!strcmp (language_string, "GNU C"))
1596 module_language = DST_K_C;
1597 else if (!strcmp (language_string, "GNU C++"))
1598 module_language = DST_K_CXX;
1599 else if (!strcmp (language_string, "GNU Ada"))
1600 module_language = DST_K_ADA;
1601 else if (!strcmp (language_string, "GNU F77"))
1602 module_language = DST_K_FORTRAN;
1603 else
1604 module_language = DST_K_UNKNOWN;
1606 module_producer = concat (language_string, " ", version_string, NULL);
1608 ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
1612 /* Not implemented in VMS Debug. */
1614 static void
1615 vmsdbgout_define (unsigned int lineno, const char *buffer)
1617 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1618 (*dwarf2_debug_hooks.define) (lineno, buffer);
1621 /* Not implemented in VMS Debug. */
1623 static void
1624 vmsdbgout_undef (unsigned int lineno, const char *buffer)
1626 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1627 (*dwarf2_debug_hooks.undef) (lineno, buffer);
1630 /* Not implemented in VMS Debug. */
1632 static void
1633 vmsdbgout_decl (tree decl)
1635 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1636 (*dwarf2_debug_hooks.function_decl) (decl);
1639 /* Not implemented in VMS Debug. */
1641 static void
1642 vmsdbgout_global_decl (tree decl)
1644 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1645 (*dwarf2_debug_hooks.global_decl) (decl);
1648 /* Not implemented in VMS Debug. */
1650 static void
1651 vmsdbgout_abstract_function (tree decl)
1653 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1654 (*dwarf2_debug_hooks.outlining_inline_function) (decl);
1657 /* Output stuff that Debug requires at the end of every file and generate the
1658 VMS Debug debugging info. */
1660 static void
1661 vmsdbgout_finish (const char *main_input_filename ATTRIBUTE_UNUSED)
1663 unsigned int i;
1664 int totsize;
1666 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1667 (*dwarf2_debug_hooks.finish) (main_input_filename);
1669 if (debug_info_level == DINFO_LEVEL_NONE)
1670 return;
1672 /* Output a terminator label for the .text section. */
1673 text_section ();
1674 (*targetm.asm_out.internal_label) (asm_out_file, TEXT_END_LABEL, 0);
1676 /* Output debugging information.
1677 Warning! Do not change the name of the .vmsdebug section without
1678 changing it in the assembler also. */
1679 named_section (NULL_TREE, ".vmsdebug", 0);
1680 ASM_OUTPUT_ALIGN (asm_out_file, 0);
1682 totsize = write_modbeg (1);
1683 for (i = 1; i < func_table_in_use; i++)
1685 totsize += write_rtnbeg (i, 1);
1686 totsize += write_rtnend (i, 1);
1688 totsize += write_pclines (1);
1690 write_modbeg (0);
1691 for (i = 1; i < func_table_in_use; i++)
1693 write_rtnbeg (i, 0);
1694 write_rtnend (i, 0);
1696 write_pclines (0);
1698 if (debug_info_level > DINFO_LEVEL_TERSE)
1700 totsize = write_srccorrs (1);
1701 write_srccorrs (0);
1704 totsize = write_modend (1);
1705 write_modend (0);
1707 #endif /* VMS_DEBUGGING_INFO */