vmsdbgout.c revision 90075
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). 5 6This file is part of GNU CC. 7 8GCC is free software; you can redistribute it and/or modify it under 9the terms of the GNU General Public License as published by the Free 10Software Foundation; either version 2, or (at your option) any later 11version. 12 13GCC is distributed in the hope that it will be useful, but WITHOUT ANY 14WARRANTY; without even the implied warranty of MERCHANTABILITY or 15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16for more details. 17 18You should have received a copy of the GNU General Public License 19along with GCC; see the file COPYING. If not, write to the Free 20Software Foundation, 59 Temple Place - Suite 330, Boston, MA 2102111-1307, USA. */ 22 23#include "config.h" 24 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" 34 35/* Difference in seconds between the VMS Epoch and the Unix Epoch */ 36static const long long vms_epoch_offset = 3506716800ll; 37 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. */ 41 42typedef struct dst_line_info_struct *dst_line_info_ref; 43 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. */ 48typedef struct dst_line_info_struct 49{ 50 unsigned long dst_file_num; 51 unsigned long dst_line_num; 52} 53dst_line_info_entry; 54 55typedef struct dst_file_info_struct *dst_file_info_ref; 56 57typedef struct dst_file_info_struct 58{ 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; 67} 68dst_file_info_entry; 69 70/* How to start an assembler comment. */ 71#ifndef ASM_COMMENT_START 72#define ASM_COMMENT_START ";#" 73#endif 74 75/* Maximum size (in bytes) of an artificially generated label. */ 76#define MAX_ARTIFICIAL_LABEL_BYTES 30 77 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 88 89/* Pointer to an structure of filenames referenced by this compilation unit. */ 90static dst_file_info_ref file_info_table; 91 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. */ 95static unsigned int file_info_table_allocated; 96 97/* Number of entries in the file_info_table which are actually in use. */ 98static unsigned int file_info_table_in_use; 99 100/* Size (in elements) of increments by which we may expand the filename 101 table. */ 102#define FILE_TABLE_INCREMENT 64 103 104static char **func_table; 105static unsigned int func_table_allocated; 106static unsigned int func_table_in_use; 107#define FUNC_TABLE_INCREMENT 256 108 109/* Local pointer to the name of the main input file. Initialized in 110 avmdbgout_init. */ 111static const char *primary_filename; 112 113static char *module_producer; 114static unsigned int module_language; 115 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. */ 118static dst_line_info_ref line_info_table; 119 120/* Number of elements currently allocated for line_info_table. */ 121static unsigned int line_info_table_allocated; 122 123/* Number of elements in line_info_table currently in use. */ 124static unsigned int line_info_table_in_use; 125 126/* Size (in elements) of increments by which we may expand line_info_table. */ 127#define LINE_INFO_TABLE_INCREMENT 1024 128 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. */ 134static unsigned int current_funcdef_number = 0; 135 136/* Forward declarations for functions defined in this file. */ 137static char *full_name PARAMS ((const char *)); 138static unsigned int lookup_filename PARAMS ((const char *)); 139static void addr_const_to_string PARAMS ((char *, rtx)); 140static int write_debug_header PARAMS ((DST_HEADER *, const char *, int)); 141static int write_debug_addr PARAMS ((char *, const char *, int)); 142static int write_debug_data1 PARAMS ((unsigned int, const char *, int)); 143static int write_debug_data2 PARAMS ((unsigned int, const char *, int)); 144static int write_debug_data4 PARAMS ((unsigned long, const char *, int)); 145static int write_debug_data8 PARAMS ((unsigned long long, const char *, 146 int)); 147static int write_debug_delta4 PARAMS ((char *, char *, const char *, int)); 148static int write_debug_string PARAMS ((char *, const char *, int)); 149static int write_modbeg PARAMS ((int)); 150static int write_modend PARAMS ((int)); 151static int write_rtnbeg PARAMS ((int, int)); 152static int write_rtnend PARAMS ((int, int)); 153static int write_pclines PARAMS ((int)); 154static int write_srccorr PARAMS ((int, dst_file_info_entry, int)); 155static int write_srccorrs PARAMS ((int)); 156 157static void vmsdbgout_init PARAMS ((const char *)); 158static void vmsdbgout_finish PARAMS ((const char *)); 159static void vmsdbgout_define PARAMS ((unsigned int, const char *)); 160static void vmsdbgout_undef PARAMS ((unsigned int, const char *)); 161static void vmsdbgout_start_source_file PARAMS ((unsigned int, const char *)); 162static void vmsdbgout_end_source_file PARAMS ((unsigned int)); 163static void vmsdbgout_begin_block PARAMS ((unsigned int, unsigned int)); 164static void vmsdbgout_end_block PARAMS ((unsigned int, unsigned int)); 165static bool vmsdbgout_ignore_block PARAMS ((tree)); 166static void vmsdbgout_source_line PARAMS ((unsigned int, const char *)); 167static void vmsdbgout_begin_prologue PARAMS ((unsigned int, const char *)); 168static void vmsdbgout_end_epilogue PARAMS ((void)); 169static void vmsdbgout_begin_function PARAMS ((tree)); 170static void vmsdbgout_decl PARAMS ((tree)); 171static void vmsdbgout_global_decl PARAMS ((tree)); 172static void vmsdbgout_abstract_function PARAMS ((tree)); 173 174/* The debug hooks structure. */ 175 176struct 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 */ 197}; 198 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" 207 208#ifdef UNALIGNED_INT_ASM_OP 209#undef UNALIGNED_INT_ASM_OP 210#endif 211#define UNALIGNED_INT_ASM_OP ".long" 212 213#ifdef UNALIGNED_LONG_ASM_OP 214#undef UNALIGNED_LONG_ASM_OP 215#endif 216#define UNALIGNED_LONG_ASM_OP ".long" 217 218#ifdef UNALIGNED_DOUBLE_INT_ASM_OP 219#undef UNALIGNED_DOUBLE_INT_ASM_OP 220#endif 221#define UNALIGNED_DOUBLE_INT_ASM_OP ".quad" 222 223#ifdef ASM_BYTE_OP 224#undef ASM_BYTE_OP 225#endif 226#define ASM_BYTE_OP ".byte" 227 228#define NUMBYTES(I) ((I) < 256 ? 1 : (I) < 65536 ? 2 : 4) 229 230#define NUMBYTES0(I) ((I) < 128 ? 0 : (I) < 65536 ? 2 : 4) 231 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 236 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 243 244/* Pseudo-op for defining a new section. */ 245#ifndef SECTION_ASM_OP 246#define SECTION_ASM_OP ".section" 247#endif 248 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. */ 254 255static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES]; 256 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 278 279#ifndef ASM_OUTPUT_DEBUG_DELTA2 280#define ASM_OUTPUT_DEBUG_DELTA2(FILE,LABEL1,LABEL2) \ 281 do \ 282 { \ 283 fprintf ((FILE), "\t%s\t", UNALIGNED_SHORT_ASM_OP); \ 284 assemble_name (FILE, LABEL1); \ 285 fprintf (FILE, "-"); \ 286 assemble_name (FILE, LABEL2); \ 287 } \ 288 while (0) 289#endif 290 291#ifndef ASM_OUTPUT_DEBUG_DELTA4 292#define ASM_OUTPUT_DEBUG_DELTA4(FILE,LABEL1,LABEL2) \ 293 do \ 294 { \ 295 fprintf ((FILE), "\t%s\t", UNALIGNED_INT_ASM_OP); \ 296 assemble_name (FILE, LABEL1); \ 297 fprintf (FILE, "-"); \ 298 assemble_name (FILE, LABEL2); \ 299 } \ 300 while (0) 301#endif 302 303#ifndef ASM_OUTPUT_DEBUG_ADDR_DELTA 304#define ASM_OUTPUT_DEBUG_ADDR_DELTA(FILE,LABEL1,LABEL2) \ 305 do \ 306 { \ 307 fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP); \ 308 assemble_name (FILE, LABEL1); \ 309 fprintf (FILE, "-"); \ 310 assemble_name (FILE, LABEL2); \ 311 } \ 312 while (0) 313#endif 314 315#ifndef ASM_OUTPUT_DEBUG_ADDR 316#define ASM_OUTPUT_DEBUG_ADDR(FILE,LABEL) \ 317 do \ 318 { \ 319 fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP); \ 320 assemble_name (FILE, LABEL); \ 321 } \ 322 while (0) 323#endif 324 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 329 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 334 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 340 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 345 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 350 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 356 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 362 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 \ 369 { \ 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++) \ 375 { \ 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); \ 383 } \ 384 fprintf (FILE, "\""); \ 385 } \ 386 while (0) 387#endif 388 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 \ 395 { \ 396 if ((NAME)[0] == '*') \ 397 strcpy (STR, NAME+1); \ 398 else \ 399 strcpy (STR, NAME); \ 400 } \ 401 while (0) 402#endif 403 404 405/* General utility functions. */ 406 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. */ 412 413static void 414addr_const_to_string (str, x) 415 char *str; 416 rtx x; 417{ 418 char buf1[256]; 419 char buf2[256]; 420 421restart: 422 str[0] = '\0'; 423 switch (GET_CODE (x)) 424 { 425 case PC: 426 if (flag_pic) 427 strcat (str, ","); 428 else 429 abort (); 430 break; 431 432 case SYMBOL_REF: 433 ASM_NAME_TO_STRING (buf1, XSTR (x, 0)); 434 strcat (str, buf1); 435 break; 436 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; 442 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; 448 449 case CONST_INT: 450 sprintf (buf1, HOST_WIDE_INT_PRINT_DEC, INTVAL (x)); 451 strcat (str, buf1); 452 break; 453 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; 460 461 case CONST_DOUBLE: 462 if (GET_MODE (x) == VOIDmode) 463 { 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); 474 } 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; 480 481 case PLUS: 482 /* Some assemblers need integer constants to appear last (eg masm). */ 483 if (GET_CODE (XEXP (x, 0)) == CONST_INT) 484 { 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); 491 } 492 else 493 { 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); 500 } 501 break; 502 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; 509 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) 515 { 516 strcat (str, "("); 517 addr_const_to_string (buf1, XEXP (x, 1)); 518 strcat (str, buf1); 519 strcat (str, ")"); 520 } 521 else 522 { 523 addr_const_to_string (buf1, XEXP (x, 1)); 524 strcat (str, buf1); 525 } 526 break; 527 528 case ZERO_EXTEND: 529 case SIGN_EXTEND: 530 addr_const_to_string (buf1, XEXP (x, 0)); 531 strcat (str, buf1); 532 break; 533 534 default: 535 output_operand_lossage ("invalid expression as operand"); 536 } 537} 538 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. */ 542 543static int 544write_debug_header (header, comment, dosizeonly) 545 DST_HEADER *header; 546 const char *comment; 547 int dosizeonly; 548{ 549 if (!dosizeonly) 550 { 551 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file, 552 header->dst__header_length.dst_w_length); 553 554 if (flag_verbose_asm) 555 fprintf (asm_out_file, "\t%s record length", ASM_COMMENT_START); 556 fputc ('\n', asm_out_file); 557 558 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file, 559 header->dst__header_type.dst_w_type); 560 561 if (flag_verbose_asm) 562 fprintf (asm_out_file, "\t%s record type (%s)", ASM_COMMENT_START, 563 comment); 564 565 fputc ('\n', asm_out_file); 566 } 567 568 return 4; 569} 570 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. */ 574 575static int 576write_debug_addr (symbol, comment, dosizeonly) 577 char *symbol; 578 const char *comment; 579 int dosizeonly; 580{ 581 if (!dosizeonly) 582 { 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); 587 } 588 589 return PTR_SIZE; 590} 591 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. */ 595 596static int 597write_debug_data1 (data1, comment, dosizeonly) 598 unsigned int data1; 599 const char *comment; 600 int dosizeonly; 601{ 602 if (!dosizeonly) 603 { 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); 608 } 609 610 return 1; 611} 612 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. */ 616 617static int 618write_debug_data2 (data2, comment, dosizeonly) 619 unsigned int data2; 620 const char *comment; 621 int dosizeonly; 622{ 623 if (!dosizeonly) 624 { 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); 629 } 630 631 return 2; 632} 633 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. */ 636 637static int 638write_debug_data4 (data4, comment, dosizeonly) 639 unsigned long data4; 640 const char *comment; 641 int dosizeonly; 642{ 643 if (!dosizeonly) 644 { 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); 649 } 650 651 return 4; 652} 653 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. */ 656 657static int 658write_debug_data8 (data8, comment, dosizeonly) 659 unsigned long long data8; 660 const char *comment; 661 int dosizeonly; 662{ 663 if (!dosizeonly) 664 { 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); 669 } 670 671 return 8; 672} 673 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. */ 677 678static int 679write_debug_delta4 (label1, label2, comment, dosizeonly) 680 char *label1; 681 char *label2; 682 const char *comment; 683 int dosizeonly; 684{ 685 if (!dosizeonly) 686 { 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); 691 } 692 693 return 4; 694} 695 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. */ 699 700static int 701write_debug_string (string, comment, dosizeonly) 702 char *string; 703 const char *comment; 704 int dosizeonly; 705{ 706 if (!dosizeonly) 707 { 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); 712 } 713 714 return strlen (string); 715} 716 717/* Output a module begin header and return the header size. Just return the 718 size if DOSIZEONLY is non-zero. */ 719 720static int 721write_modbeg (dosizeonly) 722 int dosizeonly; 723{ 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; 731 732 /* Assumes primary filename has Unix syntax file spec. */ 733 module_name = xstrdup (basename ((char *) primary_filename)); 734 735 m = strrchr (module_name, '.'); 736 if (m) 737 *m = 0; 738 739 modnamelen = strlen (module_name); 740 for (i = 0; i < modnamelen; i++) 741 module_name[i] = TOUPPER (module_name[i]); 742 743 prodnamelen = strlen (module_producer); 744 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); 756 757 mb_trlr.dst_b_compiler = strlen (module_producer); 758 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); 777 778 return totsize; 779} 780 781/* Output a module end trailer and return the trailer size. Just return 782 the size if DOSIZEONLY is non-zero. */ 783 784static int 785write_modend (dosizeonly) 786 int dosizeonly; 787{ 788 DST_MODULE_END modend; 789 int totsize = 0; 790 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; 794 795 totsize += write_debug_header (&modend.dst_a_modend_header, "modend", 796 dosizeonly); 797 798 return totsize; 799} 800 801/* Output a routine begin header routine RTNNUM and return the header size. 802 Just return the size if DOSIZEONLY is non-zero. */ 803 804static int 805write_rtnbeg (rtnnum, dosizeonly) 806 int rtnnum; 807 int dosizeonly; 808{ 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; 816 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"); 823 824 if (!strcmp (rtnname, "main")) 825 { 826 DST_HEADER header; 827 const char *go = "TRANSFER$BREAK$GO"; 828 829 /* This command isn't documented in DSTRECORDS, so it's made to 830 look like what DEC C does */ 831 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; 837 838 totsize += write_debug_header (&header, "transfer", dosizeonly); 839 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); 842 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); 849 } 850 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; 861 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); 866 867 /* Routine Begin Address */ 868 totsize += write_debug_addr (rtnentryname, "routine entry name", dosizeonly); 869 870 /* Routine Begin PD Address */ 871 totsize += write_debug_addr (rtnname, "routine procedure descriptor", 872 dosizeonly); 873 874 /* Routine Begin Name */ 875 totsize += write_debug_data1 (rtnbeg.dst_b_rtnbeg_name, 876 "length of routine name", dosizeonly); 877 878 totsize += write_debug_string (rtnname, "routine name", dosizeonly); 879 880 free (rtnentryname); 881 882 if (debug_info_level > DINFO_LEVEL_TERSE) 883 { 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; 887 888 totsize += write_debug_header (&prolog.dst_a_prolog_header, "prolog", 889 dosizeonly); 890 891 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL, rtnnum); 892 totsize += write_debug_addr (label, "prolog breakpoint addr", 893 dosizeonly); 894 } 895 896 return totsize; 897} 898 899/* Output a routine end trailer for routine RTNNUM and return the header size. 900 Just return the size if DOSIZEONLY is non-zero. */ 901 902static int 903write_rtnend (rtnnum, dosizeonly) 904 int rtnnum; 905 int dosizeonly; 906{ 907 DST_ROUTINE_END rtnend; 908 char label1[MAX_ARTIFICIAL_LABEL_BYTES]; 909 char label2[MAX_ARTIFICIAL_LABEL_BYTES]; 910 int totsize; 911 912 totsize = 0; 913 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. */ 919 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); 924 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); 928 929 return totsize; 930} 931 932#define K_DELTA_PC(I) \ 933 ((I) < 128 ? -(I) : (I) < 65536 ? DST_K_DELTA_PC_W : DST_K_DELTA_PC_L) 934 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) 938 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) 942 943/* Output the PC to line number correlations and return the size. Just return 944 the size if DOSIZEONLY is non-zero */ 945 946static int 947write_pclines (dosizeonly) 948 int dosizeonly; 949{ 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]; 961 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; 965 966 for (i = 2; i < file_info_table_in_use; i++) 967 { 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; 971 } 972 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; 977 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); 982 983 if (dosizeonly) 984 totsize += 4; 985 else 986 { 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); 991 } 992 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; 998 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); 1003 1004 sprintf (buff, "line_num (%d)", ln - 1); 1005 totsize += write_debug_data4 (ln - 1, buff, dosizeonly); 1006 1007 lastln = ln; 1008 strcpy (lastlabel, TEXT_SECTION_ASM_OP); 1009 for (i = 1; i < line_info_table_in_use; i++) 1010 { 1011 int extrabytes; 1012 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); 1016 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; 1023 1024 line_num.dst_a_line_num_header.dst__header_length.dst_w_length 1025 = 8 + extrabytes; 1026 1027 totsize += write_debug_header 1028 (&line_num.dst_a_line_num_header, "line_num", dosizeonly); 1029 1030 if (ln - lastln > 1) 1031 { 1032 int lndif = ln - lastln - 1; 1033 1034 /* K_INCR_LINUM (lndif); */ 1035 pcline.dst_b_pcline_command = DST_K_INCR_LINUM_L; 1036 1037 totsize += write_debug_data1 (pcline.dst_b_pcline_command, 1038 "line_num (INCR LINUM LONG)", 1039 dosizeonly); 1040 1041 sprintf (buff, "line_num (%d)", lndif); 1042 totsize += write_debug_data4 (lndif, buff, dosizeonly); 1043 } 1044 else if (ln <= lastln) 1045 { 1046 /* K_SET_LINUM (ln-1); */ 1047 pcline.dst_b_pcline_command = DST_K_SET_LINUM_L; 1048 1049 totsize += write_debug_data1 (pcline.dst_b_pcline_command, 1050 "line_num (SET LINUM LONG)", 1051 dosizeonly); 1052 1053 sprintf (buff, "line_num (%d)", ln - 1); 1054 totsize += write_debug_data4 (ln - 1, buff, dosizeonly); 1055 } 1056 1057 pcline.dst_b_pcline_command = DST_K_DELTA_PC_L; 1058 1059 totsize += write_debug_data1 (pcline.dst_b_pcline_command, 1060 "line_num (DELTA PC LONG)", dosizeonly); 1061 1062 ASM_GENERATE_INTERNAL_LABEL (label, LINE_CODE_LABEL, i); 1063 totsize += write_debug_delta4 (label, lastlabel, "increment line_num", 1064 dosizeonly); 1065 1066 lastln = ln; 1067 strcpy (lastlabel, label); 1068 } 1069 1070 return totsize; 1071} 1072 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. */ 1076 1077static int 1078write_srccorr (fileid, file_info_entry, dosizeonly) 1079 int fileid; 1080 dst_file_info_entry file_info_entry; 1081 int dosizeonly; 1082{ 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; 1097 1098 if (fileid == 1) 1099 { 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; 1105 1106 totsize += write_debug_header (&src_header.dst_a_source_corr_header, 1107 "source corr", dosizeonly); 1108 1109 totsize += write_debug_data1 (src_command.dst_b_src_command, 1110 "source_corr (SRC FORMFEED)", 1111 dosizeonly); 1112 } 1113 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; 1132 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; 1137 1138 src_cmdtrlr.dst_b_src_df_libmodname = 0; 1139 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); 1147 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); 1151 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); 1155 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); 1159 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); 1163 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); 1167 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); 1171 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); 1175 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); 1180 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; 1183 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; 1186 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; 1189 1190 src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W; 1191 1192 if (linesleft > 65534) 1193 linesleft = linesleft - 65534, linestodo = 65534; 1194 else 1195 linestodo = linesleft, linesleft = 0; 1196 1197 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo; 1198 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; 1203 1204 totsize += write_debug_header (&src_header.dst_a_source_corr_header, 1205 "source corr", dosizeonly); 1206 1207 totsize += write_debug_data1 (src_command_sf.dst_b_src_command, 1208 "source_corr (src setfile)", dosizeonly); 1209 1210 totsize += write_debug_data2 1211 (src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword, 1212 "source_corr (fileid)", dosizeonly); 1213 1214 totsize += write_debug_data1 (src_command_sr.dst_b_src_command, 1215 "source_corr (setrec)", dosizeonly); 1216 1217 totsize += write_debug_data2 1218 (src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword, 1219 "source_corr (recnum)", dosizeonly); 1220 1221 totsize += write_debug_data1 (src_command_sl.dst_b_src_command, 1222 "source_corr (setlnum)", dosizeonly); 1223 1224 totsize += write_debug_data4 1225 (src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong, 1226 "source_corr (linenum)", dosizeonly); 1227 1228 totsize += write_debug_data1 (src_command_dl.dst_b_src_command, 1229 "source_corr (deflines)", dosizeonly); 1230 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); 1235 1236 while (linesleft > 0) 1237 { 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; 1243 1244 if (linesleft > 65534) 1245 linesleft = linesleft - 65534, linestodo = 65534; 1246 else 1247 linestodo = linesleft, linesleft = 0; 1248 1249 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo; 1250 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); 1260 } 1261 1262 return totsize; 1263} 1264 1265/* Output all the source correlation entries and return the size. Just return 1266 the size if DOSIZEONLY is non-zero. */ 1267 1268static int 1269write_srccorrs (dosizeonly) 1270 int dosizeonly; 1271{ 1272 unsigned int i; 1273 int totsize = 0; 1274 1275 for (i = 1; i < file_info_table_in_use; i++) 1276 totsize += write_srccorr (i, file_info_table[i], dosizeonly); 1277 1278 return totsize; 1279} 1280 1281/* Output a marker (i.e. a label) for the beginning of a function, before 1282 the prologue. */ 1283 1284static void 1285vmsdbgout_begin_prologue (line, file) 1286 unsigned int line; 1287 const char *file; 1288{ 1289 char label[MAX_ARTIFICIAL_LABEL_BYTES]; 1290 1291 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1292 (*dwarf2_debug_hooks.begin_prologue) (line, file); 1293 1294 if (debug_info_level > DINFO_LEVEL_NONE) 1295 { 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); 1300 } 1301} 1302 1303/* Output a marker (i.e. a label) for the beginning of a function, after 1304 the prologue. */ 1305 1306void 1307vmsdbgout_after_prologue () 1308{ 1309 char label[MAX_ARTIFICIAL_LABEL_BYTES]; 1310 1311 if (debug_info_level > DINFO_LEVEL_TERSE) 1312 { 1313 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL, 1314 current_funcdef_number); 1315 ASM_OUTPUT_LABEL (asm_out_file, label); 1316 } 1317} 1318 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. */ 1322 1323static void 1324vmsdbgout_end_epilogue () 1325{ 1326 char label[MAX_ARTIFICIAL_LABEL_BYTES]; 1327 1328 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1329 (*dwarf2_debug_hooks.end_epilogue) (); 1330 1331 if (debug_info_level > DINFO_LEVEL_NONE) 1332 { 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); 1338 } 1339} 1340 1341/* Output a marker (i.e. a label) for the beginning of the generated code for 1342 a lexical block. */ 1343 1344static void 1345vmsdbgout_begin_block (line, blocknum) 1346 register unsigned line; 1347 register unsigned blocknum; 1348{ 1349 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1350 (*dwarf2_debug_hooks.begin_block) (line, blocknum); 1351 1352 if (debug_info_level > DINFO_LEVEL_TERSE) 1353 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BLOCK_BEGIN_LABEL, blocknum); 1354} 1355 1356/* Output a marker (i.e. a label) for the end of the generated code for a 1357 lexical block. */ 1358 1359static void 1360vmsdbgout_end_block (line, blocknum) 1361 register unsigned line; 1362 register unsigned blocknum; 1363{ 1364 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1365 (*dwarf2_debug_hooks.end_block) (line, blocknum); 1366 1367 if (debug_info_level > DINFO_LEVEL_TERSE) 1368 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BLOCK_END_LABEL, blocknum); 1369} 1370 1371/* Not implemented in VMS Debug. */ 1372 1373static bool 1374vmsdbgout_ignore_block (block) 1375 tree block; 1376{ 1377 bool retval = 0; 1378 1379 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1380 retval = (*dwarf2_debug_hooks.ignore_block) (block); 1381 1382 return retval; 1383} 1384 1385/* Add an entry for function DECL into the func_table. */ 1386 1387static void 1388vmsdbgout_begin_function (decl) 1389 tree decl; 1390{ 1391 const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0); 1392 1393 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1394 (*dwarf2_debug_hooks.begin_function) (decl); 1395 1396 if (func_table_in_use == func_table_allocated) 1397 { 1398 func_table_allocated += FUNC_TABLE_INCREMENT; 1399 func_table = (char **) xrealloc (func_table, 1400 func_table_allocated * sizeof (char *)); 1401 } 1402 1403 /* Add the new entry to the end of the function name table. */ 1404 func_table[func_table_in_use++] = xstrdup (name); 1405} 1406 1407static char fullname_buff [4096]; 1408 1409/* Return the full file specification for FILENAME. The specification must be 1410 in VMS syntax in order to be processed by VMS Debug. */ 1411 1412static char * 1413full_name (filename) 1414 const char *filename; 1415{ 1416#ifdef VMS 1417 FILE *fp = fopen (filename, "r"); 1418 1419 fgetname (fp, fullname_buff, 1); 1420 fclose (fp); 1421#else 1422 getcwd (fullname_buff, sizeof (fullname_buff)); 1423 1424 strcat (fullname_buff, "/"); 1425 strcat (fullname_buff, filename); 1426 1427 /* ??? Insert hairy code here to translate Unix style file specification 1428 to VMS style. */ 1429#endif 1430 1431 return fullname_buff; 1432} 1433 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. */ 1443 1444static unsigned int 1445lookup_filename (file_name) 1446 const char *file_name; 1447{ 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; 1458 1459 if (stat (file_name, &statbuf) == 0) 1460 { 1461 cdt = 10000000 * (statbuf.st_ctime + vms_epoch_offset); 1462 ebk = statbuf.st_size / 512 + 1; 1463 ffb = statbuf.st_size - ((statbuf.st_size / 512) * 512); 1464#ifdef VMS 1465 rfo = statbuf.st_fab_rfm; 1466#else 1467 /* Assume stream LF type file */ 1468 rfo = 2; 1469#endif 1470 fnam = full_name (file_name); 1471 flen = strlen (fnam); 1472 } 1473 else 1474 { 1475 cdt = 0; 1476 ebk = 0; 1477 ffb = 0; 1478 rfo = 0; 1479 fnam = (char *) ""; 1480 flen = 0; 1481 } 1482 1483 /* Check to see if the file name that was searched on the previous call 1484 matches this file name. If so, return the index. */ 1485 if (last_file_lookup_index != 0) 1486 { 1487 fn = file_info_table[last_file_lookup_index].file_name; 1488 if (strcmp (fnam, fn) == 0) 1489 return last_file_lookup_index; 1490 } 1491 1492 /* Didn't match the previous lookup, search the table */ 1493 for (i = 1; i < file_info_table_in_use; ++i) 1494 { 1495 fn = file_info_table[i].file_name; 1496 if (strcmp (fnam, fn) == 0) 1497 { 1498 last_file_lookup_index = i; 1499 return i; 1500 } 1501 } 1502 1503 /* Prepare to add a new table entry by making sure there is enough space in 1504 the table to do so. If not, expand the current table. */ 1505 if (file_info_table_in_use == file_info_table_allocated) 1506 { 1507 1508 file_info_table_allocated += FILE_TABLE_INCREMENT; 1509 file_info_table 1510 = (dst_file_info_ref) xrealloc (file_info_table, 1511 (file_info_table_allocated 1512 * sizeof (dst_file_info_entry))); 1513 } 1514 1515 /* Add the new entry to the end of the filename table. */ 1516 file_info_table[file_info_table_in_use].file_name = xstrdup (fnam); 1517 file_info_table[file_info_table_in_use].max_line = 0; 1518 file_info_table[file_info_table_in_use].cdt = cdt; 1519 file_info_table[file_info_table_in_use].ebk = ebk; 1520 file_info_table[file_info_table_in_use].ffb = ffb; 1521 file_info_table[file_info_table_in_use].rfo = rfo; 1522 file_info_table[file_info_table_in_use].flen = flen; 1523 1524 last_file_lookup_index = file_info_table_in_use++; 1525 return last_file_lookup_index; 1526} 1527 1528/* Output a label to mark the beginning of a source code line entry 1529 and record information relating to this source line, in 1530 'line_info_table' for later output of the .debug_line section. */ 1531 1532static void 1533vmsdbgout_source_line (line, filename) 1534 register unsigned line; 1535 register const char *filename; 1536{ 1537 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1538 (*dwarf2_debug_hooks.source_line) (line, filename); 1539 1540 if (debug_info_level >= DINFO_LEVEL_TERSE) 1541 { 1542 dst_line_info_ref line_info; 1543 1544 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, LINE_CODE_LABEL, 1545 line_info_table_in_use); 1546 1547 /* Expand the line info table if necessary. */ 1548 if (line_info_table_in_use == line_info_table_allocated) 1549 { 1550 line_info_table_allocated += LINE_INFO_TABLE_INCREMENT; 1551 line_info_table 1552 = (dst_line_info_ref) xrealloc (line_info_table, 1553 (line_info_table_allocated 1554 * sizeof (dst_line_info_entry))); 1555 } 1556 1557 /* Add the new entry at the end of the line_info_table. */ 1558 line_info = &line_info_table[line_info_table_in_use++]; 1559 line_info->dst_file_num = lookup_filename (filename); 1560 line_info->dst_line_num = line; 1561 if (line > file_info_table[line_info->dst_file_num].max_line) 1562 file_info_table[line_info->dst_file_num].max_line = line; 1563 } 1564} 1565 1566/* Record the beginning of a new source file, for later output. 1567 At present, unimplemented. */ 1568 1569static void 1570vmsdbgout_start_source_file (lineno, filename) 1571 unsigned int lineno; 1572 const char *filename; 1573{ 1574 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1575 (*dwarf2_debug_hooks.start_source_file) (lineno, filename); 1576} 1577 1578/* Record the end of a source file, for later output. 1579 At present, unimplemented. */ 1580 1581static void 1582vmsdbgout_end_source_file (lineno) 1583 unsigned int lineno ATTRIBUTE_UNUSED; 1584{ 1585 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1586 (*dwarf2_debug_hooks.end_source_file) (lineno); 1587} 1588 1589/* Set up for Debug output at the start of compilation. */ 1590 1591static void 1592vmsdbgout_init (main_input_filename) 1593 const char *main_input_filename; 1594{ 1595 const char *language_string = lang_hooks.name; 1596 1597 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1598 (*dwarf2_debug_hooks.init) (main_input_filename); 1599 1600 if (debug_info_level == DINFO_LEVEL_NONE) 1601 return; 1602 1603 /* Remember the name of the primary input file. */ 1604 primary_filename = main_input_filename; 1605 1606 /* Allocate the initial hunk of the file_info_table. */ 1607 file_info_table 1608 = (dst_file_info_ref) xcalloc (FILE_TABLE_INCREMENT, 1609 sizeof (dst_file_info_entry)); 1610 file_info_table_allocated = FILE_TABLE_INCREMENT; 1611 1612 /* Skip the first entry - file numbers begin at 1 */ 1613 file_info_table_in_use = 1; 1614 1615 func_table = (char **) xcalloc (FUNC_TABLE_INCREMENT, sizeof (char *)); 1616 func_table_allocated = FUNC_TABLE_INCREMENT; 1617 func_table_in_use = 1; 1618 1619 /* Allocate the initial hunk of the line_info_table. */ 1620 line_info_table 1621 = (dst_line_info_ref) xcalloc (LINE_INFO_TABLE_INCREMENT, 1622 sizeof (dst_line_info_entry)); 1623 line_info_table_allocated = LINE_INFO_TABLE_INCREMENT; 1624 /* zero-th entry is allocated, but unused */ 1625 line_info_table_in_use = 1; 1626 1627 lookup_filename (primary_filename); 1628 1629 if (!strcmp (language_string, "GNU C")) 1630 module_language = DST_K_C; 1631 else if (!strcmp (language_string, "GNU C++")) 1632 module_language = DST_K_CXX; 1633 else if (!strcmp (language_string, "GNU Ada")) 1634 module_language = DST_K_ADA; 1635 else if (!strcmp (language_string, "GNU F77")) 1636 module_language = DST_K_FORTRAN; 1637 else 1638 module_language = DST_K_UNKNOWN; 1639 1640 module_producer 1641 = (char *) xmalloc (strlen (language_string) + 1 1642 + strlen (version_string + 1)); 1643 sprintf (module_producer, "%s %s", language_string, version_string); 1644 1645 ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0); 1646 1647} 1648 1649/* Not implemented in VMS Debug. */ 1650 1651static void 1652vmsdbgout_define (lineno, buffer) 1653 unsigned int lineno; 1654 const char *buffer; 1655{ 1656 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1657 (*dwarf2_debug_hooks.define) (lineno, buffer); 1658} 1659 1660/* Not implemented in VMS Debug. */ 1661 1662static void 1663vmsdbgout_undef (lineno, buffer) 1664 unsigned int lineno; 1665 const char *buffer; 1666{ 1667 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1668 (*dwarf2_debug_hooks.undef) (lineno, buffer); 1669} 1670 1671/* Not implemented in VMS Debug. */ 1672 1673static void 1674vmsdbgout_decl (decl) 1675 tree decl; 1676{ 1677 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1678 (*dwarf2_debug_hooks.function_decl) (decl); 1679} 1680 1681/* Not implemented in VMS Debug. */ 1682 1683static void 1684vmsdbgout_global_decl (decl) 1685 tree decl; 1686{ 1687 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1688 (*dwarf2_debug_hooks.global_decl) (decl); 1689} 1690 1691/* Not implemented in VMS Debug. */ 1692 1693static void 1694vmsdbgout_abstract_function (decl) 1695 tree decl; 1696{ 1697 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1698 (*dwarf2_debug_hooks.outlining_inline_function) (decl); 1699} 1700 1701/* Output stuff that Debug requires at the end of every file and generate the 1702 VMS Debug debugging info. */ 1703 1704static void 1705vmsdbgout_finish (input_filename) 1706 const char *input_filename ATTRIBUTE_UNUSED; 1707{ 1708 unsigned int i; 1709 int totsize; 1710 1711 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1712 (*dwarf2_debug_hooks.finish) (input_filename); 1713 1714 if (debug_info_level == DINFO_LEVEL_NONE) 1715 return; 1716 1717 /* Output a terminator label for the .text section. */ 1718 text_section (); 1719 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, TEXT_END_LABEL, 0); 1720 1721 /* Output debugging information. 1722 Warning! Do not change the name of the .vmsdebug section without 1723 changing it in the assembler also. */ 1724 named_section (NULL_TREE, ".vmsdebug", 0); 1725 ASM_OUTPUT_ALIGN (asm_out_file, 0); 1726 1727 totsize = write_modbeg (1); 1728 for (i = 1; i < func_table_in_use; i++) 1729 { 1730 totsize += write_rtnbeg (i, 1); 1731 totsize += write_rtnend (i, 1); 1732 } 1733 totsize += write_pclines (1); 1734 1735 write_modbeg (0); 1736 for (i = 1; i < func_table_in_use; i++) 1737 { 1738 write_rtnbeg (i, 0); 1739 write_rtnend (i, 0); 1740 } 1741 write_pclines (0); 1742 1743 if (debug_info_level > DINFO_LEVEL_TERSE) 1744 { 1745 totsize = write_srccorrs (1); 1746 write_srccorrs (0); 1747 } 1748 1749 totsize = write_modend (1); 1750 write_modend (0); 1751} 1752#endif /* VMS_DEBUGGING_INFO */ 1753