2002-05-04 David S. Miller <davem@redhat.com>
[official-gcc.git] / gcc / vmsdbgout.c
blob7d0de2f2de1f815148d12195ff64ae5dd8819a48
1 /* Output VMS debug format symbol table information from the GNU C compiler.
2 Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
4 Contributed by Douglas B. Rupp (rupp@gnat.com).
6 This file is part of GNU CC.
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"
25 #ifdef VMS_DEBUGGING_INFO
26 #include "system.h"
27 #include "tree.h"
28 #include "flags.h"
29 #include "rtl.h"
30 #include "output.h"
31 #include "vmsdbg.h"
32 #include "debug.h"
33 #include "langhooks.h"
35 /* Difference in seconds between the VMS Epoch and the Unix Epoch */
36 static const long long vms_epoch_offset = 3506716800ll;
38 /* NOTE: In the comments in this file, many references are made to "Debug
39 Symbol Table". This term is abbreviated as `DST' throughout the remainder
40 of this file. */
42 typedef struct dst_line_info_struct *dst_line_info_ref;
44 /* Each entry in the line_info_table maintains the file and
45 line number associated with the label generated for that
46 entry. The label gives the PC value associated with
47 the line number entry. */
48 typedef struct dst_line_info_struct
50 unsigned long dst_file_num;
51 unsigned long dst_line_num;
53 dst_line_info_entry;
55 typedef struct dst_file_info_struct *dst_file_info_ref;
57 typedef struct dst_file_info_struct
59 char *file_name;
60 unsigned int max_line;
61 unsigned int listing_line_start;
62 long long cdt;
63 long ebk;
64 short ffb;
65 char rfo;
66 char flen;
68 dst_file_info_entry;
70 /* How to start an assembler comment. */
71 #ifndef ASM_COMMENT_START
72 #define ASM_COMMENT_START ";#"
73 #endif
75 /* Maximum size (in bytes) of an artificially generated label. */
76 #define MAX_ARTIFICIAL_LABEL_BYTES 30
78 /* Make sure we know the sizes of the various types debug can describe. These
79 are only defaults. If the sizes are different for your target, you should
80 override these values by defining the appropriate symbols in your tm.h
81 file. */
82 #ifndef PTR_SIZE
83 #define PTR_SIZE 4 /* Must be 32 bits for VMS debug info */
84 #endif
86 /* Pointer to an structure of filenames referenced by this compilation unit. */
87 static dst_file_info_ref file_info_table;
89 /* Total number of entries in the table (i.e. array) pointed to by
90 `file_info_table'. This is the *total* and includes both used and unused
91 slots. */
92 static unsigned int file_info_table_allocated;
94 /* Number of entries in the file_info_table which are actually in use. */
95 static unsigned int file_info_table_in_use;
97 /* Size (in elements) of increments by which we may expand the filename
98 table. */
99 #define FILE_TABLE_INCREMENT 64
101 static char **func_table;
102 static unsigned int func_table_allocated;
103 static unsigned int func_table_in_use;
104 #define FUNC_TABLE_INCREMENT 256
106 /* Local pointer to the name of the main input file. Initialized in
107 avmdbgout_init. */
108 static const char *primary_filename;
110 static char *module_producer;
111 static unsigned int module_language;
113 /* A pointer to the base of a table that contains line information
114 for each source code line in .text in the compilation unit. */
115 static dst_line_info_ref line_info_table;
117 /* Number of elements currently allocated for line_info_table. */
118 static unsigned int line_info_table_allocated;
120 /* Number of elements in line_info_table currently in use. */
121 static unsigned int line_info_table_in_use;
123 /* Size (in elements) of increments by which we may expand line_info_table. */
124 #define LINE_INFO_TABLE_INCREMENT 1024
126 /* The number of the current function definition for which debugging
127 information is being generated. These numbers range from 1 up to the
128 maximum number of function definitions contained within the current
129 compilation unit. These numbers are used to create unique label id's unique
130 to each function definition. */
131 static unsigned int current_funcdef_number = 0;
133 /* Forward declarations for functions defined in this file. */
134 static char *full_name PARAMS ((const char *));
135 static unsigned int lookup_filename PARAMS ((const char *));
136 static void addr_const_to_string PARAMS ((char *, rtx));
137 static int write_debug_header PARAMS ((DST_HEADER *, const char *, int));
138 static int write_debug_addr PARAMS ((char *, const char *, int));
139 static int write_debug_data1 PARAMS ((unsigned int, const char *, int));
140 static int write_debug_data2 PARAMS ((unsigned int, const char *, int));
141 static int write_debug_data4 PARAMS ((unsigned long, const char *, int));
142 static int write_debug_data8 PARAMS ((unsigned long long, const char *,
143 int));
144 static int write_debug_delta4 PARAMS ((char *, char *, const char *, int));
145 static int write_debug_string PARAMS ((char *, const char *, int));
146 static int write_modbeg PARAMS ((int));
147 static int write_modend PARAMS ((int));
148 static int write_rtnbeg PARAMS ((int, int));
149 static int write_rtnend PARAMS ((int, int));
150 static int write_pclines PARAMS ((int));
151 static int write_srccorr PARAMS ((int, dst_file_info_entry, int));
152 static int write_srccorrs PARAMS ((int));
154 static void vmsdbgout_init PARAMS ((const char *));
155 static void vmsdbgout_finish PARAMS ((const char *));
156 static void vmsdbgout_define PARAMS ((unsigned int, const char *));
157 static void vmsdbgout_undef PARAMS ((unsigned int, const char *));
158 static void vmsdbgout_start_source_file PARAMS ((unsigned int, const char *));
159 static void vmsdbgout_end_source_file PARAMS ((unsigned int));
160 static void vmsdbgout_begin_block PARAMS ((unsigned int, unsigned int));
161 static void vmsdbgout_end_block PARAMS ((unsigned int, unsigned int));
162 static bool vmsdbgout_ignore_block PARAMS ((tree));
163 static void vmsdbgout_source_line PARAMS ((unsigned int, const char *));
164 static void vmsdbgout_begin_prologue PARAMS ((unsigned int, const char *));
165 static void vmsdbgout_end_epilogue PARAMS ((void));
166 static void vmsdbgout_begin_function PARAMS ((tree));
167 static void vmsdbgout_decl PARAMS ((tree));
168 static void vmsdbgout_global_decl PARAMS ((tree));
169 static void vmsdbgout_abstract_function PARAMS ((tree));
171 /* The debug hooks structure. */
173 const struct gcc_debug_hooks vmsdbg_debug_hooks
174 = {vmsdbgout_init,
175 vmsdbgout_finish,
176 vmsdbgout_define,
177 vmsdbgout_undef,
178 vmsdbgout_start_source_file,
179 vmsdbgout_end_source_file,
180 vmsdbgout_begin_block,
181 vmsdbgout_end_block,
182 vmsdbgout_ignore_block,
183 vmsdbgout_source_line,
184 vmsdbgout_begin_prologue,
185 debug_nothing_int, /* end_prologue */
186 vmsdbgout_end_epilogue, /* end_epilogue */
187 vmsdbgout_begin_function, /* begin_function */
188 debug_nothing_int, /* end_function */
189 vmsdbgout_decl,
190 vmsdbgout_global_decl,
191 debug_nothing_tree, /* deferred_inline_function */
192 vmsdbgout_abstract_function,
193 debug_nothing_rtx /* label */
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 /* Pseudo-op for defining a new section. */
242 #ifndef SECTION_ASM_OP
243 #define SECTION_ASM_OP ".section"
244 #endif
246 /* Definitions of defaults for formats and names of various special
247 (artificial) labels which may be generated within this file (when the -g
248 options is used and VMS_DEBUGGING_INFO is in effect. If necessary, these
249 may be overridden from within the tm.h file, but typically, overriding these
250 defaults is unnecessary. */
252 static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
254 #ifndef TEXT_END_LABEL
255 #define TEXT_END_LABEL "Lvetext"
256 #endif
257 #ifndef FUNC_BEGIN_LABEL
258 #define FUNC_BEGIN_LABEL "LVFB"
259 #endif
260 #ifndef FUNC_PROLOG_LABEL
261 #define FUNC_PROLOG_LABEL "LVFP"
262 #endif
263 #ifndef FUNC_END_LABEL
264 #define FUNC_END_LABEL "LVFE"
265 #endif
266 #ifndef BLOCK_BEGIN_LABEL
267 #define BLOCK_BEGIN_LABEL "LVBB"
268 #endif
269 #ifndef BLOCK_END_LABEL
270 #define BLOCK_END_LABEL "LVBE"
271 #endif
272 #ifndef LINE_CODE_LABEL
273 #define LINE_CODE_LABEL "LVM"
274 #endif
276 #ifndef ASM_OUTPUT_DEBUG_DELTA2
277 #define ASM_OUTPUT_DEBUG_DELTA2(FILE,LABEL1,LABEL2) \
278 do \
280 fprintf ((FILE), "\t%s\t", UNALIGNED_SHORT_ASM_OP); \
281 assemble_name (FILE, LABEL1); \
282 fprintf (FILE, "-"); \
283 assemble_name (FILE, LABEL2); \
285 while (0)
286 #endif
288 #ifndef ASM_OUTPUT_DEBUG_DELTA4
289 #define ASM_OUTPUT_DEBUG_DELTA4(FILE,LABEL1,LABEL2) \
290 do \
292 fprintf ((FILE), "\t%s\t", UNALIGNED_INT_ASM_OP); \
293 assemble_name (FILE, LABEL1); \
294 fprintf (FILE, "-"); \
295 assemble_name (FILE, LABEL2); \
297 while (0)
298 #endif
300 #ifndef ASM_OUTPUT_DEBUG_ADDR_DELTA
301 #define ASM_OUTPUT_DEBUG_ADDR_DELTA(FILE,LABEL1,LABEL2) \
302 do \
304 fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP); \
305 assemble_name (FILE, LABEL1); \
306 fprintf (FILE, "-"); \
307 assemble_name (FILE, LABEL2); \
309 while (0)
310 #endif
312 #ifndef ASM_OUTPUT_DEBUG_ADDR
313 #define ASM_OUTPUT_DEBUG_ADDR(FILE,LABEL) \
314 do \
316 fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP); \
317 assemble_name (FILE, LABEL); \
319 while (0)
320 #endif
322 #ifndef ASM_OUTPUT_DEBUG_ADDR_CONST
323 #define ASM_OUTPUT_DEBUG_ADDR_CONST(FILE,ADDR) \
324 fprintf ((FILE), "\t%s\t%s", UNALIGNED_PTR_ASM_OP, (ADDR))
325 #endif
327 #ifndef ASM_OUTPUT_DEBUG_DATA1
328 #define ASM_OUTPUT_DEBUG_DATA1(FILE,VALUE) \
329 fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, (unsigned char) VALUE)
330 #endif
332 #ifndef ASM_OUTPUT_DEBUG_DATA2
333 #define ASM_OUTPUT_DEBUG_DATA2(FILE,VALUE) \
334 fprintf ((FILE), "\t%s\t0x%x", UNALIGNED_SHORT_ASM_OP, \
335 (unsigned short) VALUE)
336 #endif
338 #ifndef ASM_OUTPUT_DEBUG_DATA4
339 #define ASM_OUTPUT_DEBUG_DATA4(FILE,VALUE) \
340 fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_INT_ASM_OP, (unsigned long) VALUE)
341 #endif
343 #ifndef ASM_OUTPUT_DEBUG_DATA
344 #define ASM_OUTPUT_DEBUG_DATA(FILE,VALUE) \
345 fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_OFFSET_ASM_OP(VALUE), VALUE)
346 #endif
348 #ifndef ASM_OUTPUT_DEBUG_ADDR_DATA
349 #define ASM_OUTPUT_DEBUG_ADDR_DATA(FILE,VALUE) \
350 fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_PTR_ASM_OP, \
351 (unsigned long) VALUE)
352 #endif
354 #ifndef ASM_OUTPUT_DEBUG_DATA8
355 #define ASM_OUTPUT_DEBUG_DATA8(FILE,VALUE) \
356 fprintf ((FILE), "\t%s\t0x%llx", UNALIGNED_DOUBLE_INT_ASM_OP, \
357 (unsigned long long) VALUE)
358 #endif
360 /* This is similar to the default ASM_OUTPUT_ASCII, except that no trailing
361 newline is produced. When flag_verbose_asm is asserted, we add commnetary
362 at the end of the line, so we must avoid output of a newline here. */
363 #ifndef ASM_OUTPUT_DEBUG_STRING
364 #define ASM_OUTPUT_DEBUG_STRING(FILE,P) \
365 do \
367 register int slen = strlen(P); \
368 register char *p = (P); \
369 register int i; \
370 fprintf (FILE, "\t.ascii \""); \
371 for (i = 0; i < slen; i++) \
373 register int c = p[i]; \
374 if (c == '\"' || c == '\\') \
375 putc ('\\', FILE); \
376 if (c >= ' ' && c < 0177) \
377 putc (c, FILE); \
378 else \
379 fprintf (FILE, "\\%o", c); \
381 fprintf (FILE, "\""); \
383 while (0)
384 #endif
386 /* Convert a reference to the assembler name of a C-level name. This
387 macro has the same effect as ASM_OUTPUT_LABELREF, but copies to
388 a string rather than writing to a file. */
389 #ifndef ASM_NAME_TO_STRING
390 #define ASM_NAME_TO_STRING(STR, NAME) \
391 do \
393 if ((NAME)[0] == '*') \
394 strcpy (STR, NAME+1); \
395 else \
396 strcpy (STR, NAME); \
398 while (0)
399 #endif
402 /* General utility functions. */
404 /* Convert an integer constant expression into assembler syntax. Addition and
405 subtraction are the only arithmetic that may appear in these expressions.
406 This is an adaptation of output_addr_const in final.c. Here, the target
407 of the conversion is a string buffer. We can't use output_addr_const
408 directly, because it writes to a file. */
410 static void
411 addr_const_to_string (str, x)
412 char *str;
413 rtx x;
415 char buf1[256];
416 char buf2[256];
418 restart:
419 str[0] = '\0';
420 switch (GET_CODE (x))
422 case PC:
423 if (flag_pic)
424 strcat (str, ",");
425 else
426 abort ();
427 break;
429 case SYMBOL_REF:
430 ASM_NAME_TO_STRING (buf1, XSTR (x, 0));
431 strcat (str, buf1);
432 break;
434 case LABEL_REF:
435 ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
436 ASM_NAME_TO_STRING (buf2, buf1);
437 strcat (str, buf2);
438 break;
440 case CODE_LABEL:
441 ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (x));
442 ASM_NAME_TO_STRING (buf2, buf1);
443 strcat (str, buf2);
444 break;
446 case CONST_INT:
447 sprintf (buf1, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
448 strcat (str, buf1);
449 break;
451 case CONST:
452 /* This used to output parentheses around the expression, but that does
453 not work on the 386 (either ATT or BSD assembler). */
454 addr_const_to_string (buf1, XEXP (x, 0));
455 strcat (str, buf1);
456 break;
458 case CONST_DOUBLE:
459 if (GET_MODE (x) == VOIDmode)
461 /* We can use %d if the number is one word and positive. */
462 if (CONST_DOUBLE_HIGH (x))
463 sprintf (buf1, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
464 CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
465 else if (CONST_DOUBLE_LOW (x) < 0)
466 sprintf (buf1, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (x));
467 else
468 sprintf (buf1, HOST_WIDE_INT_PRINT_DEC,
469 CONST_DOUBLE_LOW (x));
470 strcat (str, buf1);
472 else
473 /* We can't handle floating point constants; PRINT_OPERAND must
474 handle them. */
475 output_operand_lossage ("floating constant misused");
476 break;
478 case PLUS:
479 /* Some assemblers need integer constants to appear last (eg masm). */
480 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
482 addr_const_to_string (buf1, XEXP (x, 1));
483 strcat (str, buf1);
484 if (INTVAL (XEXP (x, 0)) >= 0)
485 strcat (str, "+");
486 addr_const_to_string (buf1, XEXP (x, 0));
487 strcat (str, buf1);
489 else
491 addr_const_to_string (buf1, XEXP (x, 0));
492 strcat (str, buf1);
493 if (INTVAL (XEXP (x, 1)) >= 0)
494 strcat (str, "+");
495 addr_const_to_string (buf1, XEXP (x, 1));
496 strcat (str, buf1);
498 break;
500 case MINUS:
501 /* Avoid outputting things like x-x or x+5-x, since some assemblers
502 can't handle that. */
503 x = simplify_subtraction (x);
504 if (GET_CODE (x) != MINUS)
505 goto restart;
507 addr_const_to_string (buf1, XEXP (x, 0));
508 strcat (str, buf1);
509 strcat (str, "-");
510 if (GET_CODE (XEXP (x, 1)) == CONST_INT
511 && INTVAL (XEXP (x, 1)) < 0)
513 strcat (str, "(");
514 addr_const_to_string (buf1, XEXP (x, 1));
515 strcat (str, buf1);
516 strcat (str, ")");
518 else
520 addr_const_to_string (buf1, XEXP (x, 1));
521 strcat (str, buf1);
523 break;
525 case ZERO_EXTEND:
526 case SIGN_EXTEND:
527 addr_const_to_string (buf1, XEXP (x, 0));
528 strcat (str, buf1);
529 break;
531 default:
532 output_operand_lossage ("invalid expression as operand");
536 /* Output the debug header HEADER. Also output COMMENT if flag_verbose_asm is
537 set. Return the header size. Just return the size if DOSIZEONLY is
538 non-zero. */
540 static int
541 write_debug_header (header, comment, dosizeonly)
542 DST_HEADER *header;
543 const char *comment;
544 int dosizeonly;
546 if (!dosizeonly)
548 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file,
549 header->dst__header_length.dst_w_length);
551 if (flag_verbose_asm)
552 fprintf (asm_out_file, "\t%s record length", ASM_COMMENT_START);
553 fputc ('\n', asm_out_file);
555 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file,
556 header->dst__header_type.dst_w_type);
558 if (flag_verbose_asm)
559 fprintf (asm_out_file, "\t%s record type (%s)", ASM_COMMENT_START,
560 comment);
562 fputc ('\n', asm_out_file);
565 return 4;
568 /* Output the address of SYMBOL. Also output COMMENT if flag_verbose_asm is
569 set. Return the address size. Just return the size if DOSIZEONLY is
570 non-zero. */
572 static int
573 write_debug_addr (symbol, comment, dosizeonly)
574 char *symbol;
575 const char *comment;
576 int dosizeonly;
578 if (!dosizeonly)
580 ASM_OUTPUT_DEBUG_ADDR (asm_out_file, symbol);
581 if (flag_verbose_asm)
582 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
583 fputc ('\n', asm_out_file);
586 return PTR_SIZE;
589 /* Output the single byte DATA1. Also output COMMENT if flag_verbose_asm is
590 set. Return the data size. Just return the size if DOSIZEONLY is
591 non-zero. */
593 static int
594 write_debug_data1 (data1, comment, dosizeonly)
595 unsigned int data1;
596 const char *comment;
597 int dosizeonly;
599 if (!dosizeonly)
601 ASM_OUTPUT_DEBUG_DATA1 (asm_out_file, data1);
602 if (flag_verbose_asm)
603 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
604 fputc ('\n', asm_out_file);
607 return 1;
610 /* Output the single word DATA2. Also output COMMENT if flag_verbose_asm is
611 set. Return the data size. Just return the size if DOSIZEONLY is
612 non-zero. */
614 static int
615 write_debug_data2 (data2, comment, dosizeonly)
616 unsigned int data2;
617 const char *comment;
618 int dosizeonly;
620 if (!dosizeonly)
622 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file, data2);
623 if (flag_verbose_asm)
624 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
625 fputc ('\n', asm_out_file);
628 return 2;
631 /* Output double word DATA4. Also output COMMENT if flag_verbose_asm is set.
632 Return the data size. Just return the size if DOSIZEONLY is non-zero. */
634 static int
635 write_debug_data4 (data4, comment, dosizeonly)
636 unsigned long data4;
637 const char *comment;
638 int dosizeonly;
640 if (!dosizeonly)
642 ASM_OUTPUT_DEBUG_DATA4 (asm_out_file, data4);
643 if (flag_verbose_asm)
644 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
645 fputc ('\n', asm_out_file);
648 return 4;
651 /* Output quad word DATA8. Also output COMMENT if flag_verbose_asm is set.
652 Return the data size. Just return the size if DOSIZEONLY is non-zero. */
654 static int
655 write_debug_data8 (data8, comment, dosizeonly)
656 unsigned long long data8;
657 const char *comment;
658 int dosizeonly;
660 if (!dosizeonly)
662 ASM_OUTPUT_DEBUG_DATA8 (asm_out_file, data8);
663 if (flag_verbose_asm)
664 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
665 fputc ('\n', asm_out_file);
668 return 8;
671 /* Output the difference between LABEL1 and LABEL2. Also output COMMENT if
672 flag_verbose_asm is set. Return the data size. Just return the size if
673 DOSIZEONLY is non-zero. */
675 static int
676 write_debug_delta4 (label1, label2, comment, dosizeonly)
677 char *label1;
678 char *label2;
679 const char *comment;
680 int dosizeonly;
682 if (!dosizeonly)
684 ASM_OUTPUT_DEBUG_DELTA4 (asm_out_file, label1, label2);
685 if (flag_verbose_asm)
686 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
687 fputc ('\n', asm_out_file);
690 return 4;
693 /* Output a character string STRING. Also write COMMENT if flag_verbose_asm is
694 set. Return the string length. Just return the length if DOSIZEONLY is
695 non-zero. */
697 static int
698 write_debug_string (string, comment, dosizeonly)
699 char *string;
700 const char *comment;
701 int dosizeonly;
703 if (!dosizeonly)
705 ASM_OUTPUT_DEBUG_STRING (asm_out_file, string);
706 if (flag_verbose_asm)
707 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
708 fputc ('\n', asm_out_file);
711 return strlen (string);
714 /* Output a module begin header and return the header size. Just return the
715 size if DOSIZEONLY is non-zero. */
717 static int
718 write_modbeg (dosizeonly)
719 int dosizeonly;
721 DST_MODULE_BEGIN modbeg;
722 DST_MB_TRLR mb_trlr;
723 int i;
724 char *module_name, *m;
725 int modnamelen;
726 int prodnamelen;
727 int totsize = 0;
729 /* Assumes primary filename has Unix syntax file spec. */
730 module_name = xstrdup (basename ((char *) primary_filename));
732 m = strrchr (module_name, '.');
733 if (m)
734 *m = 0;
736 modnamelen = strlen (module_name);
737 for (i = 0; i < modnamelen; i++)
738 module_name[i] = TOUPPER (module_name[i]);
740 prodnamelen = strlen (module_producer);
742 modbeg.dst_a_modbeg_header.dst__header_length.dst_w_length
743 = DST_K_MODBEG_SIZE + modnamelen + DST_K_MB_TRLR_SIZE + prodnamelen - 1;
744 modbeg.dst_a_modbeg_header.dst__header_type.dst_w_type = DST_K_MODBEG;
745 modbeg.dst_b_modbeg_flags.dst_v_modbeg_hide = 0;
746 modbeg.dst_b_modbeg_flags.dst_v_modbeg_version = 1;
747 modbeg.dst_b_modbeg_flags.dst_v_modbeg_unused = 0;
748 modbeg.dst_b_modbeg_unused = 0;
749 modbeg.dst_l_modbeg_language = module_language;
750 modbeg.dst_w_version_major = DST_K_VERSION_MAJOR;
751 modbeg.dst_w_version_minor = DST_K_VERSION_MINOR;
752 modbeg.dst_b_modbeg_name = strlen (module_name);
754 mb_trlr.dst_b_compiler = strlen (module_producer);
756 totsize += write_debug_header (&modbeg.dst_a_modbeg_header,
757 "modbeg", dosizeonly);
758 totsize += write_debug_data1 (*((char *) &modbeg.dst_b_modbeg_flags),
759 "flags", dosizeonly);
760 totsize += write_debug_data1 (modbeg.dst_b_modbeg_unused,
761 "unused", dosizeonly);
762 totsize += write_debug_data4 (modbeg.dst_l_modbeg_language,
763 "language", dosizeonly);
764 totsize += write_debug_data2 (modbeg.dst_w_version_major,
765 "DST major version", dosizeonly);
766 totsize += write_debug_data2 (modbeg.dst_w_version_minor,
767 "DST minor version", dosizeonly);
768 totsize += write_debug_data1 (modbeg.dst_b_modbeg_name,
769 "length of module name", dosizeonly);
770 totsize += write_debug_string (module_name, "module name", dosizeonly);
771 totsize += write_debug_data1 (mb_trlr.dst_b_compiler,
772 "length of compiler name", dosizeonly);
773 totsize += write_debug_string (module_producer, "compiler name", dosizeonly);
775 return totsize;
778 /* Output a module end trailer and return the trailer size. Just return
779 the size if DOSIZEONLY is non-zero. */
781 static int
782 write_modend (dosizeonly)
783 int dosizeonly;
785 DST_MODULE_END modend;
786 int totsize = 0;
788 modend.dst_a_modend_header.dst__header_length.dst_w_length
789 = DST_K_MODEND_SIZE - 1;
790 modend.dst_a_modend_header.dst__header_type.dst_w_type = DST_K_MODEND;
792 totsize += write_debug_header (&modend.dst_a_modend_header, "modend",
793 dosizeonly);
795 return totsize;
798 /* Output a routine begin header routine RTNNUM and return the header size.
799 Just return the size if DOSIZEONLY is non-zero. */
801 static int
802 write_rtnbeg (rtnnum, dosizeonly)
803 int rtnnum;
804 int dosizeonly;
806 char *rtnname;
807 int rtnnamelen, rtnentrynamelen;
808 char *rtnentryname;
809 int totsize = 0;
810 char label[MAX_ARTIFICIAL_LABEL_BYTES];
811 DST_ROUTINE_BEGIN rtnbeg;
812 DST_PROLOG prolog;
814 rtnname = func_table[rtnnum];
815 rtnnamelen = strlen (rtnname);
816 rtnentrynamelen = rtnnamelen + 4; /* "..en" */
817 rtnentryname = (char *) xmalloc (rtnentrynamelen + 1);
818 strcpy (rtnentryname, rtnname);
819 strcat (rtnentryname, "..en");
821 if (!strcmp (rtnname, "main"))
823 DST_HEADER header;
824 const char *go = "TRANSFER$BREAK$GO";
826 /* This command isn't documented in DSTRECORDS, so it's made to
827 look like what DEC C does */
829 /* header size - 1st byte + flag byte + STO_LW size
830 + string count byte + string length */
831 header.dst__header_length.dst_w_length
832 = DST_K_DST_HEADER_SIZE - 1 + 1 + 4 + 1 + strlen (go);
833 header.dst__header_type.dst_w_type = 0x17;
835 totsize += write_debug_header (&header, "transfer", dosizeonly);
837 /* I think this is a flag byte, but I don't know what this flag means */
838 totsize += write_debug_data1 (0x1, "flags ???", dosizeonly);
840 /* Routine Begin PD Address */
841 totsize += write_debug_addr (rtnname, "main procedure descriptor",
842 dosizeonly);
843 totsize += write_debug_data1 (strlen (go), "length of main_name",
844 dosizeonly);
845 totsize += write_debug_string ((char *) go, "main name", dosizeonly);
848 /* The header length never includes the length byte */
849 rtnbeg.dst_a_rtnbeg_header.dst__header_length.dst_w_length
850 = DST_K_RTNBEG_SIZE + rtnnamelen - 1;
851 rtnbeg.dst_a_rtnbeg_header.dst__header_type.dst_w_type = DST_K_RTNBEG;
852 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_unused = 0;
853 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_unalloc = 0;
854 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_prototype = 0;
855 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_inlined = 0;
856 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_no_call = 1;
857 rtnbeg.dst_b_rtnbeg_name = rtnnamelen;
859 totsize += write_debug_header (&rtnbeg.dst_a_rtnbeg_header, "rtnbeg",
860 dosizeonly);
861 totsize += write_debug_data1 (*((char *) &rtnbeg.dst_b_rtnbeg_flags),
862 "flags", dosizeonly);
864 /* Routine Begin Address */
865 totsize += write_debug_addr (rtnentryname, "routine entry name", dosizeonly);
867 /* Routine Begin PD Address */
868 totsize += write_debug_addr (rtnname, "routine procedure descriptor",
869 dosizeonly);
871 /* Routine Begin Name */
872 totsize += write_debug_data1 (rtnbeg.dst_b_rtnbeg_name,
873 "length of routine name", dosizeonly);
875 totsize += write_debug_string (rtnname, "routine name", dosizeonly);
877 free (rtnentryname);
879 if (debug_info_level > DINFO_LEVEL_TERSE)
881 prolog.dst_a_prolog_header.dst__header_length.dst_w_length
882 = DST_K_PROLOG_SIZE - 1;
883 prolog.dst_a_prolog_header.dst__header_type.dst_w_type = DST_K_PROLOG;
885 totsize += write_debug_header (&prolog.dst_a_prolog_header, "prolog",
886 dosizeonly);
888 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL, rtnnum);
889 totsize += write_debug_addr (label, "prolog breakpoint addr",
890 dosizeonly);
893 return totsize;
896 /* Output a routine end trailer for routine RTNNUM and return the header size.
897 Just return the size if DOSIZEONLY is non-zero. */
899 static int
900 write_rtnend (rtnnum, dosizeonly)
901 int rtnnum;
902 int dosizeonly;
904 DST_ROUTINE_END rtnend;
905 char label1[MAX_ARTIFICIAL_LABEL_BYTES];
906 char label2[MAX_ARTIFICIAL_LABEL_BYTES];
907 int totsize;
909 totsize = 0;
911 rtnend.dst_a_rtnend_header.dst__header_length.dst_w_length
912 = DST_K_RTNEND_SIZE - 1;
913 rtnend.dst_a_rtnend_header.dst__header_type.dst_w_type = DST_K_RTNEND;
914 rtnend.dst_b_rtnend_unused = 0;
915 rtnend.dst_l_rtnend_size = 0; /* Calculated below. */
917 totsize += write_debug_header (&rtnend.dst_a_rtnend_header, "rtnend",
918 dosizeonly);
919 totsize += write_debug_data1 (rtnend.dst_b_rtnend_unused, "unused",
920 dosizeonly);
922 ASM_GENERATE_INTERNAL_LABEL (label1, FUNC_BEGIN_LABEL, rtnnum);
923 ASM_GENERATE_INTERNAL_LABEL (label2, FUNC_END_LABEL, rtnnum);
924 totsize += write_debug_delta4 (label2, label1, "routine size", dosizeonly);
926 return totsize;
929 #define K_DELTA_PC(I) \
930 ((I) < 128 ? -(I) : (I) < 65536 ? DST_K_DELTA_PC_W : DST_K_DELTA_PC_L)
932 #define K_SET_LINUM(I) \
933 ((I) < 256 ? DST_K_SET_LINUM_B \
934 : (I) < 65536 ? DST_K_SET_LINUM : DST_K_SET_LINUM_L)
936 #define K_INCR_LINUM(I) \
937 ((I) < 256 ? DST_K_INCR_LINUM \
938 : (I) < 65536 ? DST_K_INCR_LINUM_W : DST_K_INCR_LINUM_L)
940 /* Output the PC to line number correlations and return the size. Just return
941 the size if DOSIZEONLY is non-zero */
943 static int
944 write_pclines (dosizeonly)
945 int dosizeonly;
947 unsigned i;
948 int fn;
949 int ln, lastln;
950 int linestart = 0;
951 int max_line;
952 DST_LINE_NUM_HEADER line_num;
953 DST_PCLINE_COMMANDS pcline;
954 char label[MAX_ARTIFICIAL_LABEL_BYTES];
955 char lastlabel[MAX_ARTIFICIAL_LABEL_BYTES];
956 int totsize = 0;
957 char buff[256];
959 max_line = file_info_table[1].max_line;
960 file_info_table[1].listing_line_start = linestart;
961 linestart = linestart + ((max_line / 100000) + 1) * 100000;
963 for (i = 2; i < file_info_table_in_use; i++)
965 max_line = file_info_table[i].max_line;
966 file_info_table[i].listing_line_start = linestart;
967 linestart = linestart + ((max_line / 10000) + 1) * 10000;
970 /* Set starting address to beginning of text section */
971 line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 8;
972 line_num.dst_a_line_num_header.dst__header_type.dst_w_type = DST_K_LINE_NUM;
973 pcline.dst_b_pcline_command = DST_K_SET_ABS_PC;
975 totsize += write_debug_header (&line_num.dst_a_line_num_header,
976 "line_num", dosizeonly);
977 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
978 "line_num (SET ABS PC)", dosizeonly);
980 if (dosizeonly)
981 totsize += 4;
982 else
984 ASM_OUTPUT_DEBUG_ADDR (asm_out_file, TEXT_SECTION_ASM_OP);
985 if (flag_verbose_asm)
986 fprintf (asm_out_file, "\t%s line_num", ASM_COMMENT_START);
987 fputc ('\n', asm_out_file);
990 fn = line_info_table[1].dst_file_num;
991 ln = (file_info_table[fn].listing_line_start
992 + line_info_table[1].dst_line_num);
993 line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 4 + 4;
994 pcline.dst_b_pcline_command = DST_K_SET_LINUM_L;
996 totsize += write_debug_header (&line_num.dst_a_line_num_header,
997 "line_num", dosizeonly);
998 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
999 "line_num (SET LINUM LONG)", dosizeonly);
1001 sprintf (buff, "line_num (%d)", ln - 1);
1002 totsize += write_debug_data4 (ln - 1, buff, dosizeonly);
1004 lastln = ln;
1005 strcpy (lastlabel, TEXT_SECTION_ASM_OP);
1006 for (i = 1; i < line_info_table_in_use; i++)
1008 int extrabytes;
1010 fn = line_info_table[i].dst_file_num;
1011 ln = (file_info_table[fn].listing_line_start
1012 + line_info_table[i].dst_line_num);
1014 if (ln - lastln > 1)
1015 extrabytes = 5; /* NUMBYTES (ln - lastln - 1) + 1; */
1016 else if (ln <= lastln)
1017 extrabytes = 5; /* NUMBYTES (ln - 1) + 1; */
1018 else
1019 extrabytes = 0;
1021 line_num.dst_a_line_num_header.dst__header_length.dst_w_length
1022 = 8 + extrabytes;
1024 totsize += write_debug_header
1025 (&line_num.dst_a_line_num_header, "line_num", dosizeonly);
1027 if (ln - lastln > 1)
1029 int lndif = ln - lastln - 1;
1031 /* K_INCR_LINUM (lndif); */
1032 pcline.dst_b_pcline_command = DST_K_INCR_LINUM_L;
1034 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
1035 "line_num (INCR LINUM LONG)",
1036 dosizeonly);
1038 sprintf (buff, "line_num (%d)", lndif);
1039 totsize += write_debug_data4 (lndif, buff, dosizeonly);
1041 else if (ln <= lastln)
1043 /* K_SET_LINUM (ln-1); */
1044 pcline.dst_b_pcline_command = DST_K_SET_LINUM_L;
1046 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
1047 "line_num (SET LINUM LONG)",
1048 dosizeonly);
1050 sprintf (buff, "line_num (%d)", ln - 1);
1051 totsize += write_debug_data4 (ln - 1, buff, dosizeonly);
1054 pcline.dst_b_pcline_command = DST_K_DELTA_PC_L;
1056 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
1057 "line_num (DELTA PC LONG)", dosizeonly);
1059 ASM_GENERATE_INTERNAL_LABEL (label, LINE_CODE_LABEL, i);
1060 totsize += write_debug_delta4 (label, lastlabel, "increment line_num",
1061 dosizeonly);
1063 lastln = ln;
1064 strcpy (lastlabel, label);
1067 return totsize;
1070 /* Output a source correlation for file FILEID using information saved in
1071 FILE_INFO_ENTRY and return the size. Just return the size if DOSIZEONLY is
1072 non-zero. */
1074 static int
1075 write_srccorr (fileid, file_info_entry, dosizeonly)
1076 int fileid;
1077 dst_file_info_entry file_info_entry;
1078 int dosizeonly;
1080 int src_command_size;
1081 int linesleft = file_info_entry.max_line;
1082 int linestart = file_info_entry.listing_line_start;
1083 int flen = file_info_entry.flen;
1084 int linestodo = 0;
1085 DST_SOURCE_CORR src_header;
1086 DST_SRC_COMMAND src_command;
1087 DST_SRC_COMMAND src_command_sf;
1088 DST_SRC_COMMAND src_command_sl;
1089 DST_SRC_COMMAND src_command_sr;
1090 DST_SRC_COMMAND src_command_dl;
1091 DST_SRC_CMDTRLR src_cmdtrlr;
1092 char buff[256];
1093 int totsize = 0;
1095 if (fileid == 1)
1097 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1098 = DST_K_SOURCE_CORR_HEADER_SIZE + 1 - 1;
1099 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1100 = DST_K_SOURCE;
1101 src_command.dst_b_src_command = DST_K_SRC_FORMFEED;
1103 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1104 "source corr", dosizeonly);
1106 totsize += write_debug_data1 (src_command.dst_b_src_command,
1107 "source_corr (SRC FORMFEED)",
1108 dosizeonly);
1111 src_command_size
1112 = DST_K_SRC_COMMAND_SIZE + flen + DST_K_SRC_CMDTRLR_SIZE;
1113 src_command.dst_b_src_command = DST_K_SRC_DECLFILE;
1114 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_length
1115 = src_command_size - 2;
1116 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_flags = 0;
1117 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_fileid
1118 = fileid;
1119 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt
1120 = file_info_entry.cdt;
1121 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk
1122 = file_info_entry.ebk;
1123 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_rms_ffb
1124 = file_info_entry.ffb;
1125 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_rms_rfo
1126 = file_info_entry.rfo;
1127 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename
1128 = file_info_entry.flen;
1130 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1131 = DST_K_SOURCE_CORR_HEADER_SIZE + src_command_size - 1;
1132 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1133 = DST_K_SOURCE;
1135 src_cmdtrlr.dst_b_src_df_libmodname = 0;
1137 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1138 "source corr", dosizeonly);
1139 totsize += write_debug_data1 (src_command.dst_b_src_command,
1140 "source_corr (DECL SRC FILE)", dosizeonly);
1141 totsize += write_debug_data1
1142 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_length,
1143 "source_corr (length)", dosizeonly);
1145 totsize += write_debug_data1
1146 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_flags,
1147 "source_corr (flags)", dosizeonly);
1149 totsize += write_debug_data2
1150 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_fileid,
1151 "source_corr (fileid)", dosizeonly);
1153 totsize += write_debug_data8
1154 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt,
1155 "source_corr (creation date)", dosizeonly);
1157 totsize += write_debug_data4
1158 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk,
1159 "source_corr (EOF block number)", dosizeonly);
1161 totsize += write_debug_data2
1162 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_rms_ffb,
1163 "source_corr (first free byte)", dosizeonly);
1165 totsize += write_debug_data1
1166 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_rms_rfo,
1167 "source_corr (record and file organization)", dosizeonly);
1169 totsize += write_debug_data1
1170 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename,
1171 "source_corr (filename length)", dosizeonly);
1173 totsize += write_debug_string (file_info_entry.file_name,
1174 "source file name", dosizeonly);
1175 totsize += write_debug_data1 (src_cmdtrlr.dst_b_src_df_libmodname,
1176 "source_corr (libmodname)", dosizeonly);
1178 src_command_sf.dst_b_src_command = DST_K_SRC_SETFILE;
1179 src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword = fileid;
1181 src_command_sr.dst_b_src_command = DST_K_SRC_SETREC_W;
1182 src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword = 1;
1184 src_command_sl.dst_b_src_command = DST_K_SRC_SETLNUM_L;
1185 src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong = linestart + 1;
1187 src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W;
1189 if (linesleft > 65534)
1190 linesleft = linesleft - 65534, linestodo = 65534;
1191 else
1192 linestodo = linesleft, linesleft = 0;
1194 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo;
1196 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1197 = DST_K_SOURCE_CORR_HEADER_SIZE + 3 + 3 + 5 + 3 - 1;
1198 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1199 = DST_K_SOURCE;
1201 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1202 "source corr", dosizeonly);
1204 totsize += write_debug_data1 (src_command_sf.dst_b_src_command,
1205 "source_corr (src setfile)", dosizeonly);
1207 totsize += write_debug_data2
1208 (src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword,
1209 "source_corr (fileid)", dosizeonly);
1211 totsize += write_debug_data1 (src_command_sr.dst_b_src_command,
1212 "source_corr (setrec)", dosizeonly);
1214 totsize += write_debug_data2
1215 (src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword,
1216 "source_corr (recnum)", dosizeonly);
1218 totsize += write_debug_data1 (src_command_sl.dst_b_src_command,
1219 "source_corr (setlnum)", dosizeonly);
1221 totsize += write_debug_data4
1222 (src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong,
1223 "source_corr (linenum)", dosizeonly);
1225 totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
1226 "source_corr (deflines)", dosizeonly);
1228 sprintf (buff, "source_corr (%d)",
1229 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
1230 totsize += write_debug_data2
1231 (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword, buff, dosizeonly);
1233 while (linesleft > 0)
1235 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1236 = DST_K_SOURCE_CORR_HEADER_SIZE + 3 - 1;
1237 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1238 = DST_K_SOURCE;
1239 src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W;
1241 if (linesleft > 65534)
1242 linesleft = linesleft - 65534, linestodo = 65534;
1243 else
1244 linestodo = linesleft, linesleft = 0;
1246 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo;
1248 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1249 "source corr", dosizeonly);
1250 totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
1251 "source_corr (deflines)", dosizeonly);
1252 sprintf (buff, "source_corr (%d)",
1253 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
1254 totsize += write_debug_data2
1255 (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword,
1256 buff, dosizeonly);
1259 return totsize;
1262 /* Output all the source correlation entries and return the size. Just return
1263 the size if DOSIZEONLY is non-zero. */
1265 static int
1266 write_srccorrs (dosizeonly)
1267 int dosizeonly;
1269 unsigned int i;
1270 int totsize = 0;
1272 for (i = 1; i < file_info_table_in_use; i++)
1273 totsize += write_srccorr (i, file_info_table[i], dosizeonly);
1275 return totsize;
1278 /* Output a marker (i.e. a label) for the beginning of a function, before
1279 the prologue. */
1281 static void
1282 vmsdbgout_begin_prologue (line, file)
1283 unsigned int line;
1284 const char *file;
1286 char label[MAX_ARTIFICIAL_LABEL_BYTES];
1288 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1289 (*dwarf2_debug_hooks.begin_prologue) (line, file);
1291 if (debug_info_level > DINFO_LEVEL_NONE)
1293 current_funcdef_number++;
1294 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL,
1295 current_funcdef_number);
1296 ASM_OUTPUT_LABEL (asm_out_file, label);
1300 /* Output a marker (i.e. a label) for the beginning of a function, after
1301 the prologue. */
1303 void
1304 vmsdbgout_after_prologue ()
1306 char label[MAX_ARTIFICIAL_LABEL_BYTES];
1308 if (debug_info_level > DINFO_LEVEL_TERSE)
1310 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL,
1311 current_funcdef_number);
1312 ASM_OUTPUT_LABEL (asm_out_file, label);
1316 /* Output a marker (i.e. a label) for the absolute end of the generated code
1317 for a function definition. This gets called *after* the epilogue code has
1318 been generated. */
1320 static void
1321 vmsdbgout_end_epilogue ()
1323 char label[MAX_ARTIFICIAL_LABEL_BYTES];
1325 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1326 (*dwarf2_debug_hooks.end_epilogue) ();
1328 if (debug_info_level > DINFO_LEVEL_NONE)
1330 /* Output a label to mark the endpoint of the code generated for this
1331 function. */
1332 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL,
1333 current_funcdef_number);
1334 ASM_OUTPUT_LABEL (asm_out_file, label);
1338 /* Output a marker (i.e. a label) for the beginning of the generated code for
1339 a lexical block. */
1341 static void
1342 vmsdbgout_begin_block (line, blocknum)
1343 register unsigned line;
1344 register unsigned blocknum;
1346 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1347 (*dwarf2_debug_hooks.begin_block) (line, blocknum);
1349 if (debug_info_level > DINFO_LEVEL_TERSE)
1350 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BLOCK_BEGIN_LABEL, blocknum);
1353 /* Output a marker (i.e. a label) for the end of the generated code for a
1354 lexical block. */
1356 static void
1357 vmsdbgout_end_block (line, blocknum)
1358 register unsigned line;
1359 register unsigned blocknum;
1361 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1362 (*dwarf2_debug_hooks.end_block) (line, blocknum);
1364 if (debug_info_level > DINFO_LEVEL_TERSE)
1365 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BLOCK_END_LABEL, blocknum);
1368 /* Not implemented in VMS Debug. */
1370 static bool
1371 vmsdbgout_ignore_block (block)
1372 tree block;
1374 bool retval = 0;
1376 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1377 retval = (*dwarf2_debug_hooks.ignore_block) (block);
1379 return retval;
1382 /* Add an entry for function DECL into the func_table. */
1384 static void
1385 vmsdbgout_begin_function (decl)
1386 tree decl;
1388 const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
1390 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1391 (*dwarf2_debug_hooks.begin_function) (decl);
1393 if (func_table_in_use == func_table_allocated)
1395 func_table_allocated += FUNC_TABLE_INCREMENT;
1396 func_table = (char **) xrealloc (func_table,
1397 func_table_allocated * sizeof (char *));
1400 /* Add the new entry to the end of the function name table. */
1401 func_table[func_table_in_use++] = xstrdup (name);
1404 static char fullname_buff [4096];
1406 /* Return the full file specification for FILENAME. The specification must be
1407 in VMS syntax in order to be processed by VMS Debug. */
1409 static char *
1410 full_name (filename)
1411 const char *filename;
1413 #ifdef VMS
1414 FILE *fp = fopen (filename, "r");
1416 fgetname (fp, fullname_buff, 1);
1417 fclose (fp);
1418 #else
1419 getcwd (fullname_buff, sizeof (fullname_buff));
1421 strcat (fullname_buff, "/");
1422 strcat (fullname_buff, filename);
1424 /* ??? Insert hairy code here to translate Unix style file specification
1425 to VMS style. */
1426 #endif
1428 return fullname_buff;
1431 /* Lookup a filename (in the list of filenames that we know about here in
1432 vmsdbgout.c) and return its "index". The index of each (known) filename is
1433 just a unique number which is associated with only that one filename. We
1434 need such numbers for the sake of generating labels and references
1435 to those files numbers. If the filename given as an argument is not
1436 found in our current list, add it to the list and assign it the next
1437 available unique index number. In order to speed up searches, we remember
1438 the index of the filename was looked up last. This handles the majority of
1439 all searches. */
1441 static unsigned int
1442 lookup_filename (file_name)
1443 const char *file_name;
1445 static unsigned int last_file_lookup_index = 0;
1446 register char *fn;
1447 register unsigned i;
1448 char *fnam;
1449 long long cdt;
1450 long ebk;
1451 short ffb;
1452 char rfo;
1453 char flen;
1454 struct stat statbuf;
1456 if (stat (file_name, &statbuf) == 0)
1458 long gmtoff;
1459 #ifdef VMS
1460 struct tm *ts;
1462 /* Adjust for GMT */
1463 ts = (struct tm *) localtime (&statbuf.st_ctime);
1464 gmtoff = ts->tm_gmtoff;
1466 /* VMS has multiple file format types */
1467 rfo = statbuf.st_fab_rfm;
1468 #else
1469 /* Is GMT adjustment an issue with a cross-compiler? */
1470 gmtoff = 0;
1472 /* Assume stream LF type file */
1473 rfo = 2;
1474 #endif
1475 cdt = 10000000 * (statbuf.st_ctime + gmtoff + vms_epoch_offset);
1476 ebk = statbuf.st_size / 512 + 1;
1477 ffb = statbuf.st_size - ((statbuf.st_size / 512) * 512);
1478 fnam = full_name (file_name);
1479 flen = strlen (fnam);
1481 else
1483 cdt = 0;
1484 ebk = 0;
1485 ffb = 0;
1486 rfo = 0;
1487 fnam = (char *) "";
1488 flen = 0;
1491 /* Check to see if the file name that was searched on the previous call
1492 matches this file name. If so, return the index. */
1493 if (last_file_lookup_index != 0)
1495 fn = file_info_table[last_file_lookup_index].file_name;
1496 if (strcmp (fnam, fn) == 0)
1497 return last_file_lookup_index;
1500 /* Didn't match the previous lookup, search the table */
1501 for (i = 1; i < file_info_table_in_use; ++i)
1503 fn = file_info_table[i].file_name;
1504 if (strcmp (fnam, fn) == 0)
1506 last_file_lookup_index = i;
1507 return i;
1511 /* Prepare to add a new table entry by making sure there is enough space in
1512 the table to do so. If not, expand the current table. */
1513 if (file_info_table_in_use == file_info_table_allocated)
1516 file_info_table_allocated += FILE_TABLE_INCREMENT;
1517 file_info_table
1518 = (dst_file_info_ref) xrealloc (file_info_table,
1519 (file_info_table_allocated
1520 * sizeof (dst_file_info_entry)));
1523 /* Add the new entry to the end of the filename table. */
1524 file_info_table[file_info_table_in_use].file_name = xstrdup (fnam);
1525 file_info_table[file_info_table_in_use].max_line = 0;
1526 file_info_table[file_info_table_in_use].cdt = cdt;
1527 file_info_table[file_info_table_in_use].ebk = ebk;
1528 file_info_table[file_info_table_in_use].ffb = ffb;
1529 file_info_table[file_info_table_in_use].rfo = rfo;
1530 file_info_table[file_info_table_in_use].flen = flen;
1532 last_file_lookup_index = file_info_table_in_use++;
1533 return last_file_lookup_index;
1536 /* Output a label to mark the beginning of a source code line entry
1537 and record information relating to this source line, in
1538 'line_info_table' for later output of the .debug_line section. */
1540 static void
1541 vmsdbgout_source_line (line, filename)
1542 register unsigned line;
1543 register const char *filename;
1545 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1546 (*dwarf2_debug_hooks.source_line) (line, filename);
1548 if (debug_info_level >= DINFO_LEVEL_TERSE)
1550 dst_line_info_ref line_info;
1552 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, LINE_CODE_LABEL,
1553 line_info_table_in_use);
1555 /* Expand the line info table if necessary. */
1556 if (line_info_table_in_use == line_info_table_allocated)
1558 line_info_table_allocated += LINE_INFO_TABLE_INCREMENT;
1559 line_info_table
1560 = (dst_line_info_ref) xrealloc (line_info_table,
1561 (line_info_table_allocated
1562 * sizeof (dst_line_info_entry)));
1565 /* Add the new entry at the end of the line_info_table. */
1566 line_info = &line_info_table[line_info_table_in_use++];
1567 line_info->dst_file_num = lookup_filename (filename);
1568 line_info->dst_line_num = line;
1569 if (line > file_info_table[line_info->dst_file_num].max_line)
1570 file_info_table[line_info->dst_file_num].max_line = line;
1574 /* Record the beginning of a new source file, for later output.
1575 At present, unimplemented. */
1577 static void
1578 vmsdbgout_start_source_file (lineno, filename)
1579 unsigned int lineno;
1580 const char *filename;
1582 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1583 (*dwarf2_debug_hooks.start_source_file) (lineno, filename);
1586 /* Record the end of a source file, for later output.
1587 At present, unimplemented. */
1589 static void
1590 vmsdbgout_end_source_file (lineno)
1591 unsigned int lineno ATTRIBUTE_UNUSED;
1593 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1594 (*dwarf2_debug_hooks.end_source_file) (lineno);
1597 /* Set up for Debug output at the start of compilation. */
1599 static void
1600 vmsdbgout_init (main_input_filename)
1601 const char *main_input_filename;
1603 const char *language_string = lang_hooks.name;
1605 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1606 (*dwarf2_debug_hooks.init) (main_input_filename);
1608 if (debug_info_level == DINFO_LEVEL_NONE)
1609 return;
1611 /* Remember the name of the primary input file. */
1612 primary_filename = main_input_filename;
1614 /* Allocate the initial hunk of the file_info_table. */
1615 file_info_table
1616 = (dst_file_info_ref) xcalloc (FILE_TABLE_INCREMENT,
1617 sizeof (dst_file_info_entry));
1618 file_info_table_allocated = FILE_TABLE_INCREMENT;
1620 /* Skip the first entry - file numbers begin at 1 */
1621 file_info_table_in_use = 1;
1623 func_table = (char **) xcalloc (FUNC_TABLE_INCREMENT, sizeof (char *));
1624 func_table_allocated = FUNC_TABLE_INCREMENT;
1625 func_table_in_use = 1;
1627 /* Allocate the initial hunk of the line_info_table. */
1628 line_info_table
1629 = (dst_line_info_ref) xcalloc (LINE_INFO_TABLE_INCREMENT,
1630 sizeof (dst_line_info_entry));
1631 line_info_table_allocated = LINE_INFO_TABLE_INCREMENT;
1632 /* zero-th entry is allocated, but unused */
1633 line_info_table_in_use = 1;
1635 lookup_filename (primary_filename);
1637 if (!strcmp (language_string, "GNU C"))
1638 module_language = DST_K_C;
1639 else if (!strcmp (language_string, "GNU C++"))
1640 module_language = DST_K_CXX;
1641 else if (!strcmp (language_string, "GNU Ada"))
1642 module_language = DST_K_ADA;
1643 else if (!strcmp (language_string, "GNU F77"))
1644 module_language = DST_K_FORTRAN;
1645 else
1646 module_language = DST_K_UNKNOWN;
1648 module_producer
1649 = (char *) xmalloc (strlen (language_string) + 1
1650 + strlen (version_string) + 1);
1651 sprintf (module_producer, "%s %s", language_string, version_string);
1653 ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
1657 /* Not implemented in VMS Debug. */
1659 static void
1660 vmsdbgout_define (lineno, buffer)
1661 unsigned int lineno;
1662 const char *buffer;
1664 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1665 (*dwarf2_debug_hooks.define) (lineno, buffer);
1668 /* Not implemented in VMS Debug. */
1670 static void
1671 vmsdbgout_undef (lineno, buffer)
1672 unsigned int lineno;
1673 const char *buffer;
1675 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1676 (*dwarf2_debug_hooks.undef) (lineno, buffer);
1679 /* Not implemented in VMS Debug. */
1681 static void
1682 vmsdbgout_decl (decl)
1683 tree decl;
1685 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1686 (*dwarf2_debug_hooks.function_decl) (decl);
1689 /* Not implemented in VMS Debug. */
1691 static void
1692 vmsdbgout_global_decl (decl)
1693 tree decl;
1695 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1696 (*dwarf2_debug_hooks.global_decl) (decl);
1699 /* Not implemented in VMS Debug. */
1701 static void
1702 vmsdbgout_abstract_function (decl)
1703 tree decl;
1705 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1706 (*dwarf2_debug_hooks.outlining_inline_function) (decl);
1709 /* Output stuff that Debug requires at the end of every file and generate the
1710 VMS Debug debugging info. */
1712 static void
1713 vmsdbgout_finish (input_filename)
1714 const char *input_filename ATTRIBUTE_UNUSED;
1716 unsigned int i;
1717 int totsize;
1719 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1720 (*dwarf2_debug_hooks.finish) (input_filename);
1722 if (debug_info_level == DINFO_LEVEL_NONE)
1723 return;
1725 /* Output a terminator label for the .text section. */
1726 text_section ();
1727 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, TEXT_END_LABEL, 0);
1729 /* Output debugging information.
1730 Warning! Do not change the name of the .vmsdebug section without
1731 changing it in the assembler also. */
1732 named_section (NULL_TREE, ".vmsdebug", 0);
1733 ASM_OUTPUT_ALIGN (asm_out_file, 0);
1735 totsize = write_modbeg (1);
1736 for (i = 1; i < func_table_in_use; i++)
1738 totsize += write_rtnbeg (i, 1);
1739 totsize += write_rtnend (i, 1);
1741 totsize += write_pclines (1);
1743 write_modbeg (0);
1744 for (i = 1; i < func_table_in_use; i++)
1746 write_rtnbeg (i, 0);
1747 write_rtnend (i, 0);
1749 write_pclines (0);
1751 if (debug_info_level > DINFO_LEVEL_TERSE)
1753 totsize = write_srccorrs (1);
1754 write_srccorrs (0);
1757 totsize = write_modend (1);
1758 write_modend (0);
1760 #endif /* VMS_DEBUGGING_INFO */