2004-02-11 Eric Christopher <echristo@redhat.com>
[official-gcc.git] / gcc / vmsdbgout.c
blob5c5634de3444c95ac13fba0776df553023672867
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 */
194 debug_nothing_rtx /* var_location */
197 /* Definitions of defaults for assembler-dependent names of various
198 pseudo-ops and section names.
199 Theses may be overridden in the tm.h file (if necessary) for a particular
200 assembler. */
201 #ifdef UNALIGNED_SHORT_ASM_OP
202 #undef UNALIGNED_SHORT_ASM_OP
203 #endif
204 #define UNALIGNED_SHORT_ASM_OP ".word"
206 #ifdef UNALIGNED_INT_ASM_OP
207 #undef UNALIGNED_INT_ASM_OP
208 #endif
209 #define UNALIGNED_INT_ASM_OP ".long"
211 #ifdef UNALIGNED_LONG_ASM_OP
212 #undef UNALIGNED_LONG_ASM_OP
213 #endif
214 #define UNALIGNED_LONG_ASM_OP ".long"
216 #ifdef UNALIGNED_DOUBLE_INT_ASM_OP
217 #undef UNALIGNED_DOUBLE_INT_ASM_OP
218 #endif
219 #define UNALIGNED_DOUBLE_INT_ASM_OP ".quad"
221 #ifdef ASM_BYTE_OP
222 #undef ASM_BYTE_OP
223 #endif
224 #define ASM_BYTE_OP ".byte"
226 #define NUMBYTES(I) ((I) < 256 ? 1 : (I) < 65536 ? 2 : 4)
228 #define NUMBYTES0(I) ((I) < 128 ? 0 : (I) < 65536 ? 2 : 4)
230 #ifndef UNALIGNED_PTR_ASM_OP
231 #define UNALIGNED_PTR_ASM_OP \
232 (PTR_SIZE == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP : UNALIGNED_INT_ASM_OP)
233 #endif
235 #ifndef UNALIGNED_OFFSET_ASM_OP
236 #define UNALIGNED_OFFSET_ASM_OP(OFFSET) \
237 (NUMBYTES(OFFSET) == 4 \
238 ? UNALIGNED_LONG_ASM_OP \
239 : (NUMBYTES(OFFSET) == 2 ? UNALIGNED_SHORT_ASM_OP : ASM_BYTE_OP))
240 #endif
242 /* Definitions of defaults for formats and names of various special
243 (artificial) labels which may be generated within this file (when the -g
244 options is used and VMS_DEBUGGING_INFO is in effect. If necessary, these
245 may be overridden from within the tm.h file, but typically, overriding these
246 defaults is unnecessary. */
248 static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
250 #ifndef TEXT_END_LABEL
251 #define TEXT_END_LABEL "Lvetext"
252 #endif
253 #ifndef FUNC_BEGIN_LABEL
254 #define FUNC_BEGIN_LABEL "LVFB"
255 #endif
256 #ifndef FUNC_PROLOG_LABEL
257 #define FUNC_PROLOG_LABEL "LVFP"
258 #endif
259 #ifndef FUNC_END_LABEL
260 #define FUNC_END_LABEL "LVFE"
261 #endif
262 #ifndef BLOCK_BEGIN_LABEL
263 #define BLOCK_BEGIN_LABEL "LVBB"
264 #endif
265 #ifndef BLOCK_END_LABEL
266 #define BLOCK_END_LABEL "LVBE"
267 #endif
268 #ifndef LINE_CODE_LABEL
269 #define LINE_CODE_LABEL "LVM"
270 #endif
272 #ifndef ASM_OUTPUT_DEBUG_DELTA2
273 #define ASM_OUTPUT_DEBUG_DELTA2(FILE,LABEL1,LABEL2) \
274 do \
276 fprintf ((FILE), "\t%s\t", UNALIGNED_SHORT_ASM_OP); \
277 assemble_name (FILE, LABEL1); \
278 fprintf (FILE, "-"); \
279 assemble_name (FILE, LABEL2); \
281 while (0)
282 #endif
284 #ifndef ASM_OUTPUT_DEBUG_DELTA4
285 #define ASM_OUTPUT_DEBUG_DELTA4(FILE,LABEL1,LABEL2) \
286 do \
288 fprintf ((FILE), "\t%s\t", UNALIGNED_INT_ASM_OP); \
289 assemble_name (FILE, LABEL1); \
290 fprintf (FILE, "-"); \
291 assemble_name (FILE, LABEL2); \
293 while (0)
294 #endif
296 #ifndef ASM_OUTPUT_DEBUG_ADDR_DELTA
297 #define ASM_OUTPUT_DEBUG_ADDR_DELTA(FILE,LABEL1,LABEL2) \
298 do \
300 fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP); \
301 assemble_name (FILE, LABEL1); \
302 fprintf (FILE, "-"); \
303 assemble_name (FILE, LABEL2); \
305 while (0)
306 #endif
308 #ifndef ASM_OUTPUT_DEBUG_ADDR
309 #define ASM_OUTPUT_DEBUG_ADDR(FILE,LABEL) \
310 do \
312 fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP); \
313 assemble_name (FILE, LABEL); \
315 while (0)
316 #endif
318 #ifndef ASM_OUTPUT_DEBUG_ADDR_CONST
319 #define ASM_OUTPUT_DEBUG_ADDR_CONST(FILE,ADDR) \
320 fprintf ((FILE), "\t%s\t%s", UNALIGNED_PTR_ASM_OP, (ADDR))
321 #endif
323 #ifndef ASM_OUTPUT_DEBUG_DATA1
324 #define ASM_OUTPUT_DEBUG_DATA1(FILE,VALUE) \
325 fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, (unsigned char) VALUE)
326 #endif
328 #ifndef ASM_OUTPUT_DEBUG_DATA2
329 #define ASM_OUTPUT_DEBUG_DATA2(FILE,VALUE) \
330 fprintf ((FILE), "\t%s\t0x%x", UNALIGNED_SHORT_ASM_OP, \
331 (unsigned short) VALUE)
332 #endif
334 #ifndef ASM_OUTPUT_DEBUG_DATA4
335 #define ASM_OUTPUT_DEBUG_DATA4(FILE,VALUE) \
336 fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_INT_ASM_OP, (unsigned long) VALUE)
337 #endif
339 #ifndef ASM_OUTPUT_DEBUG_DATA
340 #define ASM_OUTPUT_DEBUG_DATA(FILE,VALUE) \
341 fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_OFFSET_ASM_OP(VALUE), VALUE)
342 #endif
344 #ifndef ASM_OUTPUT_DEBUG_ADDR_DATA
345 #define ASM_OUTPUT_DEBUG_ADDR_DATA(FILE,VALUE) \
346 fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_PTR_ASM_OP, \
347 (unsigned long) VALUE)
348 #endif
350 #ifndef ASM_OUTPUT_DEBUG_DATA8
351 #define ASM_OUTPUT_DEBUG_DATA8(FILE,VALUE) \
352 fprintf ((FILE), "\t%s\t0x%llx", UNALIGNED_DOUBLE_INT_ASM_OP, \
353 (unsigned long long) VALUE)
354 #endif
356 /* This is similar to the default ASM_OUTPUT_ASCII, except that no trailing
357 newline is produced. When flag_verbose_asm is asserted, we add commentary
358 at the end of the line, so we must avoid output of a newline here. */
359 #ifndef ASM_OUTPUT_DEBUG_STRING
360 #define ASM_OUTPUT_DEBUG_STRING(FILE,P) \
361 do \
363 register int slen = strlen(P); \
364 register char *p = (P); \
365 register int i; \
366 fprintf (FILE, "\t.ascii \""); \
367 for (i = 0; i < slen; i++) \
369 register int c = p[i]; \
370 if (c == '\"' || c == '\\') \
371 putc ('\\', FILE); \
372 if (c >= ' ' && c < 0177) \
373 putc (c, FILE); \
374 else \
375 fprintf (FILE, "\\%o", c); \
377 fprintf (FILE, "\""); \
379 while (0)
380 #endif
382 /* Convert a reference to the assembler name of a C-level name. This
383 macro has the same effect as ASM_OUTPUT_LABELREF, but copies to
384 a string rather than writing to a file. */
385 #ifndef ASM_NAME_TO_STRING
386 #define ASM_NAME_TO_STRING(STR, NAME) \
387 do \
389 if ((NAME)[0] == '*') \
390 strcpy (STR, NAME+1); \
391 else \
392 strcpy (STR, NAME); \
394 while (0)
395 #endif
398 /* General utility functions. */
400 /* Convert an integer constant expression into assembler syntax. Addition and
401 subtraction are the only arithmetic that may appear in these expressions.
402 This is an adaptation of output_addr_const in final.c. Here, the target
403 of the conversion is a string buffer. We can't use output_addr_const
404 directly, because it writes to a file. */
406 static void
407 addr_const_to_string (char *str, rtx x)
409 char buf1[256];
410 char buf2[256];
412 restart:
413 str[0] = '\0';
414 switch (GET_CODE (x))
416 case PC:
417 if (flag_pic)
418 strcat (str, ",");
419 else
420 abort ();
421 break;
423 case SYMBOL_REF:
424 ASM_NAME_TO_STRING (buf1, XSTR (x, 0));
425 strcat (str, buf1);
426 break;
428 case LABEL_REF:
429 ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
430 ASM_NAME_TO_STRING (buf2, buf1);
431 strcat (str, buf2);
432 break;
434 case CODE_LABEL:
435 ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (x));
436 ASM_NAME_TO_STRING (buf2, buf1);
437 strcat (str, buf2);
438 break;
440 case CONST_INT:
441 sprintf (buf1, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
442 strcat (str, buf1);
443 break;
445 case CONST:
446 /* This used to output parentheses around the expression, but that does
447 not work on the 386 (either ATT or BSD assembler). */
448 addr_const_to_string (buf1, XEXP (x, 0));
449 strcat (str, buf1);
450 break;
452 case CONST_DOUBLE:
453 if (GET_MODE (x) == VOIDmode)
455 /* We can use %d if the number is one word and positive. */
456 if (CONST_DOUBLE_HIGH (x))
457 sprintf (buf1, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
458 CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
459 else if (CONST_DOUBLE_LOW (x) < 0)
460 sprintf (buf1, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (x));
461 else
462 sprintf (buf1, HOST_WIDE_INT_PRINT_DEC,
463 CONST_DOUBLE_LOW (x));
464 strcat (str, buf1);
466 else
467 /* We can't handle floating point constants; PRINT_OPERAND must
468 handle them. */
469 output_operand_lossage ("floating constant misused");
470 break;
472 case PLUS:
473 /* Some assemblers need integer constants to appear last (eg masm). */
474 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
476 addr_const_to_string (buf1, XEXP (x, 1));
477 strcat (str, buf1);
478 if (INTVAL (XEXP (x, 0)) >= 0)
479 strcat (str, "+");
480 addr_const_to_string (buf1, XEXP (x, 0));
481 strcat (str, buf1);
483 else
485 addr_const_to_string (buf1, XEXP (x, 0));
486 strcat (str, buf1);
487 if (INTVAL (XEXP (x, 1)) >= 0)
488 strcat (str, "+");
489 addr_const_to_string (buf1, XEXP (x, 1));
490 strcat (str, buf1);
492 break;
494 case MINUS:
495 /* Avoid outputting things like x-x or x+5-x, since some assemblers
496 can't handle that. */
497 x = simplify_subtraction (x);
498 if (GET_CODE (x) != MINUS)
499 goto restart;
501 addr_const_to_string (buf1, XEXP (x, 0));
502 strcat (str, buf1);
503 strcat (str, "-");
504 if (GET_CODE (XEXP (x, 1)) == CONST_INT
505 && INTVAL (XEXP (x, 1)) < 0)
507 strcat (str, "(");
508 addr_const_to_string (buf1, XEXP (x, 1));
509 strcat (str, buf1);
510 strcat (str, ")");
512 else
514 addr_const_to_string (buf1, XEXP (x, 1));
515 strcat (str, buf1);
517 break;
519 case ZERO_EXTEND:
520 case SIGN_EXTEND:
521 addr_const_to_string (buf1, XEXP (x, 0));
522 strcat (str, buf1);
523 break;
525 default:
526 output_operand_lossage ("invalid expression as operand");
530 /* Output the debug header HEADER. Also output COMMENT if flag_verbose_asm is
531 set. Return the header size. Just return the size if DOSIZEONLY is
532 nonzero. */
534 static int
535 write_debug_header (DST_HEADER *header, const char *comment, int dosizeonly)
537 if (!dosizeonly)
539 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file,
540 header->dst__header_length.dst_w_length);
542 if (flag_verbose_asm)
543 fprintf (asm_out_file, "\t%s record length", ASM_COMMENT_START);
544 fputc ('\n', asm_out_file);
546 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file,
547 header->dst__header_type.dst_w_type);
549 if (flag_verbose_asm)
550 fprintf (asm_out_file, "\t%s record type (%s)", ASM_COMMENT_START,
551 comment);
553 fputc ('\n', asm_out_file);
556 return 4;
559 /* Output the address of SYMBOL. Also output COMMENT if flag_verbose_asm is
560 set. Return the address size. Just return the size if DOSIZEONLY is
561 nonzero. */
563 static int
564 write_debug_addr (char *symbol, const char *comment, int dosizeonly)
566 if (!dosizeonly)
568 ASM_OUTPUT_DEBUG_ADDR (asm_out_file, symbol);
569 if (flag_verbose_asm)
570 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
571 fputc ('\n', asm_out_file);
574 return PTR_SIZE;
577 /* Output the single byte DATA1. Also output COMMENT if flag_verbose_asm is
578 set. Return the data size. Just return the size if DOSIZEONLY is
579 nonzero. */
581 static int
582 write_debug_data1 (unsigned int data1, const char *comment, int dosizeonly)
584 if (!dosizeonly)
586 ASM_OUTPUT_DEBUG_DATA1 (asm_out_file, data1);
587 if (flag_verbose_asm)
588 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
589 fputc ('\n', asm_out_file);
592 return 1;
595 /* Output the single word DATA2. Also output COMMENT if flag_verbose_asm is
596 set. Return the data size. Just return the size if DOSIZEONLY is
597 nonzero. */
599 static int
600 write_debug_data2 (unsigned int data2, const char *comment, int dosizeonly)
602 if (!dosizeonly)
604 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file, data2);
605 if (flag_verbose_asm)
606 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
607 fputc ('\n', asm_out_file);
610 return 2;
613 /* Output double word DATA4. Also output COMMENT if flag_verbose_asm is set.
614 Return the data size. Just return the size if DOSIZEONLY is nonzero. */
616 static int
617 write_debug_data4 (unsigned long data4, const char *comment, int dosizeonly)
619 if (!dosizeonly)
621 ASM_OUTPUT_DEBUG_DATA4 (asm_out_file, data4);
622 if (flag_verbose_asm)
623 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
624 fputc ('\n', asm_out_file);
627 return 4;
630 /* Output quad word DATA8. Also output COMMENT if flag_verbose_asm is set.
631 Return the data size. Just return the size if DOSIZEONLY is nonzero. */
633 static int
634 write_debug_data8 (unsigned long long data8, const char *comment,
635 int dosizeonly)
637 if (!dosizeonly)
639 ASM_OUTPUT_DEBUG_DATA8 (asm_out_file, data8);
640 if (flag_verbose_asm)
641 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
642 fputc ('\n', asm_out_file);
645 return 8;
648 /* Output the difference between LABEL1 and LABEL2. Also output COMMENT if
649 flag_verbose_asm is set. Return the data size. Just return the size if
650 DOSIZEONLY is nonzero. */
652 static int
653 write_debug_delta4 (char *label1, char *label2, const char *comment,
654 int dosizeonly)
656 if (!dosizeonly)
658 ASM_OUTPUT_DEBUG_DELTA4 (asm_out_file, label1, label2);
659 if (flag_verbose_asm)
660 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
661 fputc ('\n', asm_out_file);
664 return 4;
667 /* Output a character string STRING. Also write COMMENT if flag_verbose_asm is
668 set. Return the string length. Just return the length if DOSIZEONLY is
669 nonzero. */
671 static int
672 write_debug_string (char *string, const char *comment, int dosizeonly)
674 if (!dosizeonly)
676 ASM_OUTPUT_DEBUG_STRING (asm_out_file, string);
677 if (flag_verbose_asm)
678 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
679 fputc ('\n', asm_out_file);
682 return strlen (string);
685 /* Output a module begin header and return the header size. Just return the
686 size if DOSIZEONLY is nonzero. */
688 static int
689 write_modbeg (int dosizeonly)
691 DST_MODULE_BEGIN modbeg;
692 DST_MB_TRLR mb_trlr;
693 int i;
694 char *module_name, *m;
695 int modnamelen;
696 int prodnamelen;
697 int totsize = 0;
699 /* Assumes primary filename has Unix syntax file spec. */
700 module_name = xstrdup (basename ((char *) primary_filename));
702 m = strrchr (module_name, '.');
703 if (m)
704 *m = 0;
706 modnamelen = strlen (module_name);
707 for (i = 0; i < modnamelen; i++)
708 module_name[i] = TOUPPER (module_name[i]);
710 prodnamelen = strlen (module_producer);
712 modbeg.dst_a_modbeg_header.dst__header_length.dst_w_length
713 = DST_K_MODBEG_SIZE + modnamelen + DST_K_MB_TRLR_SIZE + prodnamelen - 1;
714 modbeg.dst_a_modbeg_header.dst__header_type.dst_w_type = DST_K_MODBEG;
715 modbeg.dst_b_modbeg_flags.dst_v_modbeg_hide = 0;
716 modbeg.dst_b_modbeg_flags.dst_v_modbeg_version = 1;
717 modbeg.dst_b_modbeg_flags.dst_v_modbeg_unused = 0;
718 modbeg.dst_b_modbeg_unused = 0;
719 modbeg.dst_l_modbeg_language = module_language;
720 modbeg.dst_w_version_major = DST_K_VERSION_MAJOR;
721 modbeg.dst_w_version_minor = DST_K_VERSION_MINOR;
722 modbeg.dst_b_modbeg_name = strlen (module_name);
724 mb_trlr.dst_b_compiler = strlen (module_producer);
726 totsize += write_debug_header (&modbeg.dst_a_modbeg_header,
727 "modbeg", dosizeonly);
728 totsize += write_debug_data1 (*((char *) &modbeg.dst_b_modbeg_flags),
729 "flags", dosizeonly);
730 totsize += write_debug_data1 (modbeg.dst_b_modbeg_unused,
731 "unused", dosizeonly);
732 totsize += write_debug_data4 (modbeg.dst_l_modbeg_language,
733 "language", dosizeonly);
734 totsize += write_debug_data2 (modbeg.dst_w_version_major,
735 "DST major version", dosizeonly);
736 totsize += write_debug_data2 (modbeg.dst_w_version_minor,
737 "DST minor version", dosizeonly);
738 totsize += write_debug_data1 (modbeg.dst_b_modbeg_name,
739 "length of module name", dosizeonly);
740 totsize += write_debug_string (module_name, "module name", dosizeonly);
741 totsize += write_debug_data1 (mb_trlr.dst_b_compiler,
742 "length of compiler name", dosizeonly);
743 totsize += write_debug_string (module_producer, "compiler name", dosizeonly);
745 return totsize;
748 /* Output a module end trailer and return the trailer size. Just return
749 the size if DOSIZEONLY is nonzero. */
751 static int
752 write_modend (int dosizeonly)
754 DST_MODULE_END modend;
755 int totsize = 0;
757 modend.dst_a_modend_header.dst__header_length.dst_w_length
758 = DST_K_MODEND_SIZE - 1;
759 modend.dst_a_modend_header.dst__header_type.dst_w_type = DST_K_MODEND;
761 totsize += write_debug_header (&modend.dst_a_modend_header, "modend",
762 dosizeonly);
764 return totsize;
767 /* Output a routine begin header routine RTNNUM and return the header size.
768 Just return the size if DOSIZEONLY is nonzero. */
770 static int
771 write_rtnbeg (int rtnnum, int dosizeonly)
773 char *rtnname;
774 int rtnnamelen;
775 char *rtnentryname;
776 int totsize = 0;
777 char label[MAX_ARTIFICIAL_LABEL_BYTES];
778 DST_ROUTINE_BEGIN rtnbeg;
779 DST_PROLOG prolog;
781 rtnname = func_table[rtnnum];
782 rtnnamelen = strlen (rtnname);
783 rtnentryname = concat (rtnname, "..en", NULL);
785 if (!strcmp (rtnname, "main"))
787 DST_HEADER header;
788 const char *go = "TRANSFER$BREAK$GO";
790 /* This command isn't documented in DSTRECORDS, so it's made to
791 look like what DEC C does */
793 /* header size - 1st byte + flag byte + STO_LW size
794 + string count byte + string length */
795 header.dst__header_length.dst_w_length
796 = DST_K_DST_HEADER_SIZE - 1 + 1 + 4 + 1 + strlen (go);
797 header.dst__header_type.dst_w_type = 0x17;
799 totsize += write_debug_header (&header, "transfer", dosizeonly);
801 /* I think this is a flag byte, but I don't know what this flag means */
802 totsize += write_debug_data1 (0x1, "flags ???", dosizeonly);
804 /* Routine Begin PD Address */
805 totsize += write_debug_addr (rtnname, "main procedure descriptor",
806 dosizeonly);
807 totsize += write_debug_data1 (strlen (go), "length of main_name",
808 dosizeonly);
809 totsize += write_debug_string ((char *) go, "main name", dosizeonly);
812 /* The header length never includes the length byte. */
813 rtnbeg.dst_a_rtnbeg_header.dst__header_length.dst_w_length
814 = DST_K_RTNBEG_SIZE + rtnnamelen - 1;
815 rtnbeg.dst_a_rtnbeg_header.dst__header_type.dst_w_type = DST_K_RTNBEG;
816 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_unused = 0;
817 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_unalloc = 0;
818 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_prototype = 0;
819 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_inlined = 0;
820 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_no_call = 1;
821 rtnbeg.dst_b_rtnbeg_name = rtnnamelen;
823 totsize += write_debug_header (&rtnbeg.dst_a_rtnbeg_header, "rtnbeg",
824 dosizeonly);
825 totsize += write_debug_data1 (*((char *) &rtnbeg.dst_b_rtnbeg_flags),
826 "flags", dosizeonly);
828 /* Routine Begin Address */
829 totsize += write_debug_addr (rtnentryname, "routine entry name", dosizeonly);
831 /* Routine Begin PD Address */
832 totsize += write_debug_addr (rtnname, "routine procedure descriptor",
833 dosizeonly);
835 /* Routine Begin Name */
836 totsize += write_debug_data1 (rtnbeg.dst_b_rtnbeg_name,
837 "length of routine name", dosizeonly);
839 totsize += write_debug_string (rtnname, "routine name", dosizeonly);
841 free (rtnentryname);
843 if (debug_info_level > DINFO_LEVEL_TERSE)
845 prolog.dst_a_prolog_header.dst__header_length.dst_w_length
846 = DST_K_PROLOG_SIZE - 1;
847 prolog.dst_a_prolog_header.dst__header_type.dst_w_type = DST_K_PROLOG;
849 totsize += write_debug_header (&prolog.dst_a_prolog_header, "prolog",
850 dosizeonly);
852 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL, rtnnum);
853 totsize += write_debug_addr (label, "prolog breakpoint addr",
854 dosizeonly);
857 return totsize;
860 /* Output a routine end trailer for routine RTNNUM and return the header size.
861 Just return the size if DOSIZEONLY is nonzero. */
863 static int
864 write_rtnend (int rtnnum, int dosizeonly)
866 DST_ROUTINE_END rtnend;
867 char label1[MAX_ARTIFICIAL_LABEL_BYTES];
868 char label2[MAX_ARTIFICIAL_LABEL_BYTES];
869 int totsize;
871 totsize = 0;
873 rtnend.dst_a_rtnend_header.dst__header_length.dst_w_length
874 = DST_K_RTNEND_SIZE - 1;
875 rtnend.dst_a_rtnend_header.dst__header_type.dst_w_type = DST_K_RTNEND;
876 rtnend.dst_b_rtnend_unused = 0;
877 rtnend.dst_l_rtnend_size = 0; /* Calculated below. */
879 totsize += write_debug_header (&rtnend.dst_a_rtnend_header, "rtnend",
880 dosizeonly);
881 totsize += write_debug_data1 (rtnend.dst_b_rtnend_unused, "unused",
882 dosizeonly);
884 ASM_GENERATE_INTERNAL_LABEL (label1, FUNC_BEGIN_LABEL, rtnnum);
885 ASM_GENERATE_INTERNAL_LABEL (label2, FUNC_END_LABEL, rtnnum);
886 totsize += write_debug_delta4 (label2, label1, "routine size", dosizeonly);
888 return totsize;
891 #define K_DELTA_PC(I) \
892 ((I) < 128 ? -(I) : (I) < 65536 ? DST_K_DELTA_PC_W : DST_K_DELTA_PC_L)
894 #define K_SET_LINUM(I) \
895 ((I) < 256 ? DST_K_SET_LINUM_B \
896 : (I) < 65536 ? DST_K_SET_LINUM : DST_K_SET_LINUM_L)
898 #define K_INCR_LINUM(I) \
899 ((I) < 256 ? DST_K_INCR_LINUM \
900 : (I) < 65536 ? DST_K_INCR_LINUM_W : DST_K_INCR_LINUM_L)
902 /* Output the PC to line number correlations and return the size. Just return
903 the size if DOSIZEONLY is nonzero */
905 static int
906 write_pclines (int dosizeonly)
908 unsigned i;
909 int fn;
910 int ln, lastln;
911 int linestart = 0;
912 int max_line;
913 DST_LINE_NUM_HEADER line_num;
914 DST_PCLINE_COMMANDS pcline;
915 char label[MAX_ARTIFICIAL_LABEL_BYTES];
916 char lastlabel[MAX_ARTIFICIAL_LABEL_BYTES];
917 int totsize = 0;
918 char buff[256];
920 max_line = file_info_table[1].max_line;
921 file_info_table[1].listing_line_start = linestart;
922 linestart = linestart + ((max_line / 100000) + 1) * 100000;
924 for (i = 2; i < file_info_table_in_use; i++)
926 max_line = file_info_table[i].max_line;
927 file_info_table[i].listing_line_start = linestart;
928 linestart = linestart + ((max_line / 10000) + 1) * 10000;
931 /* Set starting address to beginning of text section. */
932 line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 8;
933 line_num.dst_a_line_num_header.dst__header_type.dst_w_type = DST_K_LINE_NUM;
934 pcline.dst_b_pcline_command = DST_K_SET_ABS_PC;
936 totsize += write_debug_header (&line_num.dst_a_line_num_header,
937 "line_num", dosizeonly);
938 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
939 "line_num (SET ABS PC)", dosizeonly);
941 if (dosizeonly)
942 totsize += 4;
943 else
945 ASM_OUTPUT_DEBUG_ADDR (asm_out_file, TEXT_SECTION_ASM_OP);
946 if (flag_verbose_asm)
947 fprintf (asm_out_file, "\t%s line_num", ASM_COMMENT_START);
948 fputc ('\n', asm_out_file);
951 fn = line_info_table[1].dst_file_num;
952 ln = (file_info_table[fn].listing_line_start
953 + line_info_table[1].dst_line_num);
954 line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 4 + 4;
955 pcline.dst_b_pcline_command = DST_K_SET_LINUM_L;
957 totsize += write_debug_header (&line_num.dst_a_line_num_header,
958 "line_num", dosizeonly);
959 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
960 "line_num (SET LINUM LONG)", dosizeonly);
962 sprintf (buff, "line_num (%d)", ln ? ln - 1 : 0);
963 totsize += write_debug_data4 (ln ? ln - 1 : 0, buff, dosizeonly);
965 lastln = ln;
966 strcpy (lastlabel, TEXT_SECTION_ASM_OP);
967 for (i = 1; i < line_info_table_in_use; i++)
969 int extrabytes;
971 fn = line_info_table[i].dst_file_num;
972 ln = (file_info_table[fn].listing_line_start
973 + line_info_table[i].dst_line_num);
975 if (ln - lastln > 1)
976 extrabytes = 5; /* NUMBYTES (ln - lastln - 1) + 1; */
977 else if (ln <= lastln)
978 extrabytes = 5; /* NUMBYTES (ln - 1) + 1; */
979 else
980 extrabytes = 0;
982 line_num.dst_a_line_num_header.dst__header_length.dst_w_length
983 = 8 + extrabytes;
985 totsize += write_debug_header
986 (&line_num.dst_a_line_num_header, "line_num", dosizeonly);
988 if (ln - lastln > 1)
990 int lndif = ln - lastln - 1;
992 /* K_INCR_LINUM (lndif); */
993 pcline.dst_b_pcline_command = DST_K_INCR_LINUM_L;
995 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
996 "line_num (INCR LINUM LONG)",
997 dosizeonly);
999 sprintf (buff, "line_num (%d)", lndif);
1000 totsize += write_debug_data4 (lndif, buff, dosizeonly);
1002 else if (ln <= lastln)
1004 /* K_SET_LINUM (ln-1); */
1005 pcline.dst_b_pcline_command = DST_K_SET_LINUM_L;
1007 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
1008 "line_num (SET LINUM LONG)",
1009 dosizeonly);
1011 sprintf (buff, "line_num (%d)", ln - 1);
1012 totsize += write_debug_data4 (ln - 1, buff, dosizeonly);
1015 pcline.dst_b_pcline_command = DST_K_DELTA_PC_L;
1017 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
1018 "line_num (DELTA PC LONG)", dosizeonly);
1020 ASM_GENERATE_INTERNAL_LABEL (label, LINE_CODE_LABEL, i);
1021 totsize += write_debug_delta4 (label, lastlabel, "increment line_num",
1022 dosizeonly);
1024 lastln = ln;
1025 strcpy (lastlabel, label);
1028 return totsize;
1031 /* Output a source correlation for file FILEID using information saved in
1032 FILE_INFO_ENTRY and return the size. Just return the size if DOSIZEONLY is
1033 nonzero. */
1035 static int
1036 write_srccorr (int fileid, dst_file_info_entry file_info_entry,
1037 int dosizeonly)
1039 int src_command_size;
1040 int linesleft = file_info_entry.max_line;
1041 int linestart = file_info_entry.listing_line_start;
1042 int flen = file_info_entry.flen;
1043 int linestodo = 0;
1044 DST_SOURCE_CORR src_header;
1045 DST_SRC_COMMAND src_command;
1046 DST_SRC_COMMAND src_command_sf;
1047 DST_SRC_COMMAND src_command_sl;
1048 DST_SRC_COMMAND src_command_sr;
1049 DST_SRC_COMMAND src_command_dl;
1050 DST_SRC_CMDTRLR src_cmdtrlr;
1051 char buff[256];
1052 int totsize = 0;
1054 if (fileid == 1)
1056 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1057 = DST_K_SOURCE_CORR_HEADER_SIZE + 1 - 1;
1058 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1059 = DST_K_SOURCE;
1060 src_command.dst_b_src_command = DST_K_SRC_FORMFEED;
1062 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1063 "source corr", dosizeonly);
1065 totsize += write_debug_data1 (src_command.dst_b_src_command,
1066 "source_corr (SRC FORMFEED)",
1067 dosizeonly);
1070 src_command_size
1071 = DST_K_SRC_COMMAND_SIZE + flen + DST_K_SRC_CMDTRLR_SIZE;
1072 src_command.dst_b_src_command = DST_K_SRC_DECLFILE;
1073 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_length
1074 = src_command_size - 2;
1075 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_flags = 0;
1076 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_fileid
1077 = fileid;
1078 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt
1079 = file_info_entry.cdt;
1080 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk
1081 = file_info_entry.ebk;
1082 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_rms_ffb
1083 = file_info_entry.ffb;
1084 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_rms_rfo
1085 = file_info_entry.rfo;
1086 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename
1087 = file_info_entry.flen;
1089 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1090 = DST_K_SOURCE_CORR_HEADER_SIZE + src_command_size - 1;
1091 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1092 = DST_K_SOURCE;
1094 src_cmdtrlr.dst_b_src_df_libmodname = 0;
1096 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1097 "source corr", dosizeonly);
1098 totsize += write_debug_data1 (src_command.dst_b_src_command,
1099 "source_corr (DECL SRC FILE)", dosizeonly);
1100 totsize += write_debug_data1
1101 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_length,
1102 "source_corr (length)", dosizeonly);
1104 totsize += write_debug_data1
1105 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_flags,
1106 "source_corr (flags)", dosizeonly);
1108 totsize += write_debug_data2
1109 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_fileid,
1110 "source_corr (fileid)", dosizeonly);
1112 totsize += write_debug_data8
1113 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt,
1114 "source_corr (creation date)", dosizeonly);
1116 totsize += write_debug_data4
1117 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk,
1118 "source_corr (EOF block number)", dosizeonly);
1120 totsize += write_debug_data2
1121 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_rms_ffb,
1122 "source_corr (first free byte)", dosizeonly);
1124 totsize += write_debug_data1
1125 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_rms_rfo,
1126 "source_corr (record and file organization)", dosizeonly);
1128 totsize += write_debug_data1
1129 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename,
1130 "source_corr (filename length)", dosizeonly);
1132 totsize += write_debug_string (file_info_entry.file_name,
1133 "source file name", dosizeonly);
1134 totsize += write_debug_data1 (src_cmdtrlr.dst_b_src_df_libmodname,
1135 "source_corr (libmodname)", dosizeonly);
1137 src_command_sf.dst_b_src_command = DST_K_SRC_SETFILE;
1138 src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword = fileid;
1140 src_command_sr.dst_b_src_command = DST_K_SRC_SETREC_W;
1141 src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword = 1;
1143 src_command_sl.dst_b_src_command = DST_K_SRC_SETLNUM_L;
1144 src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong = linestart + 1;
1146 src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W;
1148 if (linesleft > 65534)
1149 linesleft = linesleft - 65534, linestodo = 65534;
1150 else
1151 linestodo = linesleft, linesleft = 0;
1153 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo;
1155 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1156 = DST_K_SOURCE_CORR_HEADER_SIZE + 3 + 3 + 5 + 3 - 1;
1157 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1158 = DST_K_SOURCE;
1160 if (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword)
1162 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1163 "source corr", dosizeonly);
1165 totsize += write_debug_data1 (src_command_sf.dst_b_src_command,
1166 "source_corr (src setfile)", dosizeonly);
1168 totsize += write_debug_data2
1169 (src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword,
1170 "source_corr (fileid)", dosizeonly);
1172 totsize += write_debug_data1 (src_command_sr.dst_b_src_command,
1173 "source_corr (setrec)", dosizeonly);
1175 totsize += write_debug_data2
1176 (src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword,
1177 "source_corr (recnum)", dosizeonly);
1179 totsize += write_debug_data1 (src_command_sl.dst_b_src_command,
1180 "source_corr (setlnum)", dosizeonly);
1182 totsize += write_debug_data4
1183 (src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong,
1184 "source_corr (linenum)", dosizeonly);
1186 totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
1187 "source_corr (deflines)", dosizeonly);
1189 sprintf (buff, "source_corr (%d)",
1190 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
1191 totsize += write_debug_data2
1192 (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword,
1193 buff, dosizeonly);
1195 while (linesleft > 0)
1197 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1198 = DST_K_SOURCE_CORR_HEADER_SIZE + 3 - 1;
1199 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1200 = DST_K_SOURCE;
1201 src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W;
1203 if (linesleft > 65534)
1204 linesleft = linesleft - 65534, linestodo = 65534;
1205 else
1206 linestodo = linesleft, linesleft = 0;
1208 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo;
1210 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1211 "source corr", dosizeonly);
1212 totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
1213 "source_corr (deflines)", dosizeonly);
1214 sprintf (buff, "source_corr (%d)",
1215 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
1216 totsize += write_debug_data2
1217 (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword,
1218 buff, dosizeonly);
1222 return totsize;
1225 /* Output all the source correlation entries and return the size. Just return
1226 the size if DOSIZEONLY is nonzero. */
1228 static int
1229 write_srccorrs (int dosizeonly)
1231 unsigned int i;
1232 int totsize = 0;
1234 for (i = 1; i < file_info_table_in_use; i++)
1235 totsize += write_srccorr (i, file_info_table[i], dosizeonly);
1237 return totsize;
1240 /* Output a marker (i.e. a label) for the beginning of a function, before
1241 the prologue. */
1243 static void
1244 vmsdbgout_begin_prologue (unsigned int line, const char *file)
1246 char label[MAX_ARTIFICIAL_LABEL_BYTES];
1248 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1249 (*dwarf2_debug_hooks.begin_prologue) (line, file);
1251 if (debug_info_level > DINFO_LEVEL_NONE)
1253 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL,
1254 current_function_funcdef_no);
1255 ASM_OUTPUT_LABEL (asm_out_file, label);
1259 /* Output a marker (i.e. a label) for the beginning of a function, after
1260 the prologue. */
1262 static void
1263 vmsdbgout_end_prologue (unsigned int line, const char *file)
1265 char label[MAX_ARTIFICIAL_LABEL_BYTES];
1267 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1268 (*dwarf2_debug_hooks.end_prologue) (line, file);
1270 if (debug_info_level > DINFO_LEVEL_TERSE)
1272 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL,
1273 current_function_funcdef_no);
1274 ASM_OUTPUT_LABEL (asm_out_file, label);
1276 /* VMS PCA expects every PC range to correlate to some line and file. */
1277 vmsdbgout_source_line (line, file);
1281 /* No output for VMS debug, but make obligatory call to Dwarf2 debug */
1283 static void
1284 vmsdbgout_end_function (unsigned int line)
1286 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1287 (*dwarf2_debug_hooks.end_function) (line);
1290 /* Output a marker (i.e. a label) for the absolute end of the generated code
1291 for a function definition. This gets called *after* the epilogue code has
1292 been generated. */
1294 static void
1295 vmsdbgout_end_epilogue (unsigned int line, const char *file)
1297 char label[MAX_ARTIFICIAL_LABEL_BYTES];
1299 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1300 (*dwarf2_debug_hooks.end_epilogue) (line, file);
1302 if (debug_info_level > DINFO_LEVEL_NONE)
1304 /* Output a label to mark the endpoint of the code generated for this
1305 function. */
1306 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL,
1307 current_function_funcdef_no);
1308 ASM_OUTPUT_LABEL (asm_out_file, label);
1310 /* VMS PCA expects every PC range to correlate to some line and file. */
1311 vmsdbgout_source_line (line, file);
1315 /* Output a marker (i.e. a label) for the beginning of the generated code for
1316 a lexical block. */
1318 static void
1319 vmsdbgout_begin_block (register unsigned line, register unsigned blocknum)
1321 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1322 (*dwarf2_debug_hooks.begin_block) (line, blocknum);
1324 if (debug_info_level > DINFO_LEVEL_TERSE)
1325 (*targetm.asm_out.internal_label) (asm_out_file, BLOCK_BEGIN_LABEL, blocknum);
1328 /* Output a marker (i.e. a label) for the end of the generated code for a
1329 lexical block. */
1331 static void
1332 vmsdbgout_end_block (register unsigned line, register unsigned blocknum)
1334 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1335 (*dwarf2_debug_hooks.end_block) (line, blocknum);
1337 if (debug_info_level > DINFO_LEVEL_TERSE)
1338 (*targetm.asm_out.internal_label) (asm_out_file, BLOCK_END_LABEL, blocknum);
1341 /* Not implemented in VMS Debug. */
1343 static bool
1344 vmsdbgout_ignore_block (tree block)
1346 bool retval = 0;
1348 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1349 retval = (*dwarf2_debug_hooks.ignore_block) (block);
1351 return retval;
1354 /* Add an entry for function DECL into the func_table. */
1356 static void
1357 vmsdbgout_begin_function (tree decl)
1359 const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
1361 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1362 (*dwarf2_debug_hooks.begin_function) (decl);
1364 if (func_table_in_use == func_table_allocated)
1366 func_table_allocated += FUNC_TABLE_INCREMENT;
1367 func_table = xrealloc (func_table,
1368 func_table_allocated * sizeof (char *));
1371 /* Add the new entry to the end of the function name table. */
1372 func_table[func_table_in_use++] = xstrdup (name);
1375 static char fullname_buff [4096];
1377 /* Return the full file specification for FILENAME. The specification must be
1378 in VMS syntax in order to be processed by VMS Debug. */
1380 static char *
1381 full_name (const char *filename)
1383 #ifdef VMS
1384 FILE *fp = fopen (filename, "r");
1386 fgetname (fp, fullname_buff, 1);
1387 fclose (fp);
1388 #else
1389 getcwd (fullname_buff, sizeof (fullname_buff));
1391 strcat (fullname_buff, "/");
1392 strcat (fullname_buff, filename);
1394 /* ??? Insert hairy code here to translate Unix style file specification
1395 to VMS style. */
1396 #endif
1398 return fullname_buff;
1401 /* Lookup a filename (in the list of filenames that we know about here in
1402 vmsdbgout.c) and return its "index". The index of each (known) filename is
1403 just a unique number which is associated with only that one filename. We
1404 need such numbers for the sake of generating labels and references
1405 to those files numbers. If the filename given as an argument is not
1406 found in our current list, add it to the list and assign it the next
1407 available unique index number. In order to speed up searches, we remember
1408 the index of the filename was looked up last. This handles the majority of
1409 all searches. */
1411 static unsigned int
1412 lookup_filename (const char *file_name)
1414 static unsigned int last_file_lookup_index = 0;
1415 register char *fn;
1416 register unsigned i;
1417 char *fnam;
1418 long long cdt;
1419 long ebk;
1420 short ffb;
1421 char rfo;
1422 char flen;
1423 struct stat statbuf;
1425 if (stat (file_name, &statbuf) == 0)
1427 long gmtoff;
1428 #ifdef VMS
1429 struct tm *ts;
1431 /* Adjust for GMT. */
1432 ts = (struct tm *) localtime (&statbuf.st_ctime);
1433 gmtoff = ts->tm_gmtoff;
1435 /* VMS has multiple file format types. */
1436 rfo = statbuf.st_fab_rfm;
1437 #else
1438 /* Is GMT adjustment an issue with a cross-compiler? */
1439 gmtoff = 0;
1441 /* Assume stream LF type file. */
1442 rfo = 2;
1443 #endif
1444 cdt = 10000000 * (statbuf.st_ctime + gmtoff + vms_epoch_offset);
1445 ebk = statbuf.st_size / 512 + 1;
1446 ffb = statbuf.st_size - ((statbuf.st_size / 512) * 512);
1447 fnam = full_name (file_name);
1448 flen = strlen (fnam);
1450 else
1452 cdt = 0;
1453 ebk = 0;
1454 ffb = 0;
1455 rfo = 0;
1456 fnam = (char *) "";
1457 flen = 0;
1460 /* Check to see if the file name that was searched on the previous call
1461 matches this file name. If so, return the index. */
1462 if (last_file_lookup_index != 0)
1464 fn = file_info_table[last_file_lookup_index].file_name;
1465 if (strcmp (fnam, fn) == 0)
1466 return last_file_lookup_index;
1469 /* Didn't match the previous lookup, search the table */
1470 for (i = 1; i < file_info_table_in_use; ++i)
1472 fn = file_info_table[i].file_name;
1473 if (strcmp (fnam, fn) == 0)
1475 last_file_lookup_index = i;
1476 return i;
1480 /* Prepare to add a new table entry by making sure there is enough space in
1481 the table to do so. If not, expand the current table. */
1482 if (file_info_table_in_use == file_info_table_allocated)
1485 file_info_table_allocated += FILE_TABLE_INCREMENT;
1486 file_info_table = xrealloc (file_info_table,
1487 (file_info_table_allocated
1488 * sizeof (dst_file_info_entry)));
1491 /* Add the new entry to the end of the filename table. */
1492 file_info_table[file_info_table_in_use].file_name = xstrdup (fnam);
1493 file_info_table[file_info_table_in_use].max_line = 0;
1494 file_info_table[file_info_table_in_use].cdt = cdt;
1495 file_info_table[file_info_table_in_use].ebk = ebk;
1496 file_info_table[file_info_table_in_use].ffb = ffb;
1497 file_info_table[file_info_table_in_use].rfo = rfo;
1498 file_info_table[file_info_table_in_use].flen = flen;
1500 last_file_lookup_index = file_info_table_in_use++;
1501 return last_file_lookup_index;
1504 /* Output a label to mark the beginning of a source code line entry
1505 and record information relating to this source line, in
1506 'line_info_table' for later output of the .debug_line section. */
1508 static void
1509 vmsdbgout_source_line (register unsigned line, register const char *filename)
1511 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1512 (*dwarf2_debug_hooks.source_line) (line, filename);
1514 if (debug_info_level >= DINFO_LEVEL_TERSE)
1516 dst_line_info_ref line_info;
1518 (*targetm.asm_out.internal_label) (asm_out_file, LINE_CODE_LABEL,
1519 line_info_table_in_use);
1521 /* Expand the line info table if necessary. */
1522 if (line_info_table_in_use == line_info_table_allocated)
1524 line_info_table_allocated += LINE_INFO_TABLE_INCREMENT;
1525 line_info_table = xrealloc (line_info_table,
1526 (line_info_table_allocated
1527 * sizeof (dst_line_info_entry)));
1530 /* Add the new entry at the end of the line_info_table. */
1531 line_info = &line_info_table[line_info_table_in_use++];
1532 line_info->dst_file_num = lookup_filename (filename);
1533 line_info->dst_line_num = line;
1534 if (line > file_info_table[line_info->dst_file_num].max_line)
1535 file_info_table[line_info->dst_file_num].max_line = line;
1539 /* Record the beginning of a new source file, for later output.
1540 At present, unimplemented. */
1542 static void
1543 vmsdbgout_start_source_file (unsigned int lineno, const char *filename)
1545 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1546 (*dwarf2_debug_hooks.start_source_file) (lineno, filename);
1549 /* Record the end of a source file, for later output.
1550 At present, unimplemented. */
1552 static void
1553 vmsdbgout_end_source_file (unsigned int lineno ATTRIBUTE_UNUSED)
1555 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1556 (*dwarf2_debug_hooks.end_source_file) (lineno);
1559 /* Set up for Debug output at the start of compilation. */
1561 static void
1562 vmsdbgout_init (const char *main_input_filename)
1564 const char *language_string = lang_hooks.name;
1566 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1567 (*dwarf2_debug_hooks.init) (main_input_filename);
1569 if (debug_info_level == DINFO_LEVEL_NONE)
1570 return;
1572 /* Remember the name of the primary input file. */
1573 primary_filename = main_input_filename;
1575 /* Allocate the initial hunk of the file_info_table. */
1576 file_info_table
1577 = xcalloc (FILE_TABLE_INCREMENT, sizeof (dst_file_info_entry));
1578 file_info_table_allocated = FILE_TABLE_INCREMENT;
1580 /* Skip the first entry - file numbers begin at 1 */
1581 file_info_table_in_use = 1;
1583 func_table = xcalloc (FUNC_TABLE_INCREMENT, sizeof (char *));
1584 func_table_allocated = FUNC_TABLE_INCREMENT;
1585 func_table_in_use = 1;
1587 /* Allocate the initial hunk of the line_info_table. */
1588 line_info_table
1589 = xcalloc (LINE_INFO_TABLE_INCREMENT, sizeof (dst_line_info_entry));
1590 line_info_table_allocated = LINE_INFO_TABLE_INCREMENT;
1591 /* zero-th entry is allocated, but unused */
1592 line_info_table_in_use = 1;
1594 lookup_filename (primary_filename);
1596 if (!strcmp (language_string, "GNU C"))
1597 module_language = DST_K_C;
1598 else if (!strcmp (language_string, "GNU C++"))
1599 module_language = DST_K_CXX;
1600 else if (!strcmp (language_string, "GNU Ada"))
1601 module_language = DST_K_ADA;
1602 else if (!strcmp (language_string, "GNU F77"))
1603 module_language = DST_K_FORTRAN;
1604 else
1605 module_language = DST_K_UNKNOWN;
1607 module_producer = concat (language_string, " ", version_string, NULL);
1609 ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
1613 /* Not implemented in VMS Debug. */
1615 static void
1616 vmsdbgout_define (unsigned int lineno, const char *buffer)
1618 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1619 (*dwarf2_debug_hooks.define) (lineno, buffer);
1622 /* Not implemented in VMS Debug. */
1624 static void
1625 vmsdbgout_undef (unsigned int lineno, const char *buffer)
1627 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1628 (*dwarf2_debug_hooks.undef) (lineno, buffer);
1631 /* Not implemented in VMS Debug. */
1633 static void
1634 vmsdbgout_decl (tree decl)
1636 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1637 (*dwarf2_debug_hooks.function_decl) (decl);
1640 /* Not implemented in VMS Debug. */
1642 static void
1643 vmsdbgout_global_decl (tree decl)
1645 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1646 (*dwarf2_debug_hooks.global_decl) (decl);
1649 /* Not implemented in VMS Debug. */
1651 static void
1652 vmsdbgout_abstract_function (tree decl)
1654 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1655 (*dwarf2_debug_hooks.outlining_inline_function) (decl);
1658 /* Output stuff that Debug requires at the end of every file and generate the
1659 VMS Debug debugging info. */
1661 static void
1662 vmsdbgout_finish (const char *main_input_filename ATTRIBUTE_UNUSED)
1664 unsigned int i;
1665 int totsize;
1667 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1668 (*dwarf2_debug_hooks.finish) (main_input_filename);
1670 if (debug_info_level == DINFO_LEVEL_NONE)
1671 return;
1673 /* Output a terminator label for the .text section. */
1674 text_section ();
1675 (*targetm.asm_out.internal_label) (asm_out_file, TEXT_END_LABEL, 0);
1677 /* Output debugging information.
1678 Warning! Do not change the name of the .vmsdebug section without
1679 changing it in the assembler also. */
1680 named_section (NULL_TREE, ".vmsdebug", 0);
1681 ASM_OUTPUT_ALIGN (asm_out_file, 0);
1683 totsize = write_modbeg (1);
1684 for (i = 1; i < func_table_in_use; i++)
1686 totsize += write_rtnbeg (i, 1);
1687 totsize += write_rtnend (i, 1);
1689 totsize += write_pclines (1);
1691 write_modbeg (0);
1692 for (i = 1; i < func_table_in_use; i++)
1694 write_rtnbeg (i, 0);
1695 write_rtnend (i, 0);
1697 write_pclines (0);
1699 if (debug_info_level > DINFO_LEVEL_TERSE)
1701 totsize = write_srccorrs (1);
1702 write_srccorrs (0);
1705 totsize = write_modend (1);
1706 write_modend (0);
1708 #endif /* VMS_DEBUGGING_INFO */