Daily bump.
[official-gcc.git] / gcc / vmsdbgout.c
blob7332389cf63a4304506b23163892d709763c8cff
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 CHAR_TYPE_SIZE
83 #define CHAR_TYPE_SIZE BITS_PER_UNIT
84 #endif
85 #ifndef PTR_SIZE
86 #define PTR_SIZE 4 /* Must be 32 bits for VMS debug info */
87 #endif
89 /* Pointer to an structure of filenames referenced by this compilation unit. */
90 static dst_file_info_ref file_info_table;
92 /* Total number of entries in the table (i.e. array) pointed to by
93 `file_info_table'. This is the *total* and includes both used and unused
94 slots. */
95 static unsigned int file_info_table_allocated;
97 /* Number of entries in the file_info_table which are actually in use. */
98 static unsigned int file_info_table_in_use;
100 /* Size (in elements) of increments by which we may expand the filename
101 table. */
102 #define FILE_TABLE_INCREMENT 64
104 static char **func_table;
105 static unsigned int func_table_allocated;
106 static unsigned int func_table_in_use;
107 #define FUNC_TABLE_INCREMENT 256
109 /* Local pointer to the name of the main input file. Initialized in
110 avmdbgout_init. */
111 static const char *primary_filename;
113 static char *module_producer;
114 static unsigned int module_language;
116 /* A pointer to the base of a table that contains line information
117 for each source code line in .text in the compilation unit. */
118 static dst_line_info_ref line_info_table;
120 /* Number of elements currently allocated for line_info_table. */
121 static unsigned int line_info_table_allocated;
123 /* Number of elements in line_info_table currently in use. */
124 static unsigned int line_info_table_in_use;
126 /* Size (in elements) of increments by which we may expand line_info_table. */
127 #define LINE_INFO_TABLE_INCREMENT 1024
129 /* The number of the current function definition for which debugging
130 information is being generated. These numbers range from 1 up to the
131 maximum number of function definitions contained within the current
132 compilation unit. These numbers are used to create unique label id's unique
133 to each function definition. */
134 static unsigned int current_funcdef_number = 0;
136 /* Forward declarations for functions defined in this file. */
137 static char *full_name PARAMS ((const char *));
138 static unsigned int lookup_filename PARAMS ((const char *));
139 static void addr_const_to_string PARAMS ((char *, rtx));
140 static int write_debug_header PARAMS ((DST_HEADER *, const char *, int));
141 static int write_debug_addr PARAMS ((char *, const char *, int));
142 static int write_debug_data1 PARAMS ((unsigned int, const char *, int));
143 static int write_debug_data2 PARAMS ((unsigned int, const char *, int));
144 static int write_debug_data4 PARAMS ((unsigned long, const char *, int));
145 static int write_debug_data8 PARAMS ((unsigned long long, const char *,
146 int));
147 static int write_debug_delta4 PARAMS ((char *, char *, const char *, int));
148 static int write_debug_string PARAMS ((char *, const char *, int));
149 static int write_modbeg PARAMS ((int));
150 static int write_modend PARAMS ((int));
151 static int write_rtnbeg PARAMS ((int, int));
152 static int write_rtnend PARAMS ((int, int));
153 static int write_pclines PARAMS ((int));
154 static int write_srccorr PARAMS ((int, dst_file_info_entry, int));
155 static int write_srccorrs PARAMS ((int));
157 static void vmsdbgout_init PARAMS ((const char *));
158 static void vmsdbgout_finish PARAMS ((const char *));
159 static void vmsdbgout_define PARAMS ((unsigned int, const char *));
160 static void vmsdbgout_undef PARAMS ((unsigned int, const char *));
161 static void vmsdbgout_start_source_file PARAMS ((unsigned int, const char *));
162 static void vmsdbgout_end_source_file PARAMS ((unsigned int));
163 static void vmsdbgout_begin_block PARAMS ((unsigned int, unsigned int));
164 static void vmsdbgout_end_block PARAMS ((unsigned int, unsigned int));
165 static bool vmsdbgout_ignore_block PARAMS ((tree));
166 static void vmsdbgout_source_line PARAMS ((unsigned int, const char *));
167 static void vmsdbgout_begin_prologue PARAMS ((unsigned int, const char *));
168 static void vmsdbgout_end_epilogue PARAMS ((void));
169 static void vmsdbgout_begin_function PARAMS ((tree));
170 static void vmsdbgout_decl PARAMS ((tree));
171 static void vmsdbgout_global_decl PARAMS ((tree));
172 static void vmsdbgout_abstract_function PARAMS ((tree));
174 /* The debug hooks structure. */
176 struct gcc_debug_hooks vmsdbg_debug_hooks
177 = {vmsdbgout_init,
178 vmsdbgout_finish,
179 vmsdbgout_define,
180 vmsdbgout_undef,
181 vmsdbgout_start_source_file,
182 vmsdbgout_end_source_file,
183 vmsdbgout_begin_block,
184 vmsdbgout_end_block,
185 vmsdbgout_ignore_block,
186 vmsdbgout_source_line,
187 vmsdbgout_begin_prologue,
188 debug_nothing_int, /* end_prologue */
189 vmsdbgout_end_epilogue, /* end_epilogue */
190 vmsdbgout_begin_function, /* begin_function */
191 debug_nothing_int, /* end_function */
192 vmsdbgout_decl,
193 vmsdbgout_global_decl,
194 debug_nothing_tree, /* deferred_inline_function */
195 vmsdbgout_abstract_function,
196 debug_nothing_rtx /* label */
199 /* Definitions of defaults for assembler-dependent names of various
200 pseudo-ops and section names.
201 Theses may be overridden in the tm.h file (if necessary) for a particular
202 assembler. */
203 #ifdef UNALIGNED_SHORT_ASM_OP
204 #undef UNALIGNED_SHORT_ASM_OP
205 #endif
206 #define UNALIGNED_SHORT_ASM_OP ".word"
208 #ifdef UNALIGNED_INT_ASM_OP
209 #undef UNALIGNED_INT_ASM_OP
210 #endif
211 #define UNALIGNED_INT_ASM_OP ".long"
213 #ifdef UNALIGNED_LONG_ASM_OP
214 #undef UNALIGNED_LONG_ASM_OP
215 #endif
216 #define UNALIGNED_LONG_ASM_OP ".long"
218 #ifdef UNALIGNED_DOUBLE_INT_ASM_OP
219 #undef UNALIGNED_DOUBLE_INT_ASM_OP
220 #endif
221 #define UNALIGNED_DOUBLE_INT_ASM_OP ".quad"
223 #ifdef ASM_BYTE_OP
224 #undef ASM_BYTE_OP
225 #endif
226 #define ASM_BYTE_OP ".byte"
228 #define NUMBYTES(I) ((I) < 256 ? 1 : (I) < 65536 ? 2 : 4)
230 #define NUMBYTES0(I) ((I) < 128 ? 0 : (I) < 65536 ? 2 : 4)
232 #ifndef UNALIGNED_PTR_ASM_OP
233 #define UNALIGNED_PTR_ASM_OP \
234 (PTR_SIZE == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP : UNALIGNED_INT_ASM_OP)
235 #endif
237 #ifndef UNALIGNED_OFFSET_ASM_OP
238 #define UNALIGNED_OFFSET_ASM_OP(OFFSET) \
239 (NUMBYTES(OFFSET) == 4 \
240 ? UNALIGNED_LONG_ASM_OP \
241 : (NUMBYTES(OFFSET) == 2 ? UNALIGNED_SHORT_ASM_OP : ASM_BYTE_OP))
242 #endif
244 /* Pseudo-op for defining a new section. */
245 #ifndef SECTION_ASM_OP
246 #define SECTION_ASM_OP ".section"
247 #endif
249 /* Definitions of defaults for formats and names of various special
250 (artificial) labels which may be generated within this file (when the -g
251 options is used and VMS_DEBUGGING_INFO is in effect. If necessary, these
252 may be overridden from within the tm.h file, but typically, overriding these
253 defaults is unnecessary. */
255 static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
257 #ifndef TEXT_END_LABEL
258 #define TEXT_END_LABEL "Lvetext"
259 #endif
260 #ifndef FUNC_BEGIN_LABEL
261 #define FUNC_BEGIN_LABEL "LVFB"
262 #endif
263 #ifndef FUNC_PROLOG_LABEL
264 #define FUNC_PROLOG_LABEL "LVFP"
265 #endif
266 #ifndef FUNC_END_LABEL
267 #define FUNC_END_LABEL "LVFE"
268 #endif
269 #ifndef BLOCK_BEGIN_LABEL
270 #define BLOCK_BEGIN_LABEL "LVBB"
271 #endif
272 #ifndef BLOCK_END_LABEL
273 #define BLOCK_END_LABEL "LVBE"
274 #endif
275 #ifndef LINE_CODE_LABEL
276 #define LINE_CODE_LABEL "LVM"
277 #endif
279 #ifndef ASM_OUTPUT_DEBUG_DELTA2
280 #define ASM_OUTPUT_DEBUG_DELTA2(FILE,LABEL1,LABEL2) \
281 do \
283 fprintf ((FILE), "\t%s\t", UNALIGNED_SHORT_ASM_OP); \
284 assemble_name (FILE, LABEL1); \
285 fprintf (FILE, "-"); \
286 assemble_name (FILE, LABEL2); \
288 while (0)
289 #endif
291 #ifndef ASM_OUTPUT_DEBUG_DELTA4
292 #define ASM_OUTPUT_DEBUG_DELTA4(FILE,LABEL1,LABEL2) \
293 do \
295 fprintf ((FILE), "\t%s\t", UNALIGNED_INT_ASM_OP); \
296 assemble_name (FILE, LABEL1); \
297 fprintf (FILE, "-"); \
298 assemble_name (FILE, LABEL2); \
300 while (0)
301 #endif
303 #ifndef ASM_OUTPUT_DEBUG_ADDR_DELTA
304 #define ASM_OUTPUT_DEBUG_ADDR_DELTA(FILE,LABEL1,LABEL2) \
305 do \
307 fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP); \
308 assemble_name (FILE, LABEL1); \
309 fprintf (FILE, "-"); \
310 assemble_name (FILE, LABEL2); \
312 while (0)
313 #endif
315 #ifndef ASM_OUTPUT_DEBUG_ADDR
316 #define ASM_OUTPUT_DEBUG_ADDR(FILE,LABEL) \
317 do \
319 fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP); \
320 assemble_name (FILE, LABEL); \
322 while (0)
323 #endif
325 #ifndef ASM_OUTPUT_DEBUG_ADDR_CONST
326 #define ASM_OUTPUT_DEBUG_ADDR_CONST(FILE,ADDR) \
327 fprintf ((FILE), "\t%s\t%s", UNALIGNED_PTR_ASM_OP, (ADDR))
328 #endif
330 #ifndef ASM_OUTPUT_DEBUG_DATA1
331 #define ASM_OUTPUT_DEBUG_DATA1(FILE,VALUE) \
332 fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, (unsigned char) VALUE)
333 #endif
335 #ifndef ASM_OUTPUT_DEBUG_DATA2
336 #define ASM_OUTPUT_DEBUG_DATA2(FILE,VALUE) \
337 fprintf ((FILE), "\t%s\t0x%x", UNALIGNED_SHORT_ASM_OP, \
338 (unsigned short) VALUE)
339 #endif
341 #ifndef ASM_OUTPUT_DEBUG_DATA4
342 #define ASM_OUTPUT_DEBUG_DATA4(FILE,VALUE) \
343 fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_INT_ASM_OP, (unsigned long) VALUE)
344 #endif
346 #ifndef ASM_OUTPUT_DEBUG_DATA
347 #define ASM_OUTPUT_DEBUG_DATA(FILE,VALUE) \
348 fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_OFFSET_ASM_OP(VALUE), VALUE)
349 #endif
351 #ifndef ASM_OUTPUT_DEBUG_ADDR_DATA
352 #define ASM_OUTPUT_DEBUG_ADDR_DATA(FILE,VALUE) \
353 fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_PTR_ASM_OP, \
354 (unsigned long) VALUE)
355 #endif
357 #ifndef ASM_OUTPUT_DEBUG_DATA8
358 #define ASM_OUTPUT_DEBUG_DATA8(FILE,VALUE) \
359 fprintf ((FILE), "\t%s\t0x%llx", UNALIGNED_DOUBLE_INT_ASM_OP, \
360 (unsigned long long) VALUE)
361 #endif
363 /* This is similar to the default ASM_OUTPUT_ASCII, except that no trailing
364 newline is produced. When flag_verbose_asm is asserted, we add commnetary
365 at the end of the line, so we must avoid output of a newline here. */
366 #ifndef ASM_OUTPUT_DEBUG_STRING
367 #define ASM_OUTPUT_DEBUG_STRING(FILE,P) \
368 do \
370 register int slen = strlen(P); \
371 register char *p = (P); \
372 register int i; \
373 fprintf (FILE, "\t.ascii \""); \
374 for (i = 0; i < slen; i++) \
376 register int c = p[i]; \
377 if (c == '\"' || c == '\\') \
378 putc ('\\', FILE); \
379 if (c >= ' ' && c < 0177) \
380 putc (c, FILE); \
381 else \
382 fprintf (FILE, "\\%o", c); \
384 fprintf (FILE, "\""); \
386 while (0)
387 #endif
389 /* Convert a reference to the assembler name of a C-level name. This
390 macro has the same effect as ASM_OUTPUT_LABELREF, but copies to
391 a string rather than writing to a file. */
392 #ifndef ASM_NAME_TO_STRING
393 #define ASM_NAME_TO_STRING(STR, NAME) \
394 do \
396 if ((NAME)[0] == '*') \
397 strcpy (STR, NAME+1); \
398 else \
399 strcpy (STR, NAME); \
401 while (0)
402 #endif
405 /* General utility functions. */
407 /* Convert an integer constant expression into assembler syntax. Addition and
408 subtraction are the only arithmetic that may appear in these expressions.
409 This is an adaptation of output_addr_const in final.c. Here, the target
410 of the conversion is a string buffer. We can't use output_addr_const
411 directly, because it writes to a file. */
413 static void
414 addr_const_to_string (str, x)
415 char *str;
416 rtx x;
418 char buf1[256];
419 char buf2[256];
421 restart:
422 str[0] = '\0';
423 switch (GET_CODE (x))
425 case PC:
426 if (flag_pic)
427 strcat (str, ",");
428 else
429 abort ();
430 break;
432 case SYMBOL_REF:
433 ASM_NAME_TO_STRING (buf1, XSTR (x, 0));
434 strcat (str, buf1);
435 break;
437 case LABEL_REF:
438 ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
439 ASM_NAME_TO_STRING (buf2, buf1);
440 strcat (str, buf2);
441 break;
443 case CODE_LABEL:
444 ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (x));
445 ASM_NAME_TO_STRING (buf2, buf1);
446 strcat (str, buf2);
447 break;
449 case CONST_INT:
450 sprintf (buf1, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
451 strcat (str, buf1);
452 break;
454 case CONST:
455 /* This used to output parentheses around the expression, but that does
456 not work on the 386 (either ATT or BSD assembler). */
457 addr_const_to_string (buf1, XEXP (x, 0));
458 strcat (str, buf1);
459 break;
461 case CONST_DOUBLE:
462 if (GET_MODE (x) == VOIDmode)
464 /* We can use %d if the number is one word and positive. */
465 if (CONST_DOUBLE_HIGH (x))
466 sprintf (buf1, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
467 CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
468 else if (CONST_DOUBLE_LOW (x) < 0)
469 sprintf (buf1, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (x));
470 else
471 sprintf (buf1, HOST_WIDE_INT_PRINT_DEC,
472 CONST_DOUBLE_LOW (x));
473 strcat (str, buf1);
475 else
476 /* We can't handle floating point constants; PRINT_OPERAND must
477 handle them. */
478 output_operand_lossage ("floating constant misused");
479 break;
481 case PLUS:
482 /* Some assemblers need integer constants to appear last (eg masm). */
483 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
485 addr_const_to_string (buf1, XEXP (x, 1));
486 strcat (str, buf1);
487 if (INTVAL (XEXP (x, 0)) >= 0)
488 strcat (str, "+");
489 addr_const_to_string (buf1, XEXP (x, 0));
490 strcat (str, buf1);
492 else
494 addr_const_to_string (buf1, XEXP (x, 0));
495 strcat (str, buf1);
496 if (INTVAL (XEXP (x, 1)) >= 0)
497 strcat (str, "+");
498 addr_const_to_string (buf1, XEXP (x, 1));
499 strcat (str, buf1);
501 break;
503 case MINUS:
504 /* Avoid outputting things like x-x or x+5-x, since some assemblers
505 can't handle that. */
506 x = simplify_subtraction (x);
507 if (GET_CODE (x) != MINUS)
508 goto restart;
510 addr_const_to_string (buf1, XEXP (x, 0));
511 strcat (str, buf1);
512 strcat (str, "-");
513 if (GET_CODE (XEXP (x, 1)) == CONST_INT
514 && INTVAL (XEXP (x, 1)) < 0)
516 strcat (str, "(");
517 addr_const_to_string (buf1, XEXP (x, 1));
518 strcat (str, buf1);
519 strcat (str, ")");
521 else
523 addr_const_to_string (buf1, XEXP (x, 1));
524 strcat (str, buf1);
526 break;
528 case ZERO_EXTEND:
529 case SIGN_EXTEND:
530 addr_const_to_string (buf1, XEXP (x, 0));
531 strcat (str, buf1);
532 break;
534 default:
535 output_operand_lossage ("invalid expression as operand");
539 /* Output the debug header HEADER. Also output COMMENT if flag_verbose_asm is
540 set. Return the header size. Just return the size if DOSIZEONLY is
541 non-zero. */
543 static int
544 write_debug_header (header, comment, dosizeonly)
545 DST_HEADER *header;
546 const char *comment;
547 int dosizeonly;
549 if (!dosizeonly)
551 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file,
552 header->dst__header_length.dst_w_length);
554 if (flag_verbose_asm)
555 fprintf (asm_out_file, "\t%s record length", ASM_COMMENT_START);
556 fputc ('\n', asm_out_file);
558 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file,
559 header->dst__header_type.dst_w_type);
561 if (flag_verbose_asm)
562 fprintf (asm_out_file, "\t%s record type (%s)", ASM_COMMENT_START,
563 comment);
565 fputc ('\n', asm_out_file);
568 return 4;
571 /* Output the address of SYMBOL. Also output COMMENT if flag_verbose_asm is
572 set. Return the address size. Just return the size if DOSIZEONLY is
573 non-zero. */
575 static int
576 write_debug_addr (symbol, comment, dosizeonly)
577 char *symbol;
578 const char *comment;
579 int dosizeonly;
581 if (!dosizeonly)
583 ASM_OUTPUT_DEBUG_ADDR (asm_out_file, symbol);
584 if (flag_verbose_asm)
585 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
586 fputc ('\n', asm_out_file);
589 return PTR_SIZE;
592 /* Output the single byte DATA1. Also output COMMENT if flag_verbose_asm is
593 set. Return the data size. Just return the size if DOSIZEONLY is
594 non-zero. */
596 static int
597 write_debug_data1 (data1, comment, dosizeonly)
598 unsigned int data1;
599 const char *comment;
600 int dosizeonly;
602 if (!dosizeonly)
604 ASM_OUTPUT_DEBUG_DATA1 (asm_out_file, data1);
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 1;
613 /* Output the single word DATA2. Also output COMMENT if flag_verbose_asm is
614 set. Return the data size. Just return the size if DOSIZEONLY is
615 non-zero. */
617 static int
618 write_debug_data2 (data2, comment, dosizeonly)
619 unsigned int data2;
620 const char *comment;
621 int dosizeonly;
623 if (!dosizeonly)
625 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file, data2);
626 if (flag_verbose_asm)
627 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
628 fputc ('\n', asm_out_file);
631 return 2;
634 /* Output double word DATA4. Also output COMMENT if flag_verbose_asm is set.
635 Return the data size. Just return the size if DOSIZEONLY is non-zero. */
637 static int
638 write_debug_data4 (data4, comment, dosizeonly)
639 unsigned long data4;
640 const char *comment;
641 int dosizeonly;
643 if (!dosizeonly)
645 ASM_OUTPUT_DEBUG_DATA4 (asm_out_file, data4);
646 if (flag_verbose_asm)
647 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
648 fputc ('\n', asm_out_file);
651 return 4;
654 /* Output quad word DATA8. Also output COMMENT if flag_verbose_asm is set.
655 Return the data size. Just return the size if DOSIZEONLY is non-zero. */
657 static int
658 write_debug_data8 (data8, comment, dosizeonly)
659 unsigned long long data8;
660 const char *comment;
661 int dosizeonly;
663 if (!dosizeonly)
665 ASM_OUTPUT_DEBUG_DATA8 (asm_out_file, data8);
666 if (flag_verbose_asm)
667 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
668 fputc ('\n', asm_out_file);
671 return 8;
674 /* Output the difference between LABEL1 and LABEL2. Also output COMMENT if
675 flag_verbose_asm is set. Return the data size. Just return the size if
676 DOSIZEONLY is non-zero. */
678 static int
679 write_debug_delta4 (label1, label2, comment, dosizeonly)
680 char *label1;
681 char *label2;
682 const char *comment;
683 int dosizeonly;
685 if (!dosizeonly)
687 ASM_OUTPUT_DEBUG_DELTA4 (asm_out_file, label1, label2);
688 if (flag_verbose_asm)
689 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
690 fputc ('\n', asm_out_file);
693 return 4;
696 /* Output a character string STRING. Also write COMMENT if flag_verbose_asm is
697 set. Return the string length. Just return the length if DOSIZEONLY is
698 non-zero. */
700 static int
701 write_debug_string (string, comment, dosizeonly)
702 char *string;
703 const char *comment;
704 int dosizeonly;
706 if (!dosizeonly)
708 ASM_OUTPUT_DEBUG_STRING (asm_out_file, string);
709 if (flag_verbose_asm)
710 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
711 fputc ('\n', asm_out_file);
714 return strlen (string);
717 /* Output a module begin header and return the header size. Just return the
718 size if DOSIZEONLY is non-zero. */
720 static int
721 write_modbeg (dosizeonly)
722 int dosizeonly;
724 DST_MODULE_BEGIN modbeg;
725 DST_MB_TRLR mb_trlr;
726 int i;
727 char *module_name, *m;
728 int modnamelen;
729 int prodnamelen;
730 int totsize = 0;
732 /* Assumes primary filename has Unix syntax file spec. */
733 module_name = xstrdup (basename ((char *) primary_filename));
735 m = strrchr (module_name, '.');
736 if (m)
737 *m = 0;
739 modnamelen = strlen (module_name);
740 for (i = 0; i < modnamelen; i++)
741 module_name[i] = TOUPPER (module_name[i]);
743 prodnamelen = strlen (module_producer);
745 modbeg.dst_a_modbeg_header.dst__header_length.dst_w_length
746 = DST_K_MODBEG_SIZE + modnamelen + DST_K_MB_TRLR_SIZE + prodnamelen - 1;
747 modbeg.dst_a_modbeg_header.dst__header_type.dst_w_type = DST_K_MODBEG;
748 modbeg.dst_b_modbeg_flags.dst_v_modbeg_hide = 0;
749 modbeg.dst_b_modbeg_flags.dst_v_modbeg_version = 1;
750 modbeg.dst_b_modbeg_flags.dst_v_modbeg_unused = 0;
751 modbeg.dst_b_modbeg_unused = 0;
752 modbeg.dst_l_modbeg_language = module_language;
753 modbeg.dst_w_version_major = DST_K_VERSION_MAJOR;
754 modbeg.dst_w_version_minor = DST_K_VERSION_MINOR;
755 modbeg.dst_b_modbeg_name = strlen (module_name);
757 mb_trlr.dst_b_compiler = strlen (module_producer);
759 totsize += write_debug_header (&modbeg.dst_a_modbeg_header,
760 "modbeg", dosizeonly);
761 totsize += write_debug_data1 (*((char *) &modbeg.dst_b_modbeg_flags),
762 "flags", dosizeonly);
763 totsize += write_debug_data1 (modbeg.dst_b_modbeg_unused,
764 "unused", dosizeonly);
765 totsize += write_debug_data4 (modbeg.dst_l_modbeg_language,
766 "language", dosizeonly);
767 totsize += write_debug_data2 (modbeg.dst_w_version_major,
768 "DST major version", dosizeonly);
769 totsize += write_debug_data2 (modbeg.dst_w_version_minor,
770 "DST minor version", dosizeonly);
771 totsize += write_debug_data1 (modbeg.dst_b_modbeg_name,
772 "length of module name", dosizeonly);
773 totsize += write_debug_string (module_name, "module name", dosizeonly);
774 totsize += write_debug_data1 (mb_trlr.dst_b_compiler,
775 "length of compiler name", dosizeonly);
776 totsize += write_debug_string (module_producer, "compiler name", dosizeonly);
778 return totsize;
781 /* Output a module end trailer and return the trailer size. Just return
782 the size if DOSIZEONLY is non-zero. */
784 static int
785 write_modend (dosizeonly)
786 int dosizeonly;
788 DST_MODULE_END modend;
789 int totsize = 0;
791 modend.dst_a_modend_header.dst__header_length.dst_w_length
792 = DST_K_MODEND_SIZE - 1;
793 modend.dst_a_modend_header.dst__header_type.dst_w_type = DST_K_MODEND;
795 totsize += write_debug_header (&modend.dst_a_modend_header, "modend",
796 dosizeonly);
798 return totsize;
801 /* Output a routine begin header routine RTNNUM and return the header size.
802 Just return the size if DOSIZEONLY is non-zero. */
804 static int
805 write_rtnbeg (rtnnum, dosizeonly)
806 int rtnnum;
807 int dosizeonly;
809 char *rtnname;
810 int rtnnamelen, rtnentrynamelen;
811 char *rtnentryname;
812 int totsize = 0;
813 char label[MAX_ARTIFICIAL_LABEL_BYTES];
814 DST_ROUTINE_BEGIN rtnbeg;
815 DST_PROLOG prolog;
817 rtnname = func_table[rtnnum];
818 rtnnamelen = strlen (rtnname);
819 rtnentrynamelen = rtnnamelen + 4; /* "..en" */
820 rtnentryname = (char *) xmalloc (rtnentrynamelen + 1);
821 strcpy (rtnentryname, rtnname);
822 strcat (rtnentryname, "..en");
824 if (!strcmp (rtnname, "main"))
826 DST_HEADER header;
827 const char *go = "TRANSFER$BREAK$GO";
829 /* This command isn't documented in DSTRECORDS, so it's made to
830 look like what DEC C does */
832 /* header size - 1st byte + flag byte + STO_LW size
833 + string count byte + string length */
834 header.dst__header_length.dst_w_length
835 = DST_K_DST_HEADER_SIZE - 1 + 1 + 4 + 1 + strlen (go);
836 header.dst__header_type.dst_w_type = 0x17;
838 totsize += write_debug_header (&header, "transfer", dosizeonly);
840 /* I think this is a flag byte, but I don't know what this flag means */
841 totsize += write_debug_data1 (0x1, "flags ???", dosizeonly);
843 /* Routine Begin PD Address */
844 totsize += write_debug_addr (rtnname, "main procedure descriptor",
845 dosizeonly);
846 totsize += write_debug_data1 (strlen (go), "length of main_name",
847 dosizeonly);
848 totsize += write_debug_string ((char *) go, "main name", dosizeonly);
851 /* The header length never includes the length byte */
852 rtnbeg.dst_a_rtnbeg_header.dst__header_length.dst_w_length
853 = DST_K_RTNBEG_SIZE + rtnnamelen - 1;
854 rtnbeg.dst_a_rtnbeg_header.dst__header_type.dst_w_type = DST_K_RTNBEG;
855 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_unused = 0;
856 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_unalloc = 0;
857 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_prototype = 0;
858 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_inlined = 0;
859 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_no_call = 1;
860 rtnbeg.dst_b_rtnbeg_name = rtnnamelen;
862 totsize += write_debug_header (&rtnbeg.dst_a_rtnbeg_header, "rtnbeg",
863 dosizeonly);
864 totsize += write_debug_data1 (*((char *) &rtnbeg.dst_b_rtnbeg_flags),
865 "flags", dosizeonly);
867 /* Routine Begin Address */
868 totsize += write_debug_addr (rtnentryname, "routine entry name", dosizeonly);
870 /* Routine Begin PD Address */
871 totsize += write_debug_addr (rtnname, "routine procedure descriptor",
872 dosizeonly);
874 /* Routine Begin Name */
875 totsize += write_debug_data1 (rtnbeg.dst_b_rtnbeg_name,
876 "length of routine name", dosizeonly);
878 totsize += write_debug_string (rtnname, "routine name", dosizeonly);
880 free (rtnentryname);
882 if (debug_info_level > DINFO_LEVEL_TERSE)
884 prolog.dst_a_prolog_header.dst__header_length.dst_w_length
885 = DST_K_PROLOG_SIZE - 1;
886 prolog.dst_a_prolog_header.dst__header_type.dst_w_type = DST_K_PROLOG;
888 totsize += write_debug_header (&prolog.dst_a_prolog_header, "prolog",
889 dosizeonly);
891 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL, rtnnum);
892 totsize += write_debug_addr (label, "prolog breakpoint addr",
893 dosizeonly);
896 return totsize;
899 /* Output a routine end trailer for routine RTNNUM and return the header size.
900 Just return the size if DOSIZEONLY is non-zero. */
902 static int
903 write_rtnend (rtnnum, dosizeonly)
904 int rtnnum;
905 int dosizeonly;
907 DST_ROUTINE_END rtnend;
908 char label1[MAX_ARTIFICIAL_LABEL_BYTES];
909 char label2[MAX_ARTIFICIAL_LABEL_BYTES];
910 int totsize;
912 totsize = 0;
914 rtnend.dst_a_rtnend_header.dst__header_length.dst_w_length
915 = DST_K_RTNEND_SIZE - 1;
916 rtnend.dst_a_rtnend_header.dst__header_type.dst_w_type = DST_K_RTNEND;
917 rtnend.dst_b_rtnend_unused = 0;
918 rtnend.dst_l_rtnend_size = 0; /* Calculated below. */
920 totsize += write_debug_header (&rtnend.dst_a_rtnend_header, "rtnend",
921 dosizeonly);
922 totsize += write_debug_data1 (rtnend.dst_b_rtnend_unused, "unused",
923 dosizeonly);
925 ASM_GENERATE_INTERNAL_LABEL (label1, FUNC_BEGIN_LABEL, rtnnum);
926 ASM_GENERATE_INTERNAL_LABEL (label2, FUNC_END_LABEL, rtnnum);
927 totsize += write_debug_delta4 (label2, label1, "routine size", dosizeonly);
929 return totsize;
932 #define K_DELTA_PC(I) \
933 ((I) < 128 ? -(I) : (I) < 65536 ? DST_K_DELTA_PC_W : DST_K_DELTA_PC_L)
935 #define K_SET_LINUM(I) \
936 ((I) < 256 ? DST_K_SET_LINUM_B \
937 : (I) < 65536 ? DST_K_SET_LINUM : DST_K_SET_LINUM_L)
939 #define K_INCR_LINUM(I) \
940 ((I) < 256 ? DST_K_INCR_LINUM \
941 : (I) < 65536 ? DST_K_INCR_LINUM_W : DST_K_INCR_LINUM_L)
943 /* Output the PC to line number correlations and return the size. Just return
944 the size if DOSIZEONLY is non-zero */
946 static int
947 write_pclines (dosizeonly)
948 int dosizeonly;
950 unsigned i;
951 int fn;
952 int ln, lastln;
953 int linestart = 0;
954 int max_line;
955 DST_LINE_NUM_HEADER line_num;
956 DST_PCLINE_COMMANDS pcline;
957 char label[MAX_ARTIFICIAL_LABEL_BYTES];
958 char lastlabel[MAX_ARTIFICIAL_LABEL_BYTES];
959 int totsize = 0;
960 char buff[256];
962 max_line = file_info_table[1].max_line;
963 file_info_table[1].listing_line_start = linestart;
964 linestart = linestart + ((max_line / 100000) + 1) * 100000;
966 for (i = 2; i < file_info_table_in_use; i++)
968 max_line = file_info_table[i].max_line;
969 file_info_table[i].listing_line_start = linestart;
970 linestart = linestart + ((max_line / 10000) + 1) * 10000;
973 /* Set starting address to beginning of text section */
974 line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 8;
975 line_num.dst_a_line_num_header.dst__header_type.dst_w_type = DST_K_LINE_NUM;
976 pcline.dst_b_pcline_command = DST_K_SET_ABS_PC;
978 totsize += write_debug_header (&line_num.dst_a_line_num_header,
979 "line_num", dosizeonly);
980 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
981 "line_num (SET ABS PC)", dosizeonly);
983 if (dosizeonly)
984 totsize += 4;
985 else
987 ASM_OUTPUT_DEBUG_ADDR (asm_out_file, TEXT_SECTION_ASM_OP);
988 if (flag_verbose_asm)
989 fprintf (asm_out_file, "\t%s line_num", ASM_COMMENT_START);
990 fputc ('\n', asm_out_file);
993 fn = line_info_table[1].dst_file_num;
994 ln = (file_info_table[fn].listing_line_start
995 + line_info_table[1].dst_line_num);
996 line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 4 + 4;
997 pcline.dst_b_pcline_command = DST_K_SET_LINUM_L;
999 totsize += write_debug_header (&line_num.dst_a_line_num_header,
1000 "line_num", dosizeonly);
1001 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
1002 "line_num (SET LINUM LONG)", dosizeonly);
1004 sprintf (buff, "line_num (%d)", ln - 1);
1005 totsize += write_debug_data4 (ln - 1, buff, dosizeonly);
1007 lastln = ln;
1008 strcpy (lastlabel, TEXT_SECTION_ASM_OP);
1009 for (i = 1; i < line_info_table_in_use; i++)
1011 int extrabytes;
1013 fn = line_info_table[i].dst_file_num;
1014 ln = (file_info_table[fn].listing_line_start
1015 + line_info_table[i].dst_line_num);
1017 if (ln - lastln > 1)
1018 extrabytes = 5; /* NUMBYTES (ln - lastln - 1) + 1; */
1019 else if (ln <= lastln)
1020 extrabytes = 5; /* NUMBYTES (ln - 1) + 1; */
1021 else
1022 extrabytes = 0;
1024 line_num.dst_a_line_num_header.dst__header_length.dst_w_length
1025 = 8 + extrabytes;
1027 totsize += write_debug_header
1028 (&line_num.dst_a_line_num_header, "line_num", dosizeonly);
1030 if (ln - lastln > 1)
1032 int lndif = ln - lastln - 1;
1034 /* K_INCR_LINUM (lndif); */
1035 pcline.dst_b_pcline_command = DST_K_INCR_LINUM_L;
1037 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
1038 "line_num (INCR LINUM LONG)",
1039 dosizeonly);
1041 sprintf (buff, "line_num (%d)", lndif);
1042 totsize += write_debug_data4 (lndif, buff, dosizeonly);
1044 else if (ln <= lastln)
1046 /* K_SET_LINUM (ln-1); */
1047 pcline.dst_b_pcline_command = DST_K_SET_LINUM_L;
1049 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
1050 "line_num (SET LINUM LONG)",
1051 dosizeonly);
1053 sprintf (buff, "line_num (%d)", ln - 1);
1054 totsize += write_debug_data4 (ln - 1, buff, dosizeonly);
1057 pcline.dst_b_pcline_command = DST_K_DELTA_PC_L;
1059 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
1060 "line_num (DELTA PC LONG)", dosizeonly);
1062 ASM_GENERATE_INTERNAL_LABEL (label, LINE_CODE_LABEL, i);
1063 totsize += write_debug_delta4 (label, lastlabel, "increment line_num",
1064 dosizeonly);
1066 lastln = ln;
1067 strcpy (lastlabel, label);
1070 return totsize;
1073 /* Output a source correlation for file FILEID using information saved in
1074 FILE_INFO_ENTRY and return the size. Just return the size if DOSIZEONLY is
1075 non-zero. */
1077 static int
1078 write_srccorr (fileid, file_info_entry, dosizeonly)
1079 int fileid;
1080 dst_file_info_entry file_info_entry;
1081 int dosizeonly;
1083 int src_command_size;
1084 int linesleft = file_info_entry.max_line;
1085 int linestart = file_info_entry.listing_line_start;
1086 int flen = file_info_entry.flen;
1087 int linestodo = 0;
1088 DST_SOURCE_CORR src_header;
1089 DST_SRC_COMMAND src_command;
1090 DST_SRC_COMMAND src_command_sf;
1091 DST_SRC_COMMAND src_command_sl;
1092 DST_SRC_COMMAND src_command_sr;
1093 DST_SRC_COMMAND src_command_dl;
1094 DST_SRC_CMDTRLR src_cmdtrlr;
1095 char buff[256];
1096 int totsize = 0;
1098 if (fileid == 1)
1100 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1101 = DST_K_SOURCE_CORR_HEADER_SIZE + 1 - 1;
1102 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1103 = DST_K_SOURCE;
1104 src_command.dst_b_src_command = DST_K_SRC_FORMFEED;
1106 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1107 "source corr", dosizeonly);
1109 totsize += write_debug_data1 (src_command.dst_b_src_command,
1110 "source_corr (SRC FORMFEED)",
1111 dosizeonly);
1114 src_command_size
1115 = DST_K_SRC_COMMAND_SIZE + flen + DST_K_SRC_CMDTRLR_SIZE;
1116 src_command.dst_b_src_command = DST_K_SRC_DECLFILE;
1117 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_length
1118 = src_command_size - 2;
1119 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_flags = 0;
1120 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_fileid
1121 = fileid;
1122 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt
1123 = file_info_entry.cdt;
1124 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk
1125 = file_info_entry.ebk;
1126 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_rms_ffb
1127 = file_info_entry.ffb;
1128 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_rms_rfo
1129 = file_info_entry.rfo;
1130 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename
1131 = file_info_entry.flen;
1133 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1134 = DST_K_SOURCE_CORR_HEADER_SIZE + src_command_size - 1;
1135 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1136 = DST_K_SOURCE;
1138 src_cmdtrlr.dst_b_src_df_libmodname = 0;
1140 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1141 "source corr", dosizeonly);
1142 totsize += write_debug_data1 (src_command.dst_b_src_command,
1143 "source_corr (DECL SRC FILE)", dosizeonly);
1144 totsize += write_debug_data1
1145 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_length,
1146 "source_corr (length)", dosizeonly);
1148 totsize += write_debug_data1
1149 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_flags,
1150 "source_corr (flags)", dosizeonly);
1152 totsize += write_debug_data2
1153 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_fileid,
1154 "source_corr (fileid)", dosizeonly);
1156 totsize += write_debug_data8
1157 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt,
1158 "source_corr (creation date)", dosizeonly);
1160 totsize += write_debug_data4
1161 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk,
1162 "source_corr (EOF block number)", dosizeonly);
1164 totsize += write_debug_data2
1165 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_rms_ffb,
1166 "source_corr (first free byte)", dosizeonly);
1168 totsize += write_debug_data1
1169 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_rms_rfo,
1170 "source_corr (record and file organization)", dosizeonly);
1172 totsize += write_debug_data1
1173 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename,
1174 "source_corr (filename length)", dosizeonly);
1176 totsize += write_debug_string (file_info_entry.file_name,
1177 "source file name", dosizeonly);
1178 totsize += write_debug_data1 (src_cmdtrlr.dst_b_src_df_libmodname,
1179 "source_corr (libmodname)", dosizeonly);
1181 src_command_sf.dst_b_src_command = DST_K_SRC_SETFILE;
1182 src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword = fileid;
1184 src_command_sr.dst_b_src_command = DST_K_SRC_SETREC_W;
1185 src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword = 1;
1187 src_command_sl.dst_b_src_command = DST_K_SRC_SETLNUM_L;
1188 src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong = linestart + 1;
1190 src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W;
1192 if (linesleft > 65534)
1193 linesleft = linesleft - 65534, linestodo = 65534;
1194 else
1195 linestodo = linesleft, linesleft = 0;
1197 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo;
1199 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1200 = DST_K_SOURCE_CORR_HEADER_SIZE + 3 + 3 + 5 + 3 - 1;
1201 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1202 = DST_K_SOURCE;
1204 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1205 "source corr", dosizeonly);
1207 totsize += write_debug_data1 (src_command_sf.dst_b_src_command,
1208 "source_corr (src setfile)", dosizeonly);
1210 totsize += write_debug_data2
1211 (src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword,
1212 "source_corr (fileid)", dosizeonly);
1214 totsize += write_debug_data1 (src_command_sr.dst_b_src_command,
1215 "source_corr (setrec)", dosizeonly);
1217 totsize += write_debug_data2
1218 (src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword,
1219 "source_corr (recnum)", dosizeonly);
1221 totsize += write_debug_data1 (src_command_sl.dst_b_src_command,
1222 "source_corr (setlnum)", dosizeonly);
1224 totsize += write_debug_data4
1225 (src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong,
1226 "source_corr (linenum)", dosizeonly);
1228 totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
1229 "source_corr (deflines)", dosizeonly);
1231 sprintf (buff, "source_corr (%d)",
1232 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
1233 totsize += write_debug_data2
1234 (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword, buff, dosizeonly);
1236 while (linesleft > 0)
1238 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1239 = DST_K_SOURCE_CORR_HEADER_SIZE + 3 - 1;
1240 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1241 = DST_K_SOURCE;
1242 src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W;
1244 if (linesleft > 65534)
1245 linesleft = linesleft - 65534, linestodo = 65534;
1246 else
1247 linestodo = linesleft, linesleft = 0;
1249 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo;
1251 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1252 "source corr", dosizeonly);
1253 totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
1254 "source_corr (deflines)", dosizeonly);
1255 sprintf (buff, "source_corr (%d)",
1256 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
1257 totsize += write_debug_data2
1258 (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword,
1259 buff, dosizeonly);
1262 return totsize;
1265 /* Output all the source correlation entries and return the size. Just return
1266 the size if DOSIZEONLY is non-zero. */
1268 static int
1269 write_srccorrs (dosizeonly)
1270 int dosizeonly;
1272 unsigned int i;
1273 int totsize = 0;
1275 for (i = 1; i < file_info_table_in_use; i++)
1276 totsize += write_srccorr (i, file_info_table[i], dosizeonly);
1278 return totsize;
1281 /* Output a marker (i.e. a label) for the beginning of a function, before
1282 the prologue. */
1284 static void
1285 vmsdbgout_begin_prologue (line, file)
1286 unsigned int line;
1287 const char *file;
1289 char label[MAX_ARTIFICIAL_LABEL_BYTES];
1291 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1292 (*dwarf2_debug_hooks.begin_prologue) (line, file);
1294 if (debug_info_level > DINFO_LEVEL_NONE)
1296 current_funcdef_number++;
1297 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL,
1298 current_funcdef_number);
1299 ASM_OUTPUT_LABEL (asm_out_file, label);
1303 /* Output a marker (i.e. a label) for the beginning of a function, after
1304 the prologue. */
1306 void
1307 vmsdbgout_after_prologue ()
1309 char label[MAX_ARTIFICIAL_LABEL_BYTES];
1311 if (debug_info_level > DINFO_LEVEL_TERSE)
1313 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL,
1314 current_funcdef_number);
1315 ASM_OUTPUT_LABEL (asm_out_file, label);
1319 /* Output a marker (i.e. a label) for the absolute end of the generated code
1320 for a function definition. This gets called *after* the epilogue code has
1321 been generated. */
1323 static void
1324 vmsdbgout_end_epilogue ()
1326 char label[MAX_ARTIFICIAL_LABEL_BYTES];
1328 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1329 (*dwarf2_debug_hooks.end_epilogue) ();
1331 if (debug_info_level > DINFO_LEVEL_NONE)
1333 /* Output a label to mark the endpoint of the code generated for this
1334 function. */
1335 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL,
1336 current_funcdef_number);
1337 ASM_OUTPUT_LABEL (asm_out_file, label);
1341 /* Output a marker (i.e. a label) for the beginning of the generated code for
1342 a lexical block. */
1344 static void
1345 vmsdbgout_begin_block (line, blocknum)
1346 register unsigned line;
1347 register unsigned blocknum;
1349 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1350 (*dwarf2_debug_hooks.begin_block) (line, blocknum);
1352 if (debug_info_level > DINFO_LEVEL_TERSE)
1353 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BLOCK_BEGIN_LABEL, blocknum);
1356 /* Output a marker (i.e. a label) for the end of the generated code for a
1357 lexical block. */
1359 static void
1360 vmsdbgout_end_block (line, blocknum)
1361 register unsigned line;
1362 register unsigned blocknum;
1364 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1365 (*dwarf2_debug_hooks.end_block) (line, blocknum);
1367 if (debug_info_level > DINFO_LEVEL_TERSE)
1368 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BLOCK_END_LABEL, blocknum);
1371 /* Not implemented in VMS Debug. */
1373 static bool
1374 vmsdbgout_ignore_block (block)
1375 tree block;
1377 bool retval = 0;
1379 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1380 retval = (*dwarf2_debug_hooks.ignore_block) (block);
1382 return retval;
1385 /* Add an entry for function DECL into the func_table. */
1387 static void
1388 vmsdbgout_begin_function (decl)
1389 tree decl;
1391 const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
1393 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1394 (*dwarf2_debug_hooks.begin_function) (decl);
1396 if (func_table_in_use == func_table_allocated)
1398 func_table_allocated += FUNC_TABLE_INCREMENT;
1399 func_table = (char **) xrealloc (func_table,
1400 func_table_allocated * sizeof (char *));
1403 /* Add the new entry to the end of the function name table. */
1404 func_table[func_table_in_use++] = xstrdup (name);
1407 static char fullname_buff [4096];
1409 /* Return the full file specification for FILENAME. The specification must be
1410 in VMS syntax in order to be processed by VMS Debug. */
1412 static char *
1413 full_name (filename)
1414 const char *filename;
1416 #ifdef VMS
1417 FILE *fp = fopen (filename, "r");
1419 fgetname (fp, fullname_buff, 1);
1420 fclose (fp);
1421 #else
1422 getcwd (fullname_buff, sizeof (fullname_buff));
1424 strcat (fullname_buff, "/");
1425 strcat (fullname_buff, filename);
1427 /* ??? Insert hairy code here to translate Unix style file specification
1428 to VMS style. */
1429 #endif
1431 return fullname_buff;
1434 /* Lookup a filename (in the list of filenames that we know about here in
1435 vmsdbgout.c) and return its "index". The index of each (known) filename is
1436 just a unique number which is associated with only that one filename. We
1437 need such numbers for the sake of generating labels and references
1438 to those files numbers. If the filename given as an argument is not
1439 found in our current list, add it to the list and assign it the next
1440 available unique index number. In order to speed up searches, we remember
1441 the index of the filename was looked up last. This handles the majority of
1442 all searches. */
1444 static unsigned int
1445 lookup_filename (file_name)
1446 const char *file_name;
1448 static unsigned int last_file_lookup_index = 0;
1449 register char *fn;
1450 register unsigned i;
1451 char *fnam;
1452 long long cdt;
1453 long ebk;
1454 short ffb;
1455 char rfo;
1456 char flen;
1457 struct stat statbuf;
1459 if (stat (file_name, &statbuf) == 0)
1461 long gmtoff;
1462 #ifdef VMS
1463 struct tm *ts;
1465 /* Adjust for GMT */
1466 ts = (struct tm *) localtime (&statbuf.st_ctime);
1467 gmtoff = ts->tm_gmtoff;
1469 /* VMS has multiple file format types */
1470 rfo = statbuf.st_fab_rfm;
1471 #else
1472 /* Is GMT adjustment an issue with a cross-compiler? */
1473 gmtoff = 0;
1475 /* Assume stream LF type file */
1476 rfo = 2;
1477 #endif
1478 cdt = 10000000 * (statbuf.st_ctime + gmtoff + vms_epoch_offset);
1479 ebk = statbuf.st_size / 512 + 1;
1480 ffb = statbuf.st_size - ((statbuf.st_size / 512) * 512);
1481 fnam = full_name (file_name);
1482 flen = strlen (fnam);
1484 else
1486 cdt = 0;
1487 ebk = 0;
1488 ffb = 0;
1489 rfo = 0;
1490 fnam = (char *) "";
1491 flen = 0;
1494 /* Check to see if the file name that was searched on the previous call
1495 matches this file name. If so, return the index. */
1496 if (last_file_lookup_index != 0)
1498 fn = file_info_table[last_file_lookup_index].file_name;
1499 if (strcmp (fnam, fn) == 0)
1500 return last_file_lookup_index;
1503 /* Didn't match the previous lookup, search the table */
1504 for (i = 1; i < file_info_table_in_use; ++i)
1506 fn = file_info_table[i].file_name;
1507 if (strcmp (fnam, fn) == 0)
1509 last_file_lookup_index = i;
1510 return i;
1514 /* Prepare to add a new table entry by making sure there is enough space in
1515 the table to do so. If not, expand the current table. */
1516 if (file_info_table_in_use == file_info_table_allocated)
1519 file_info_table_allocated += FILE_TABLE_INCREMENT;
1520 file_info_table
1521 = (dst_file_info_ref) xrealloc (file_info_table,
1522 (file_info_table_allocated
1523 * sizeof (dst_file_info_entry)));
1526 /* Add the new entry to the end of the filename table. */
1527 file_info_table[file_info_table_in_use].file_name = xstrdup (fnam);
1528 file_info_table[file_info_table_in_use].max_line = 0;
1529 file_info_table[file_info_table_in_use].cdt = cdt;
1530 file_info_table[file_info_table_in_use].ebk = ebk;
1531 file_info_table[file_info_table_in_use].ffb = ffb;
1532 file_info_table[file_info_table_in_use].rfo = rfo;
1533 file_info_table[file_info_table_in_use].flen = flen;
1535 last_file_lookup_index = file_info_table_in_use++;
1536 return last_file_lookup_index;
1539 /* Output a label to mark the beginning of a source code line entry
1540 and record information relating to this source line, in
1541 'line_info_table' for later output of the .debug_line section. */
1543 static void
1544 vmsdbgout_source_line (line, filename)
1545 register unsigned line;
1546 register const char *filename;
1548 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1549 (*dwarf2_debug_hooks.source_line) (line, filename);
1551 if (debug_info_level >= DINFO_LEVEL_TERSE)
1553 dst_line_info_ref line_info;
1555 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, LINE_CODE_LABEL,
1556 line_info_table_in_use);
1558 /* Expand the line info table if necessary. */
1559 if (line_info_table_in_use == line_info_table_allocated)
1561 line_info_table_allocated += LINE_INFO_TABLE_INCREMENT;
1562 line_info_table
1563 = (dst_line_info_ref) xrealloc (line_info_table,
1564 (line_info_table_allocated
1565 * sizeof (dst_line_info_entry)));
1568 /* Add the new entry at the end of the line_info_table. */
1569 line_info = &line_info_table[line_info_table_in_use++];
1570 line_info->dst_file_num = lookup_filename (filename);
1571 line_info->dst_line_num = line;
1572 if (line > file_info_table[line_info->dst_file_num].max_line)
1573 file_info_table[line_info->dst_file_num].max_line = line;
1577 /* Record the beginning of a new source file, for later output.
1578 At present, unimplemented. */
1580 static void
1581 vmsdbgout_start_source_file (lineno, filename)
1582 unsigned int lineno;
1583 const char *filename;
1585 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1586 (*dwarf2_debug_hooks.start_source_file) (lineno, filename);
1589 /* Record the end of a source file, for later output.
1590 At present, unimplemented. */
1592 static void
1593 vmsdbgout_end_source_file (lineno)
1594 unsigned int lineno ATTRIBUTE_UNUSED;
1596 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1597 (*dwarf2_debug_hooks.end_source_file) (lineno);
1600 /* Set up for Debug output at the start of compilation. */
1602 static void
1603 vmsdbgout_init (main_input_filename)
1604 const char *main_input_filename;
1606 const char *language_string = lang_hooks.name;
1608 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1609 (*dwarf2_debug_hooks.init) (main_input_filename);
1611 if (debug_info_level == DINFO_LEVEL_NONE)
1612 return;
1614 /* Remember the name of the primary input file. */
1615 primary_filename = main_input_filename;
1617 /* Allocate the initial hunk of the file_info_table. */
1618 file_info_table
1619 = (dst_file_info_ref) xcalloc (FILE_TABLE_INCREMENT,
1620 sizeof (dst_file_info_entry));
1621 file_info_table_allocated = FILE_TABLE_INCREMENT;
1623 /* Skip the first entry - file numbers begin at 1 */
1624 file_info_table_in_use = 1;
1626 func_table = (char **) xcalloc (FUNC_TABLE_INCREMENT, sizeof (char *));
1627 func_table_allocated = FUNC_TABLE_INCREMENT;
1628 func_table_in_use = 1;
1630 /* Allocate the initial hunk of the line_info_table. */
1631 line_info_table
1632 = (dst_line_info_ref) xcalloc (LINE_INFO_TABLE_INCREMENT,
1633 sizeof (dst_line_info_entry));
1634 line_info_table_allocated = LINE_INFO_TABLE_INCREMENT;
1635 /* zero-th entry is allocated, but unused */
1636 line_info_table_in_use = 1;
1638 lookup_filename (primary_filename);
1640 if (!strcmp (language_string, "GNU C"))
1641 module_language = DST_K_C;
1642 else if (!strcmp (language_string, "GNU C++"))
1643 module_language = DST_K_CXX;
1644 else if (!strcmp (language_string, "GNU Ada"))
1645 module_language = DST_K_ADA;
1646 else if (!strcmp (language_string, "GNU F77"))
1647 module_language = DST_K_FORTRAN;
1648 else
1649 module_language = DST_K_UNKNOWN;
1651 module_producer
1652 = (char *) xmalloc (strlen (language_string) + 1
1653 + strlen (version_string) + 1);
1654 sprintf (module_producer, "%s %s", language_string, version_string);
1656 ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
1660 /* Not implemented in VMS Debug. */
1662 static void
1663 vmsdbgout_define (lineno, buffer)
1664 unsigned int lineno;
1665 const char *buffer;
1667 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1668 (*dwarf2_debug_hooks.define) (lineno, buffer);
1671 /* Not implemented in VMS Debug. */
1673 static void
1674 vmsdbgout_undef (lineno, buffer)
1675 unsigned int lineno;
1676 const char *buffer;
1678 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1679 (*dwarf2_debug_hooks.undef) (lineno, buffer);
1682 /* Not implemented in VMS Debug. */
1684 static void
1685 vmsdbgout_decl (decl)
1686 tree decl;
1688 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1689 (*dwarf2_debug_hooks.function_decl) (decl);
1692 /* Not implemented in VMS Debug. */
1694 static void
1695 vmsdbgout_global_decl (decl)
1696 tree decl;
1698 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1699 (*dwarf2_debug_hooks.global_decl) (decl);
1702 /* Not implemented in VMS Debug. */
1704 static void
1705 vmsdbgout_abstract_function (decl)
1706 tree decl;
1708 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1709 (*dwarf2_debug_hooks.outlining_inline_function) (decl);
1712 /* Output stuff that Debug requires at the end of every file and generate the
1713 VMS Debug debugging info. */
1715 static void
1716 vmsdbgout_finish (input_filename)
1717 const char *input_filename ATTRIBUTE_UNUSED;
1719 unsigned int i;
1720 int totsize;
1722 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1723 (*dwarf2_debug_hooks.finish) (input_filename);
1725 if (debug_info_level == DINFO_LEVEL_NONE)
1726 return;
1728 /* Output a terminator label for the .text section. */
1729 text_section ();
1730 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, TEXT_END_LABEL, 0);
1732 /* Output debugging information.
1733 Warning! Do not change the name of the .vmsdebug section without
1734 changing it in the assembler also. */
1735 named_section (NULL_TREE, ".vmsdebug", 0);
1736 ASM_OUTPUT_ALIGN (asm_out_file, 0);
1738 totsize = write_modbeg (1);
1739 for (i = 1; i < func_table_in_use; i++)
1741 totsize += write_rtnbeg (i, 1);
1742 totsize += write_rtnend (i, 1);
1744 totsize += write_pclines (1);
1746 write_modbeg (0);
1747 for (i = 1; i < func_table_in_use; i++)
1749 write_rtnbeg (i, 0);
1750 write_rtnend (i, 0);
1752 write_pclines (0);
1754 if (debug_info_level > DINFO_LEVEL_TERSE)
1756 totsize = write_srccorrs (1);
1757 write_srccorrs (0);
1760 totsize = write_modend (1);
1761 write_modend (0);
1763 #endif /* VMS_DEBUGGING_INFO */