]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/vmsdbgout.c
* MAINTAINERS: Update mail address for config.* patches.
[thirdparty/gcc.git] / gcc / vmsdbgout.c
CommitLineData
7a0c8d71
DR
1/* Output VMS debug format symbol table information from the GNU C compiler.
2 Copyright (C) 1997-2001 Free Software Foundation, Inc.
3 Contributed by Douglas B. Rupp (rupp@gnat.com).
4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU CC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU CC; see the file COPYING. If not, write to
19the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21#include "config.h"
22
23#ifdef VMS_DEBUGGING_INFO
24#include "system.h"
25#include "tree.h"
26#include "flags.h"
27#include "rtl.h"
28#include "output.h"
29#include "vmsdbg.h"
30#include "debug.h"
31#include "langhooks.h"
32
33/* Difference in seconds between the VMS Epoch and the Unix Epoch */
34static const long long vms_epoch_offset = 3506716800ll;
35
36/* NOTE: In the comments in this file, many references are made to "Debug
37 Symbol Table". This term is abbreviated as `DST' throughout the remainder
38 of this file. */
39
40typedef struct dst_line_info_struct *dst_line_info_ref;
41
42/* Each entry in the line_info_table maintains the file and
43 line number associated with the label generated for that
44 entry. The label gives the PC value associated with
45 the line number entry. */
46typedef struct dst_line_info_struct
47{
48 unsigned long dst_file_num;
49 unsigned long dst_line_num;
50}
51dst_line_info_entry;
52
53typedef struct dst_file_info_struct *dst_file_info_ref;
54
55typedef struct dst_file_info_struct
56{
57 char *file_name;
58 unsigned int max_line;
59 unsigned int listing_line_start;
60 long long cdt;
61 long ebk;
62 short ffb;
63 char rfo;
64 char flen;
65}
66dst_file_info_entry;
67
68/* How to start an assembler comment. */
69#ifndef ASM_COMMENT_START
70#define ASM_COMMENT_START ";#"
71#endif
72
73/* Maximum size (in bytes) of an artificially generated label. */
74#define MAX_ARTIFICIAL_LABEL_BYTES 30
75
76/* Make sure we know the sizes of the various types debug can describe. These
77 are only defaults. If the sizes are different for your target, you should
78 override these values by defining the appropriate symbols in your tm.h
79 file. */
80#ifndef CHAR_TYPE_SIZE
81#define CHAR_TYPE_SIZE BITS_PER_UNIT
82#endif
83#ifndef PTR_SIZE
84#define PTR_SIZE 4 /* Must be 32 bits for VMS debug info */
85#endif
86
87/* Pointer to an structure of filenames referenced by this compilation unit. */
88static dst_file_info_ref file_info_table;
89
90/* Total number of entries in the table (i.e. array) pointed to by
91 `file_info_table'. This is the *total* and includes both used and unused
92 slots. */
93static unsigned int file_info_table_allocated;
94
95/* Number of entries in the file_info_table which are actually in use. */
96static unsigned int file_info_table_in_use;
97
98/* Size (in elements) of increments by which we may expand the filename
99 table. */
100#define FILE_TABLE_INCREMENT 64
101
102static char **func_table;
103static unsigned int func_table_allocated;
104static unsigned int func_table_in_use;
105#define FUNC_TABLE_INCREMENT 256
106
107/* Local pointer to the name of the main input file. Initialized in
108 avmdbgout_init. */
109static const char *primary_filename;
110
111static char *module_producer;
112static unsigned int module_language;
113
114/* A pointer to the base of a table that contains line information
115 for each source code line in .text in the compilation unit. */
116static dst_line_info_ref line_info_table;
117
118/* Number of elements currently allocated for line_info_table. */
119static unsigned int line_info_table_allocated;
120
121/* Number of elements in line_info_table currently in use. */
122static unsigned int line_info_table_in_use;
123
124/* Size (in elements) of increments by which we may expand line_info_table. */
125#define LINE_INFO_TABLE_INCREMENT 1024
126
127/* The number of the current function definition for which debugging
128 information is being generated. These numbers range from 1 up to the
129 maximum number of function definitions contained within the current
130 compilation unit. These numbers are used to create unique label id's unique
131 to each function definition. */
132static unsigned int current_funcdef_number = 0;
133
134/* Forward declarations for functions defined in this file. */
135static char *full_name PARAMS ((const char *));
136static unsigned int lookup_filename PARAMS ((const char *));
137static void addr_const_to_string PARAMS ((char *, rtx));
138static int write_debug_header PARAMS ((DST_HEADER *, const char *, int));
139static int write_debug_addr PARAMS ((char *, const char *, int));
140static int write_debug_data1 PARAMS ((unsigned int, const char *, int));
141static int write_debug_data2 PARAMS ((unsigned int, const char *, int));
142static int write_debug_data4 PARAMS ((unsigned long, const char *, int));
143static int write_debug_data8 PARAMS ((unsigned long long, const char *,
144 int));
145static int write_debug_delta4 PARAMS ((char *, char *, const char *, int));
146static int write_debug_string PARAMS ((char *, const char *, int));
147static int write_modbeg PARAMS ((int));
148static int write_modend PARAMS ((int));
149static int write_rtnbeg PARAMS ((int, int));
150static int write_rtnend PARAMS ((int, int));
151static int write_pclines PARAMS ((int));
152static int write_srccorr PARAMS ((int, dst_file_info_entry, int));
153static int write_srccorrs PARAMS ((int));
154
155static void vmsdbgout_init PARAMS ((const char *));
156static void vmsdbgout_finish PARAMS ((const char *));
157static void vmsdbgout_define PARAMS ((unsigned int, const char *));
158static void vmsdbgout_undef PARAMS ((unsigned int, const char *));
159static void vmsdbgout_start_source_file PARAMS ((unsigned int, const char *));
160static void vmsdbgout_end_source_file PARAMS ((unsigned int));
161static void vmsdbgout_begin_block PARAMS ((unsigned int, unsigned int));
162static void vmsdbgout_end_block PARAMS ((unsigned int, unsigned int));
163static bool vmsdbgout_ignore_block PARAMS ((tree));
164static void vmsdbgout_source_line PARAMS ((unsigned int, const char *));
165static void vmsdbgout_begin_prologue PARAMS ((unsigned int, const char *));
166static void vmsdbgout_end_epilogue PARAMS ((void));
167static void vmsdbgout_begin_function PARAMS ((tree));
168static void vmsdbgout_decl PARAMS ((tree));
169static void vmsdbgout_global_decl PARAMS ((tree));
170static void vmsdbgout_abstract_function PARAMS ((tree));
171
172
173/* The debug hooks structure. */
174
175struct gcc_debug_hooks vmsdbg_debug_hooks
176= {vmsdbgout_init,
177 vmsdbgout_finish,
178 vmsdbgout_define,
179 vmsdbgout_undef,
180 vmsdbgout_start_source_file,
181 vmsdbgout_end_source_file,
182 vmsdbgout_begin_block,
183 vmsdbgout_end_block,
184 vmsdbgout_ignore_block,
185 vmsdbgout_source_line,
186 vmsdbgout_begin_prologue,
187 debug_nothing_int, /* end_prologue */
188 vmsdbgout_end_epilogue, /* end_epilogue */
189 vmsdbgout_begin_function, /* begin_function */
190 debug_nothing_int, /* end_function */
191 vmsdbgout_decl,
192 vmsdbgout_global_decl,
193 debug_nothing_tree, /* deferred_inline_function */
194 vmsdbgout_abstract_function,
195 debug_nothing_rtx /* label */
196};
197
198/* Definitions of defaults for assembler-dependent names of various
199 pseudo-ops and section names.
200 Theses may be overridden in the tm.h file (if necessary) for a particular
201 assembler. */
202#ifdef UNALIGNED_SHORT_ASM_OP
203#undef UNALIGNED_SHORT_ASM_OP
204#endif
205#define UNALIGNED_SHORT_ASM_OP ".word"
206
207#ifdef UNALIGNED_INT_ASM_OP
208#undef UNALIGNED_INT_ASM_OP
209#endif
210#define UNALIGNED_INT_ASM_OP ".long"
211
212#ifdef UNALIGNED_LONG_ASM_OP
213#undef UNALIGNED_LONG_ASM_OP
214#endif
215#define UNALIGNED_LONG_ASM_OP ".long"
216
217#ifdef UNALIGNED_DOUBLE_INT_ASM_OP
218#undef UNALIGNED_DOUBLE_INT_ASM_OP
219#endif
220#define UNALIGNED_DOUBLE_INT_ASM_OP ".quad"
221
222#ifdef ASM_BYTE_OP
223#undef ASM_BYTE_OP
224#endif
225#define ASM_BYTE_OP ".byte"
226
227#define NUMBYTES(I) ((I) < 256 ? 1 : (I) < 65536 ? 2 : 4)
228
229#define NUMBYTES0(I) ((I) < 128 ? 0 : (I) < 65536 ? 2 : 4)
230
231#ifndef UNALIGNED_PTR_ASM_OP
232#define UNALIGNED_PTR_ASM_OP \
233 (PTR_SIZE == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP : UNALIGNED_INT_ASM_OP)
234#endif
235
236#ifndef UNALIGNED_OFFSET_ASM_OP
237#define UNALIGNED_OFFSET_ASM_OP(OFFSET) \
238 (NUMBYTES(OFFSET) == 4 \
239 ? UNALIGNED_LONG_ASM_OP \
240 : (NUMBYTES(OFFSET) == 2 ? UNALIGNED_SHORT_ASM_OP : ASM_BYTE_OP))
241#endif
242
243/* Pseudo-op for defining a new section. */
244#ifndef SECTION_ASM_OP
245#define SECTION_ASM_OP ".section"
246#endif
247
248/* Definitions of defaults for formats and names of various special
249 (artificial) labels which may be generated within this file (when the -g
250 options is used and VMS_DEBUGGING_INFO is in effect. If necessary, these
251 may be overridden from within the tm.h file, but typically, overriding these
252 defaults is unnecessary. */
253
254static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
255
256#ifndef TEXT_END_LABEL
257#define TEXT_END_LABEL "Lvetext"
258#endif
259#ifndef FUNC_BEGIN_LABEL
260#define FUNC_BEGIN_LABEL "LVFB"
261#endif
262#ifndef FUNC_PROLOG_LABEL
263#define FUNC_PROLOG_LABEL "LVFP"
264#endif
265#ifndef FUNC_END_LABEL
266#define FUNC_END_LABEL "LVFE"
267#endif
268#ifndef BLOCK_BEGIN_LABEL
269#define BLOCK_BEGIN_LABEL "LVBB"
270#endif
271#ifndef BLOCK_END_LABEL
272#define BLOCK_END_LABEL "LVBE"
273#endif
274#ifndef LINE_CODE_LABEL
275#define LINE_CODE_LABEL "LVM"
276#endif
277
278#ifndef ASM_OUTPUT_DEBUG_DELTA2
279#define ASM_OUTPUT_DEBUG_DELTA2(FILE,LABEL1,LABEL2) \
280 do { fprintf ((FILE), "\t%s\t", UNALIGNED_SHORT_ASM_OP); \
281 assemble_name (FILE, LABEL1); \
282 fprintf (FILE, "-"); \
283 assemble_name (FILE, LABEL2); \
284 } while (0)
285#endif
286
287#ifndef ASM_OUTPUT_DEBUG_DELTA4
288#define ASM_OUTPUT_DEBUG_DELTA4(FILE,LABEL1,LABEL2) \
289 do { fprintf ((FILE), "\t%s\t", UNALIGNED_INT_ASM_OP); \
290 assemble_name (FILE, LABEL1); \
291 fprintf (FILE, "-"); \
292 assemble_name (FILE, LABEL2); \
293 } while (0)
294#endif
295
296#ifndef ASM_OUTPUT_DEBUG_ADDR_DELTA
297#define ASM_OUTPUT_DEBUG_ADDR_DELTA(FILE,LABEL1,LABEL2) \
298 do { fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP); \
299 assemble_name (FILE, LABEL1); \
300 fprintf (FILE, "-"); \
301 assemble_name (FILE, LABEL2); \
302 } while (0)
303#endif
304
305#ifndef ASM_OUTPUT_DEBUG_ADDR
306#define ASM_OUTPUT_DEBUG_ADDR(FILE,LABEL) \
307 do { fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP); \
308 assemble_name (FILE, LABEL); \
309 } while (0)
310#endif
311
312#ifndef ASM_OUTPUT_DEBUG_ADDR_CONST
313#define ASM_OUTPUT_DEBUG_ADDR_CONST(FILE,ADDR) \
314 fprintf ((FILE), "\t%s\t%s", UNALIGNED_PTR_ASM_OP, (ADDR))
315#endif
316
317#ifndef ASM_OUTPUT_DEBUG_DATA1
318#define ASM_OUTPUT_DEBUG_DATA1(FILE,VALUE) \
319 fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, (unsigned char) VALUE)
320#endif
321
322#ifndef ASM_OUTPUT_DEBUG_DATA2
323#define ASM_OUTPUT_DEBUG_DATA2(FILE,VALUE) \
324 fprintf ((FILE), "\t%s\t0x%x", UNALIGNED_SHORT_ASM_OP, \
325 (unsigned short) VALUE)
326#endif
327
328#ifndef ASM_OUTPUT_DEBUG_DATA4
329#define ASM_OUTPUT_DEBUG_DATA4(FILE,VALUE) \
330 fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_INT_ASM_OP, (unsigned long) VALUE)
331#endif
332
333#ifndef ASM_OUTPUT_DEBUG_DATA
334#define ASM_OUTPUT_DEBUG_DATA(FILE,VALUE) \
335 fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_OFFSET_ASM_OP(VALUE), VALUE)
336#endif
337
338#ifndef ASM_OUTPUT_DEBUG_ADDR_DATA
339#define ASM_OUTPUT_DEBUG_ADDR_DATA(FILE,VALUE) \
340 fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_PTR_ASM_OP, \
341 (unsigned long) VALUE)
342#endif
343
344#ifndef ASM_OUTPUT_DEBUG_DATA8
345#define ASM_OUTPUT_DEBUG_DATA8(FILE,VALUE) \
346 fprintf ((FILE), "\t%s\t0x%llx", UNALIGNED_DOUBLE_INT_ASM_OP, \
347 (unsigned long long) VALUE)
348#endif
349
350/* This is similar to the default ASM_OUTPUT_ASCII, except that no trailing
351 newline is produced. When flag_verbose_asm is asserted, we add commnetary
352 at the end of the line, so we must avoid output of a newline here. */
353#ifndef ASM_OUTPUT_DEBUG_STRING
354#define ASM_OUTPUT_DEBUG_STRING(FILE,P) \
355 do { \
356 register int slen = strlen(P); \
357 register char *p = (P); \
358 register int i; \
359 fprintf (FILE, "\t.ascii \""); \
360 for (i = 0; i < slen; i++) \
361 { \
362 register int c = p[i]; \
363 if (c == '\"' || c == '\\') \
364 putc ('\\', FILE); \
365 if (c >= ' ' && c < 0177) \
366 putc (c, FILE); \
367 else \
368 fprintf (FILE, "\\%o", c); \
369 } \
370 fprintf (FILE, "\""); \
371 } \
372 while (0)
373#endif
374
375/* Convert a reference to the assembler name of a C-level name. This
376 macro has the same effect as ASM_OUTPUT_LABELREF, but copies to
377 a string rather than writing to a file. */
378#ifndef ASM_NAME_TO_STRING
379#define ASM_NAME_TO_STRING(STR, NAME) \
380 do { \
381 if ((NAME)[0] == '*') \
382 strcpy (STR, NAME+1); \
383 else \
384 strcpy (STR, NAME); \
385 } \
386 while (0)
387#endif
388
389\f
390/* General utility functions. */
391
392/* Convert an integer constant expression into assembler syntax. Addition and
393 subtraction are the only arithmetic that may appear in these expressions.
394 This is an adaptation of output_addr_const in final.c. Here, the target
395 of the conversion is a string buffer. We can't use output_addr_const
396 directly, because it writes to a file. */
397
398static void
399addr_const_to_string (str, x)
400 char *str;
401 rtx x;
402{
403 char buf1[256];
404 char buf2[256];
405
406restart:
407 str[0] = '\0';
408 switch (GET_CODE (x))
409 {
410 case PC:
411 if (flag_pic)
412 strcat (str, ",");
413 else
414 abort ();
415 break;
416
417 case SYMBOL_REF:
418 ASM_NAME_TO_STRING (buf1, XSTR (x, 0));
419 strcat (str, buf1);
420 break;
421
422 case LABEL_REF:
423 ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
424 ASM_NAME_TO_STRING (buf2, buf1);
425 strcat (str, buf2);
426 break;
427
428 case CODE_LABEL:
429 ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (x));
430 ASM_NAME_TO_STRING (buf2, buf1);
431 strcat (str, buf2);
432 break;
433
434 case CONST_INT:
435 sprintf (buf1, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
436 strcat (str, buf1);
437 break;
438
439 case CONST:
440 /* This used to output parentheses around the expression, but that does
441 not work on the 386 (either ATT or BSD assembler). */
442 addr_const_to_string (buf1, XEXP (x, 0));
443 strcat (str, buf1);
444 break;
445
446 case CONST_DOUBLE:
447 if (GET_MODE (x) == VOIDmode)
448 {
449 /* We can use %d if the number is one word and positive. */
450 if (CONST_DOUBLE_HIGH (x))
451 sprintf (buf1, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
452 CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
453 else if (CONST_DOUBLE_LOW (x) < 0)
454 sprintf (buf1, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (x));
455 else
456 sprintf (buf1, HOST_WIDE_INT_PRINT_DEC,
457 CONST_DOUBLE_LOW (x));
458 strcat (str, buf1);
459 }
460 else
461 /* We can't handle floating point constants; PRINT_OPERAND must
462 handle them. */
463 output_operand_lossage ("floating constant misused");
464 break;
465
466 case PLUS:
467 /* Some assemblers need integer constants to appear last (eg masm). */
468 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
469 {
470 addr_const_to_string (buf1, XEXP (x, 1));
471 strcat (str, buf1);
472 if (INTVAL (XEXP (x, 0)) >= 0)
473 strcat (str, "+");
474 addr_const_to_string (buf1, XEXP (x, 0));
475 strcat (str, buf1);
476 }
477 else
478 {
479 addr_const_to_string (buf1, XEXP (x, 0));
480 strcat (str, buf1);
481 if (INTVAL (XEXP (x, 1)) >= 0)
482 strcat (str, "+");
483 addr_const_to_string (buf1, XEXP (x, 1));
484 strcat (str, buf1);
485 }
486 break;
487
488 case MINUS:
489 /* Avoid outputting things like x-x or x+5-x, since some assemblers
490 can't handle that. */
491 x = simplify_subtraction (x);
492 if (GET_CODE (x) != MINUS)
493 goto restart;
494
495 addr_const_to_string (buf1, XEXP (x, 0));
496 strcat (str, buf1);
497 strcat (str, "-");
498 if (GET_CODE (XEXP (x, 1)) == CONST_INT
499 && INTVAL (XEXP (x, 1)) < 0)
500 {
501 strcat (str, "(");
502 addr_const_to_string (buf1, XEXP (x, 1));
503 strcat (str, buf1);
504 strcat (str, ")");
505 }
506 else
507 {
508 addr_const_to_string (buf1, XEXP (x, 1));
509 strcat (str, buf1);
510 }
511 break;
512
513 case ZERO_EXTEND:
514 case SIGN_EXTEND:
515 addr_const_to_string (buf1, XEXP (x, 0));
516 strcat (str, buf1);
517 break;
518
519 default:
520 output_operand_lossage ("invalid expression as operand");
521 }
522}
523
524static int
525write_debug_header (header, comment, dosizeonly)
526 DST_HEADER *header;
527 const char *comment;
528 int dosizeonly;
529{
530 if (dosizeonly)
531 return 4;
532
533 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file,
534 header->dst__header_length.dst_w_length);
535 if (flag_verbose_asm)
536 fprintf (asm_out_file, "\t%s record length", ASM_COMMENT_START);
537 fputc ('\n', asm_out_file);
538
539 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file,
540 header->dst__header_type.dst_w_type);
541 if (flag_verbose_asm)
542 fprintf (asm_out_file, "\t%s record type (%s)", ASM_COMMENT_START,
543 comment);
544
545 fputc ('\n', asm_out_file);
546
547 return 4;
548}
549
550static int
551write_debug_addr (symbol, comment, dosizeonly)
552 char *symbol;
553 const char *comment;
554 int dosizeonly;
555{
556 if (dosizeonly)
557 return PTR_SIZE;
558
559 ASM_OUTPUT_DEBUG_ADDR (asm_out_file, symbol);
560 if (flag_verbose_asm)
561 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
562 fputc ('\n', asm_out_file);
563
564 return PTR_SIZE;
565}
566
567static int
568write_debug_data1 (data1, comment, dosizeonly)
569 unsigned int data1;
570 const char *comment;
571 int dosizeonly;
572{
573 if (dosizeonly)
574 return 1;
575
576 ASM_OUTPUT_DEBUG_DATA1 (asm_out_file, data1);
577 if (flag_verbose_asm)
578 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
579 fputc ('\n', asm_out_file);
580
581 return 1;
582}
583
584static int
585write_debug_data2 (data2, comment, dosizeonly)
586 unsigned int data2;
587 const char *comment;
588 int dosizeonly;
589{
590 if (dosizeonly)
591 return 2;
592
593 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file, data2);
594 if (flag_verbose_asm)
595 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
596 fputc ('\n', asm_out_file);
597
598 return 2;
599}
600
601static int
602write_debug_data4 (data4, comment, dosizeonly)
603 unsigned long data4;
604 const char *comment;
605 int dosizeonly;
606{
607 if (dosizeonly)
608 return 4;
609
610 ASM_OUTPUT_DEBUG_DATA4 (asm_out_file, data4);
611 if (flag_verbose_asm)
612 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
613 fputc ('\n', asm_out_file);
614
615 return 4;
616}
617
618static int
619write_debug_data8 (data8, comment, dosizeonly)
620 unsigned long long data8;
621 const char *comment;
622 int dosizeonly;
623{
624 if (dosizeonly)
625 return 8;
626
627 ASM_OUTPUT_DEBUG_DATA8 (asm_out_file, data8);
628 if (flag_verbose_asm)
629 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
630 fputc ('\n', asm_out_file);
631
632 return 8;
633}
634
635static int
636write_debug_delta4 (label1, label2, comment, dosizeonly)
637 char *label1;
638 char *label2;
639 const char *comment;
640 int dosizeonly;
641{
642 if (dosizeonly)
643 return 4;
644
645 ASM_OUTPUT_DEBUG_DELTA4(asm_out_file, label1, label2);
646 if (flag_verbose_asm)
647 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
648 fputc ('\n', asm_out_file);
649
650 return 4;
651}
652
653static int
654write_debug_string (string, comment, dosizeonly)
655 char *string;
656 const char *comment;
657 int dosizeonly;
658{
659 if (dosizeonly)
660 return strlen (string);
661
662 ASM_OUTPUT_DEBUG_STRING (asm_out_file, string);
663 if (flag_verbose_asm)
664 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
665 fputc ('\n', asm_out_file);
666
667 return strlen (string);
668}
669
670static int
671write_modbeg (dosizeonly)
672 int dosizeonly;
673{
674
675 DST_MODULE_BEGIN modbeg;
676 DST_MB_TRLR mb_trlr;
677 int i;
678 char *module_name, *m;
679 int modnamelen;
680 int prodnamelen;
681 int totsize = 0;
682
683 /* Assumes primary filename has Unix syntax file spec. */
684 module_name = xstrdup (basename ((char *) primary_filename));
685
686 m = strrchr (module_name, '.');
687 if (m)
688 *m = 0;
689
690 modnamelen = strlen (module_name);
691 for (i = 0; i < modnamelen; i++)
692 module_name[i] = TOUPPER (module_name[i]);
693
694 prodnamelen = strlen (module_producer);
695
696 modbeg.dst_a_modbeg_header.dst__header_length.dst_w_length
697 = DST_K_MODBEG_SIZE + modnamelen + DST_K_MB_TRLR_SIZE + prodnamelen - 1;
698 modbeg.dst_a_modbeg_header.dst__header_type.dst_w_type = DST_K_MODBEG;
699 modbeg.dst_b_modbeg_flags.dst_v_modbeg_hide = 0;
700 modbeg.dst_b_modbeg_flags.dst_v_modbeg_version = 1;
701 modbeg.dst_b_modbeg_flags.dst_v_modbeg_unused = 0;
702 modbeg.dst_b_modbeg_unused = 0;
703 modbeg.dst_l_modbeg_language = module_language;
704 modbeg.dst_w_version_major = DST_K_VERSION_MAJOR;
705 modbeg.dst_w_version_minor = DST_K_VERSION_MINOR;
706 modbeg.dst_b_modbeg_name = strlen (module_name);
707
708 mb_trlr.dst_b_compiler = strlen (module_producer);
709
710 totsize += write_debug_header (&modbeg.dst_a_modbeg_header,
711 "modbeg", dosizeonly);
712 totsize += write_debug_data1 (*((char *) &modbeg.dst_b_modbeg_flags),
713 "flags", dosizeonly);
714 totsize += write_debug_data1 (modbeg.dst_b_modbeg_unused,
715 "unused", dosizeonly);
716 totsize += write_debug_data4 (modbeg.dst_l_modbeg_language,
717 "language", dosizeonly);
718 totsize += write_debug_data2 (modbeg.dst_w_version_major,
719 "DST major version", dosizeonly);
720 totsize += write_debug_data2 (modbeg.dst_w_version_minor,
721 "DST minor version", dosizeonly);
722 totsize += write_debug_data1 (modbeg.dst_b_modbeg_name,
723 "length of module name", dosizeonly);
724 totsize += write_debug_string (module_name, "module name", dosizeonly);
725 totsize += write_debug_data1 (mb_trlr.dst_b_compiler,
726 "length of compiler name", dosizeonly);
727 totsize += write_debug_string (module_producer, "compiler name", dosizeonly);
728
729 return totsize;
730}
731
732static int
733write_modend (dosizeonly)
734 int dosizeonly;
735{
736 DST_MODULE_END modend;
737 int totsize = 0;
738
739 modend.dst_a_modend_header.dst__header_length.dst_w_length
740 = DST_K_MODEND_SIZE - 1;
741 modend.dst_a_modend_header.dst__header_type.dst_w_type = DST_K_MODEND;
742
743 totsize += write_debug_header (&modend.dst_a_modend_header, "modend",
744 dosizeonly);
745
746 return totsize;
747}
748
749static int
750write_rtnbeg (rtnnum, dosizeonly)
751 int rtnnum;
752 int dosizeonly;
753{
754 char *rtnname;
755 int rtnnamelen, rtnentrynamelen;
756 char *rtnentryname;
757 int totsize = 0;
758 char label[MAX_ARTIFICIAL_LABEL_BYTES];
759 DST_ROUTINE_BEGIN rtnbeg;
760 DST_PROLOG prolog;
761
762 rtnname = func_table[rtnnum];
763 rtnnamelen = strlen (rtnname);
764 rtnentrynamelen = rtnnamelen + 4; /* "..en" */
765 rtnentryname = (char *) xmalloc (rtnentrynamelen + 1);
766 strcpy (rtnentryname, rtnname);
767 strcat (rtnentryname, "..en");
768
769 if (!strcmp (rtnname, "main"))
770 {
771 DST_HEADER header;
772 const char *go = "TRANSFER$BREAK$GO";
773
774 /* This command isn't documented in DSTRECORDS, so it's made to
775 look like what DEC C does */
776
777 /* header size - 1st byte + flag byte + STO_LW size
778 + string count byte + string length */
779 header.dst__header_length.dst_w_length
780 = DST_K_DST_HEADER_SIZE - 1 + 1 + 4 + 1 + strlen (go);
781 header.dst__header_type.dst_w_type = 0x17;
782
783 totsize += write_debug_header (&header, "transfer", dosizeonly);
784
785 /* I think this is a flag byte, but I don't know what this flag means */
786 totsize += write_debug_data1 (0x1, "flags ???", dosizeonly);
787
788 /* Routine Begin PD Address */
789 totsize += write_debug_addr (rtnname, "main procedure descriptor",
790 dosizeonly);
791 totsize += write_debug_data1 (strlen (go), "length of main_name",
792 dosizeonly);
793 totsize += write_debug_string ((char *) go, "main name", dosizeonly);
794 }
795
796 /* The header length never includes the length byte */
797 rtnbeg.dst_a_rtnbeg_header.dst__header_length.dst_w_length
798 = DST_K_RTNBEG_SIZE + rtnnamelen - 1;
799 rtnbeg.dst_a_rtnbeg_header.dst__header_type.dst_w_type = DST_K_RTNBEG;
800 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_unused = 0;
801 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_unalloc = 0;
802 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_prototype = 0;
803 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_inlined = 0;
804 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_no_call = 1;
805 rtnbeg.dst_b_rtnbeg_name = rtnnamelen;
806
807 totsize += write_debug_header (&rtnbeg.dst_a_rtnbeg_header, "rtnbeg",
808 dosizeonly);
809 totsize += write_debug_data1 (*((char *) &rtnbeg.dst_b_rtnbeg_flags),
810 "flags", dosizeonly);
811
812 /* Routine Begin Address */
813 totsize += write_debug_addr (rtnentryname, "routine entry name", dosizeonly);
814
815 /* Routine Begin PD Address */
816 totsize += write_debug_addr (rtnname, "routine procedure descriptor",
817 dosizeonly);
818
819 /* Routine Begin Name */
820 totsize += write_debug_data1 (rtnbeg.dst_b_rtnbeg_name,
821 "length of routine name", dosizeonly);
822
823 totsize += write_debug_string (rtnname, "routine name", dosizeonly);
824
825 free (rtnentryname);
826
827 if (debug_info_level > DINFO_LEVEL_TERSE)
828 {
829 prolog.dst_a_prolog_header.dst__header_length.dst_w_length
830 = DST_K_PROLOG_SIZE - 1;
831 prolog.dst_a_prolog_header.dst__header_type.dst_w_type = DST_K_PROLOG;
832
833 totsize += write_debug_header (&prolog.dst_a_prolog_header, "prolog",
834 dosizeonly);
835
836 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL, rtnnum);
837 totsize += write_debug_addr (label, "prolog breakpoint addr",
838 dosizeonly);
839 }
840
841 return totsize;
842}
843
844static int
845write_rtnend (rtnnum, dosizeonly)
846 int rtnnum;
847 int dosizeonly;
848{
849 DST_ROUTINE_END rtnend;
850 char label1[MAX_ARTIFICIAL_LABEL_BYTES];
851 char label2[MAX_ARTIFICIAL_LABEL_BYTES];
852 int totsize;
853
854 totsize = 0;
855
856 rtnend.dst_a_rtnend_header.dst__header_length.dst_w_length
857 = DST_K_RTNEND_SIZE - 1;
858 rtnend.dst_a_rtnend_header.dst__header_type.dst_w_type = DST_K_RTNEND;
859 rtnend.dst_b_rtnend_unused = 0;
860 rtnend.dst_l_rtnend_size = 0; /* Calculated below. */
861
862 totsize += write_debug_header (&rtnend.dst_a_rtnend_header, "rtnend",
863 dosizeonly);
864 totsize += write_debug_data1 (rtnend.dst_b_rtnend_unused, "unused",
865 dosizeonly);
866
867 ASM_GENERATE_INTERNAL_LABEL (label1, FUNC_BEGIN_LABEL, rtnnum);
868 ASM_GENERATE_INTERNAL_LABEL (label2, FUNC_END_LABEL, rtnnum);
869 totsize += write_debug_delta4 (label2, label1, "routine size", dosizeonly);
870
871 return totsize;
872}
873
874#define K_DELTA_PC(I) \
875 ((I) < 128 ? -(I) : (I) < 65536 ? DST_K_DELTA_PC_W : DST_K_DELTA_PC_L)
876
877#define K_SET_LINUM(I) \
878 ((I) < 256 ? DST_K_SET_LINUM_B \
879 : (I) < 65536 ? DST_K_SET_LINUM : DST_K_SET_LINUM_L)
880
881#define K_INCR_LINUM(I) \
882 ((I) < 256 ? DST_K_INCR_LINUM \
883 : (I) < 65536 ? DST_K_INCR_LINUM_W : DST_K_INCR_LINUM_L)
884
885static int
886write_pclines (dosizeonly)
887 int dosizeonly;
888{
889 unsigned i;
890 int fn;
891 int ln, lastln;
892 int linestart = 0;
893 int max_line;
894 DST_LINE_NUM_HEADER line_num;
895 DST_PCLINE_COMMANDS pcline;
896 char label[MAX_ARTIFICIAL_LABEL_BYTES];
897 char lastlabel[MAX_ARTIFICIAL_LABEL_BYTES];
898 int totsize = 0;
899 char buff[256];
900
901 max_line = file_info_table[1].max_line;
902 file_info_table[1].listing_line_start = linestart;
903 linestart = linestart + ((max_line / 100000) + 1) * 100000;
904
905 for (i = 2; i < file_info_table_in_use; i++)
906 {
907 max_line = file_info_table[i].max_line;
908 file_info_table[i].listing_line_start = linestart;
909 linestart = linestart + ((max_line / 10000) + 1) * 10000;
910 }
911
912 /* Set starting address to beginning of text section */
913 line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 8;
914 line_num.dst_a_line_num_header.dst__header_type.dst_w_type = DST_K_LINE_NUM;
915 pcline.dst_b_pcline_command = DST_K_SET_ABS_PC;
916
917 totsize += write_debug_header (&line_num.dst_a_line_num_header,
918 "line_num", dosizeonly);
919 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
920 "line_num (SET ABS PC)", dosizeonly);
921
922 if (dosizeonly)
923 totsize += 4;
924 else
925 {
926 ASM_OUTPUT_DEBUG_ADDR (asm_out_file, TEXT_SECTION_ASM_OP);
927 if (flag_verbose_asm)
928 fprintf (asm_out_file, "\t%s line_num", ASM_COMMENT_START);
929 fputc ('\n', asm_out_file);
930 }
931
932 fn = line_info_table[1].dst_file_num;
933 ln = (file_info_table[fn].listing_line_start
934 + line_info_table[1].dst_line_num);
935 line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 4 + 4;
936 pcline.dst_b_pcline_command = DST_K_SET_LINUM_L;
937
938 totsize += write_debug_header (&line_num.dst_a_line_num_header,
939 "line_num", dosizeonly);
940 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
941 "line_num (SET LINUM LONG)", dosizeonly);
942
943 sprintf (buff, "line_num (%d)", ln - 1);
944 totsize += write_debug_data4 (ln - 1, buff, dosizeonly);
945
946 lastln = ln;
947 strcpy (lastlabel, TEXT_SECTION_ASM_OP);
948 for (i = 1; i < line_info_table_in_use; i++)
949 {
950 int extrabytes;
951
952 fn = line_info_table[i].dst_file_num;
953 ln = (file_info_table[fn].listing_line_start
954 + line_info_table[i].dst_line_num);
955
956 if (ln - lastln > 1)
957 extrabytes = 5; /* NUMBYTES (ln - lastln - 1) + 1; */
958 else if (ln <= lastln)
959 extrabytes = 5; /* NUMBYTES (ln - 1) + 1; */
960 else
961 extrabytes = 0;
962
963 line_num.dst_a_line_num_header.dst__header_length.dst_w_length
964 = 8 + extrabytes;
965
966 totsize += write_debug_header
967 (&line_num.dst_a_line_num_header, "line_num", dosizeonly);
968
969 if (ln - lastln > 1)
970 {
971 int lndif = ln - lastln - 1;
972
973 /* K_INCR_LINUM (lndif); */
974 pcline.dst_b_pcline_command = DST_K_INCR_LINUM_L;
975
976 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
977 "line_num (INCR LINUM LONG)",
978 dosizeonly);
979
980 sprintf (buff, "line_num (%d)", lndif);
981 totsize += write_debug_data4 (lndif, buff, dosizeonly);
982 }
983 else if (ln <= lastln)
984 {
985 /* K_SET_LINUM (ln-1); */
986 pcline.dst_b_pcline_command = DST_K_SET_LINUM_L;
987
988 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
989 "line_num (SET LINUM LONG)",
990 dosizeonly);
991
992 sprintf (buff, "line_num (%d)", ln - 1);
993 totsize += write_debug_data4 (ln - 1, buff, dosizeonly);
994 }
995
996 pcline.dst_b_pcline_command = DST_K_DELTA_PC_L;
997
998 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
999 "line_num (DELTA PC LONG)", dosizeonly);
1000
1001 ASM_GENERATE_INTERNAL_LABEL (label, LINE_CODE_LABEL, i);
1002 totsize += write_debug_delta4 (label, lastlabel, "increment line_num",
1003 dosizeonly);
1004
1005 lastln = ln;
1006 strcpy (lastlabel, label);
1007 }
1008
1009 return totsize;
1010}
1011
1012static int
1013write_srccorr (fileid, file_info_entry, dosizeonly)
1014 int fileid;
1015 dst_file_info_entry file_info_entry;
1016 int dosizeonly;
1017{
1018 int src_command_size;
1019 int linesleft = file_info_entry.max_line;
1020 int linestart = file_info_entry.listing_line_start;
1021 int flen = file_info_entry.flen;
1022 int linestodo = 0;
1023 DST_SOURCE_CORR src_header;
1024 DST_SRC_COMMAND src_command;
1025 DST_SRC_COMMAND src_command_sf;
1026 DST_SRC_COMMAND src_command_sl;
1027 DST_SRC_COMMAND src_command_sr;
1028 DST_SRC_COMMAND src_command_dl;
1029 DST_SRC_CMDTRLR src_cmdtrlr;
1030 char buff[256];
1031 int totsize = 0;
1032
1033 if (fileid == 1)
1034 {
1035 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1036 = DST_K_SOURCE_CORR_HEADER_SIZE + 1 - 1;
1037 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1038 = DST_K_SOURCE;
1039 src_command.dst_b_src_command = DST_K_SRC_FORMFEED;
1040
1041 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1042 "source corr", dosizeonly);
1043
1044 totsize += write_debug_data1 (src_command.dst_b_src_command,
1045 "source_corr (SRC FORMFEED)",
1046 dosizeonly);
1047 }
1048
1049 src_command_size
1050 = DST_K_SRC_COMMAND_SIZE + flen + DST_K_SRC_CMDTRLR_SIZE;
1051 src_command.dst_b_src_command = DST_K_SRC_DECLFILE;
1052 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_length
1053 = src_command_size - 2;
1054 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_flags = 0;
1055 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_fileid
1056 = fileid;
1057 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt
1058 = file_info_entry.cdt;
1059 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk
1060 = file_info_entry.ebk;
1061 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_rms_ffb
1062 = file_info_entry.ffb;
1063 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_rms_rfo
1064 = file_info_entry.rfo;
1065 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename
1066 = file_info_entry.flen;
1067
1068 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1069 = DST_K_SOURCE_CORR_HEADER_SIZE + src_command_size - 1;
1070 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1071 = DST_K_SOURCE;
1072
1073 src_cmdtrlr.dst_b_src_df_libmodname = 0;
1074
1075 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1076 "source corr", dosizeonly);
1077 totsize += write_debug_data1 (src_command.dst_b_src_command,
1078 "source_corr (DECL SRC FILE)", dosizeonly);
1079 totsize += write_debug_data1
1080 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_length,
1081 "source_corr (length)", dosizeonly);
1082
1083 totsize += write_debug_data1
1084 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_flags,
1085 "source_corr (flags)", dosizeonly);
1086
1087 totsize += write_debug_data2
1088 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_fileid,
1089 "source_corr (fileid)", dosizeonly);
1090
1091 totsize += write_debug_data8
1092 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt,
1093 "source_corr (creation date)", dosizeonly);
1094
1095 totsize += write_debug_data4
1096 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk,
1097 "source_corr (EOF block number)", dosizeonly);
1098
1099 totsize += write_debug_data2
1100 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_rms_ffb,
1101 "source_corr (first free byte)", dosizeonly);
1102
1103 totsize += write_debug_data1
1104 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_rms_rfo,
1105 "source_corr (record and file organization)", dosizeonly);
1106
1107 totsize += write_debug_data1
1108 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename,
1109 "source_corr (filename length)", dosizeonly);
1110
1111 totsize += write_debug_string (file_info_entry.file_name,
1112 "source file name", dosizeonly);
1113 totsize += write_debug_data1 (src_cmdtrlr.dst_b_src_df_libmodname,
1114 "source_corr (libmodname)", dosizeonly);
1115
1116 src_command_sf.dst_b_src_command = DST_K_SRC_SETFILE;
1117 src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword = fileid;
1118
1119 src_command_sr.dst_b_src_command = DST_K_SRC_SETREC_W;
1120 src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword = 1;
1121
1122 src_command_sl.dst_b_src_command = DST_K_SRC_SETLNUM_L;
1123 src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong = linestart + 1;
1124
1125 src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W;
1126
1127 if (linesleft > 65534)
1128 linesleft = linesleft - 65534, linestodo = 65534;
1129 else
1130 linestodo = linesleft, linesleft = 0;
1131
1132 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo;
1133
1134 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1135 = DST_K_SOURCE_CORR_HEADER_SIZE + 3 + 3 + 5 + 3 - 1;
1136 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1137 = DST_K_SOURCE;
1138
1139 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1140 "source corr", dosizeonly);
1141
1142 totsize += write_debug_data1 (src_command_sf.dst_b_src_command,
1143 "source_corr (src setfile)", dosizeonly);
1144
1145 totsize += write_debug_data2
1146 (src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword,
1147 "source_corr (fileid)", dosizeonly);
1148
1149 totsize += write_debug_data1 (src_command_sr.dst_b_src_command,
1150 "source_corr (setrec)", dosizeonly);
1151
1152 totsize += write_debug_data2
1153 (src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword,
1154 "source_corr (recnum)", dosizeonly);
1155
1156 totsize += write_debug_data1 (src_command_sl.dst_b_src_command,
1157 "source_corr (setlnum)", dosizeonly);
1158
1159 totsize += write_debug_data4
1160 (src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong,
1161 "source_corr (linenum)", dosizeonly);
1162
1163 totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
1164 "source_corr (deflines)", dosizeonly);
1165
1166 sprintf (buff, "source_corr (%d)",
1167 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
1168 totsize += write_debug_data2
1169 (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword, buff, dosizeonly);
1170
1171 while (linesleft > 0)
1172 {
1173 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1174 = DST_K_SOURCE_CORR_HEADER_SIZE + 3 - 1;
1175 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1176 = DST_K_SOURCE;
1177 src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W;
1178
1179 if (linesleft > 65534)
1180 linesleft = linesleft - 65534, linestodo = 65534;
1181 else
1182 linestodo = linesleft, linesleft = 0;
1183
1184 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo;
1185
1186 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1187 "source corr", dosizeonly);
1188 totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
1189 "source_corr (deflines)", dosizeonly);
1190 sprintf (buff, "source_corr (%d)",
1191 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
1192 totsize += write_debug_data2
1193 (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword,
1194 buff, dosizeonly);
1195 }
1196
1197 return totsize;
1198}
1199
1200static int
1201write_srccorrs (dosizeonly)
1202 int dosizeonly;
1203{
1204 unsigned int i;
1205 int totsize = 0;
1206
1207 for (i = 1; i < file_info_table_in_use; i++)
1208 totsize += write_srccorr (i, file_info_table[i], dosizeonly);
1209
1210 return totsize;
1211}
1212
1213\f
1214/* Output a marker (i.e. a label) for the beginning of a function, before
1215 the prologue. */
1216
1217static void
1218vmsdbgout_begin_prologue (line, file)
1219 unsigned int line;
1220 const char *file;
1221{
1222 char label[MAX_ARTIFICIAL_LABEL_BYTES];
1223
1224 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1225 (*dwarf2_debug_hooks.begin_prologue) (line, file);
1226
1227 if (debug_info_level > DINFO_LEVEL_NONE)
1228 {
1229 current_funcdef_number++;
1230 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL,
1231 current_funcdef_number);
1232 ASM_OUTPUT_LABEL (asm_out_file, label);
1233 }
1234}
1235
1236/* Output a marker (i.e. a label) for the beginning of a function, after
1237 the prologue. */
1238
1239void
1240vmsdbgout_after_prologue ()
1241{
1242 char label[MAX_ARTIFICIAL_LABEL_BYTES];
1243
1244 if (debug_info_level > DINFO_LEVEL_TERSE)
1245 {
1246 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL,
1247 current_funcdef_number);
1248 ASM_OUTPUT_LABEL (asm_out_file, label);
1249 }
1250}
1251
1252/* Output a marker (i.e. a label) for the absolute end of the generated code
1253 for a function definition. This gets called *after* the epilogue code has
1254 been generated. */
1255
1256static void
1257vmsdbgout_end_epilogue ()
1258{
1259 char label[MAX_ARTIFICIAL_LABEL_BYTES];
1260
1261 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1262 (*dwarf2_debug_hooks.end_epilogue) ();
1263
1264 if (debug_info_level > DINFO_LEVEL_NONE)
1265 {
1266 /* Output a label to mark the endpoint of the code generated for this
1267 function. */
1268 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL,
1269 current_funcdef_number);
1270 ASM_OUTPUT_LABEL (asm_out_file, label);
1271 }
1272}
1273
1274/* Output a marker (i.e. a label) for the beginning of the generated code for
1275 a lexical block. */
1276
1277static void
1278vmsdbgout_begin_block (line, blocknum)
1279 register unsigned line;
1280 register unsigned blocknum;
1281{
1282 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1283 (*dwarf2_debug_hooks.begin_block) (line, blocknum);
1284
1285 if (debug_info_level > DINFO_LEVEL_TERSE)
1286 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BLOCK_BEGIN_LABEL, blocknum);
1287}
1288
1289/* Output a marker (i.e. a label) for the end of the generated code for a
1290 lexical block. */
1291
1292static void
1293vmsdbgout_end_block (line, blocknum)
1294 register unsigned line;
1295 register unsigned blocknum;
1296{
1297 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1298 (*dwarf2_debug_hooks.end_block) (line, blocknum);
1299
1300 if (debug_info_level > DINFO_LEVEL_TERSE)
1301 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BLOCK_END_LABEL, blocknum);
1302}
1303
1304static bool
1305vmsdbgout_ignore_block (block)
1306 tree block;
1307{
1308 bool retval = 0;
1309
1310 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1311 retval = (*dwarf2_debug_hooks.ignore_block) (block);
1312
1313 return retval;
1314}
1315
1316static void
1317vmsdbgout_begin_function (decl)
1318 tree decl;
1319{
1320 const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
1321
1322 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1323 (*dwarf2_debug_hooks.begin_function) (decl);
1324
1325 if (func_table_in_use == func_table_allocated)
1326 {
1327 func_table_allocated += FUNC_TABLE_INCREMENT;
1328 func_table = (char **) xrealloc (func_table,
1329 func_table_allocated * sizeof (char *));
1330 }
1331
1332 /* Add the new entry to the end of the function name table. */
1333 func_table[func_table_in_use++] = xstrdup (name);
1334}
1335
1336static char fullname_buff [4096];
1337
1338static char *
1339full_name (filename)
1340 const char *filename;
1341{
1342#ifdef VMS
1343 FILE *fp = fopen (filename, "r");
1344
1345 fgetname (fp, fullname_buff, 1);
1346 fclose (fp);
1347#else
1348 getcwd (fullname_buff, sizeof (fullname_buff));
1349
1350 strcat (fullname_buff, "/");
1351 strcat (fullname_buff, filename);
1352
1353 /* ??? Insert hairy code here to translate Unix style file specification
1354 to VMS style. */
1355#endif
1356
1357 return fullname_buff;
1358}
1359
1360/* Lookup a filename (in the list of filenames that we know about here in
1361 vmsdbgout.c) and return its "index". The index of each (known) filename is
1362 just a unique number which is associated with only that one filename. We
1363 need such numbers for the sake of generating labels (in the .debug_sfnames
1364 section) and references to those files numbers (in the .debug_srcinfo
1365 and.debug_macinfo sections). If the filename given as an argument is not
1366 found in our current list, add it to the list and assign it the next
1367 available unique index number. In order to speed up searches, we remember
1368 the index of the filename was looked up last. This handles the majority of
1369 all searches. */
1370
1371static unsigned int
1372lookup_filename (file_name)
1373 const char *file_name;
1374{
1375 static unsigned int last_file_lookup_index = 0;
1376 register char *fn;
1377 register unsigned i;
1378 char *fnam;
1379 long long cdt;
1380 long ebk;
1381 short ffb;
1382 char rfo;
1383 char flen;
1384 struct stat statbuf;
1385
1386 if (stat (file_name, &statbuf) == 0)
1387 {
1388 cdt = 10000000 * (statbuf.st_ctime + vms_epoch_offset);
1389 ebk = statbuf.st_size / 512 + 1;
1390 ffb = statbuf.st_size - ((statbuf.st_size / 512) * 512);
1391#ifdef VMS
1392 rfo = statbuf.st_fab_rfm;
1393#else
1394 /* Assume stream LF type file */
1395 rfo = 2;
1396#endif
1397 fnam = full_name (file_name);
1398 flen = strlen (fnam);
1399 }
1400 else
1401 {
1402 cdt = 0;
1403 ebk = 0;
1404 ffb = 0;
1405 rfo = 0;
1406 fnam = (char *) 0;
1407 flen = 0;
1408 }
1409
1410 /* Check to see if the file name that was searched on the previous call
1411 matches this file name. If so, return the index. */
1412 if (last_file_lookup_index != 0)
1413 {
1414 fn = file_info_table[last_file_lookup_index].file_name;
1415 if (strcmp (fnam, fn) == 0)
1416 return last_file_lookup_index;
1417 }
1418
1419 /* Didn't match the previous lookup, search the table */
1420 for (i = 1; i < file_info_table_in_use; ++i)
1421 {
1422 fn = file_info_table[i].file_name;
1423 if (strcmp (fnam, fn) == 0)
1424 {
1425 last_file_lookup_index = i;
1426 return i;
1427 }
1428 }
1429
1430 /* Prepare to add a new table entry by making sure there is enough space in
1431 the table to do so. If not, expand the current table. */
1432 if (file_info_table_in_use == file_info_table_allocated)
1433 {
1434
1435 file_info_table_allocated += FILE_TABLE_INCREMENT;
1436 file_info_table
1437 = (dst_file_info_ref) xrealloc (file_info_table,
1438 (file_info_table_allocated
1439 * sizeof (dst_file_info_entry)));
1440 }
1441
1442 /* Add the new entry to the end of the filename table. */
1443 file_info_table[file_info_table_in_use].file_name = xstrdup (fnam);
1444 file_info_table[file_info_table_in_use].max_line = 0;
1445 file_info_table[file_info_table_in_use].cdt = cdt;
1446 file_info_table[file_info_table_in_use].ebk = ebk;
1447 file_info_table[file_info_table_in_use].ffb = ffb;
1448 file_info_table[file_info_table_in_use].rfo = rfo;
1449 file_info_table[file_info_table_in_use].flen = flen;
1450
1451 last_file_lookup_index = file_info_table_in_use++;
1452 return last_file_lookup_index;
1453}
1454
1455/* Output a label to mark the beginning of a source code line entry
1456 and record information relating to this source line, in
1457 'line_info_table' for later output of the .debug_line section. */
1458
1459static void
1460vmsdbgout_source_line (line, filename)
1461 register unsigned line;
1462 register const char *filename;
1463{
1464 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1465 (*dwarf2_debug_hooks.source_line) (line, filename);
1466
1467 if (debug_info_level >= DINFO_LEVEL_TERSE)
1468 {
1469 dst_line_info_ref line_info;
1470
1471 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, LINE_CODE_LABEL,
1472 line_info_table_in_use);
1473
1474 /* Expand the line info table if necessary. */
1475 if (line_info_table_in_use == line_info_table_allocated)
1476 {
1477 line_info_table_allocated += LINE_INFO_TABLE_INCREMENT;
1478 line_info_table
1479 = (dst_line_info_ref) xrealloc (line_info_table,
1480 (line_info_table_allocated
1481 * sizeof (dst_line_info_entry)));
1482 }
1483
1484 /* Add the new entry at the end of the line_info_table. */
1485 line_info = &line_info_table[line_info_table_in_use++];
1486 line_info->dst_file_num = lookup_filename (filename);
1487 line_info->dst_line_num = line;
1488 if (line > file_info_table[line_info->dst_file_num].max_line)
1489 file_info_table[line_info->dst_file_num].max_line = line;
1490 }
1491}
1492
1493/* Record the beginning of a new source file, for later output.
1494 At present, unimplemented. */
1495
1496static void
1497vmsdbgout_start_source_file (lineno, filename)
1498 unsigned int lineno;
1499 const char *filename;
1500{
1501 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1502 (*dwarf2_debug_hooks.start_source_file) (lineno, filename);
1503}
1504
1505/* Record the end of a source file, for later output.
1506 At present, unimplemented. */
1507
1508static void
1509vmsdbgout_end_source_file (lineno)
1510 unsigned int lineno ATTRIBUTE_UNUSED;
1511{
1512 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1513 (*dwarf2_debug_hooks.end_source_file) (lineno);
1514}
1515
1516/* Set up for Debug output at the start of compilation. */
1517
1518static void
1519vmsdbgout_init (main_input_filename)
1520 const char *main_input_filename;
1521{
1522 const char *language_string = lang_hooks.name;
1523
1524 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1525 (*dwarf2_debug_hooks.init) (main_input_filename);
1526
1527 if (debug_info_level == DINFO_LEVEL_NONE)
1528 return;
1529
1530 /* Remember the name of the primary input file. */
1531 primary_filename = main_input_filename;
1532
1533 /* Allocate the initial hunk of the file_info_table. */
1534 file_info_table
1535 = (dst_file_info_ref) xcalloc (FILE_TABLE_INCREMENT,
1536 sizeof (dst_file_info_entry));
1537 file_info_table_allocated = FILE_TABLE_INCREMENT;
1538
1539 /* Skip the first entry - file numbers begin at 1 */
1540 file_info_table_in_use = 1;
1541
1542 func_table = (char **) xcalloc (FUNC_TABLE_INCREMENT, sizeof (char *));
1543 func_table_allocated = FUNC_TABLE_INCREMENT;
1544 func_table_in_use = 1;
1545
1546 /* Allocate the initial hunk of the line_info_table. */
1547 line_info_table
1548 = (dst_line_info_ref) xcalloc (LINE_INFO_TABLE_INCREMENT,
1549 sizeof (dst_line_info_entry));
1550 line_info_table_allocated = LINE_INFO_TABLE_INCREMENT;
1551 /* zero-th entry is allocated, but unused */
1552 line_info_table_in_use = 1;
1553
1554 lookup_filename (primary_filename);
1555
1556 if (!strcmp (language_string, "GNU C"))
1557 module_language = DST_K_C;
1558 else if (!strcmp (language_string, "GNU C++"))
1559 module_language = DST_K_CXX;
1560 else if (!strcmp (language_string, "GNU Ada"))
1561 module_language = DST_K_ADA;
1562 else if (!strcmp (language_string, "GNU F77"))
1563 module_language = DST_K_FORTRAN;
1564 else
1565 module_language = DST_K_UNKNOWN;
1566
1567 module_producer
1568 = (char *) xmalloc (strlen (language_string) + 1
1569 + strlen (version_string + 1));
1570 sprintf (module_producer, "%s %s", language_string, version_string);
1571
1572 ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
1573
1574}
1575
1576static void
1577vmsdbgout_define (lineno, buffer)
1578 unsigned int lineno;
1579 const char *buffer;
1580{
1581 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1582 (*dwarf2_debug_hooks.define) (lineno, buffer);
1583}
1584
1585static void
1586vmsdbgout_undef (lineno, buffer)
1587 unsigned int lineno;
1588 const char *buffer;
1589{
1590 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1591 (*dwarf2_debug_hooks.undef) (lineno, buffer);
1592}
1593
1594static void
1595vmsdbgout_decl (decl)
1596 tree decl;
1597{
1598 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1599 (*dwarf2_debug_hooks.function_decl) (decl);
1600}
1601
1602static void
1603vmsdbgout_global_decl (decl)
1604 tree decl;
1605{
1606 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1607 (*dwarf2_debug_hooks.global_decl) (decl);
1608}
1609
1610static void
1611vmsdbgout_abstract_function (decl)
1612 tree decl;
1613{
1614 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1615 (*dwarf2_debug_hooks.outlining_inline_function) (decl);
1616}
1617
1618/* Output stuff that Debug requires at the end of every file,
1619 and generate the VMS Debug debugging info. */
1620
1621static void
1622vmsdbgout_finish (input_filename)
1623 const char *input_filename ATTRIBUTE_UNUSED;
1624{
1625 unsigned int i;
1626 int totsize;
1627
1628 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1629 (*dwarf2_debug_hooks.finish) (input_filename);
1630
1631 if (debug_info_level == DINFO_LEVEL_NONE)
1632 return;
1633
1634 /* Output a terminator label for the .text section. */
1635 text_section ();
1636 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, TEXT_END_LABEL, 0);
1637
1638 /* Output debugging information.
1639 Warning! Do not change the name of the .vmsdebug section without
1640 changing it in the assembler also. */
1641 named_section (NULL_TREE, ".vmsdebug", 0);
1642 ASM_OUTPUT_ALIGN (asm_out_file, 0);
1643
1644 totsize = write_modbeg (1);
1645 for (i = 1; i < func_table_in_use; i++)
1646 {
1647 totsize += write_rtnbeg (i, 1);
1648 totsize += write_rtnend (i, 1);
1649 }
1650 totsize += write_pclines (1);
1651
1652 write_modbeg (0);
1653 for (i = 1; i < func_table_in_use; i++)
1654 {
1655 write_rtnbeg (i, 0);
1656 write_rtnend (i, 0);
1657 }
1658 write_pclines (0);
1659
1660 if (debug_info_level > DINFO_LEVEL_TERSE)
1661 {
1662 totsize = write_srccorrs (1);
1663 write_srccorrs (0);
1664 }
1665
1666 totsize = write_modend (1);
1667 write_modend (0);
1668}
1669#endif /* VMS_DEBUGGING_INFO */