1132718Skan/* Output VMS debug format symbol table information from GCC. 290075Sobrien Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 3169689Skan 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. 490075Sobrien Contributed by Douglas B. Rupp (rupp@gnat.com). 5169689Skan Updated by Bernard W. Giroud (bgiroud@users.sourceforge.net). 690075Sobrien 7132718SkanThis file is part of GCC. 890075Sobrien 990075SobrienGCC is free software; you can redistribute it and/or modify it under 1090075Sobrienthe terms of the GNU General Public License as published by the Free 1190075SobrienSoftware Foundation; either version 2, or (at your option) any later 1290075Sobrienversion. 1390075Sobrien 1490075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1590075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or 1690075SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1790075Sobrienfor more details. 1890075Sobrien 1990075SobrienYou should have received a copy of the GNU General Public License 2090075Sobrienalong with GCC; see the file COPYING. If not, write to the Free 21169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 22169689Skan02110-1301, USA. */ 2390075Sobrien 2490075Sobrien#include "config.h" 25132718Skan#include "system.h" 26132718Skan#include "coretypes.h" 27132718Skan#include "tm.h" 2890075Sobrien 2990075Sobrien#ifdef VMS_DEBUGGING_INFO 3090075Sobrien#include "tree.h" 31169689Skan#include "version.h" 3290075Sobrien#include "flags.h" 3390075Sobrien#include "rtl.h" 3490075Sobrien#include "output.h" 3590075Sobrien#include "vmsdbg.h" 3690075Sobrien#include "debug.h" 3790075Sobrien#include "langhooks.h" 38117395Skan#include "function.h" 39132718Skan#include "target.h" 4090075Sobrien 4190075Sobrien/* Difference in seconds between the VMS Epoch and the Unix Epoch */ 4290075Sobrienstatic const long long vms_epoch_offset = 3506716800ll; 4390075Sobrien 4490075Sobrien/* NOTE: In the comments in this file, many references are made to "Debug 4590075Sobrien Symbol Table". This term is abbreviated as `DST' throughout the remainder 4690075Sobrien of this file. */ 4790075Sobrien 4890075Sobrientypedef struct dst_line_info_struct *dst_line_info_ref; 4990075Sobrien 5090075Sobrien/* Each entry in the line_info_table maintains the file and 5190075Sobrien line number associated with the label generated for that 5290075Sobrien entry. The label gives the PC value associated with 5390075Sobrien the line number entry. */ 5490075Sobrientypedef struct dst_line_info_struct 5590075Sobrien{ 5690075Sobrien unsigned long dst_file_num; 5790075Sobrien unsigned long dst_line_num; 5890075Sobrien} 5990075Sobriendst_line_info_entry; 6090075Sobrien 6190075Sobrientypedef struct dst_file_info_struct *dst_file_info_ref; 6290075Sobrien 6390075Sobrientypedef struct dst_file_info_struct 6490075Sobrien{ 6590075Sobrien char *file_name; 6690075Sobrien unsigned int max_line; 6790075Sobrien unsigned int listing_line_start; 6890075Sobrien long long cdt; 6990075Sobrien long ebk; 7090075Sobrien short ffb; 7190075Sobrien char rfo; 7290075Sobrien char flen; 7390075Sobrien} 7490075Sobriendst_file_info_entry; 7590075Sobrien 7690075Sobrien/* How to start an assembler comment. */ 7790075Sobrien#ifndef ASM_COMMENT_START 7890075Sobrien#define ASM_COMMENT_START ";#" 7990075Sobrien#endif 8090075Sobrien 8190075Sobrien/* Maximum size (in bytes) of an artificially generated label. */ 8290075Sobrien#define MAX_ARTIFICIAL_LABEL_BYTES 30 8390075Sobrien 8490075Sobrien/* Make sure we know the sizes of the various types debug can describe. These 8590075Sobrien are only defaults. If the sizes are different for your target, you should 8690075Sobrien override these values by defining the appropriate symbols in your tm.h 8790075Sobrien file. */ 8890075Sobrien#ifndef PTR_SIZE 8990075Sobrien#define PTR_SIZE 4 /* Must be 32 bits for VMS debug info */ 9090075Sobrien#endif 9190075Sobrien 92117395Skan/* Pointer to a structure of filenames referenced by this compilation unit. */ 9390075Sobrienstatic dst_file_info_ref file_info_table; 9490075Sobrien 9590075Sobrien/* Total number of entries in the table (i.e. array) pointed to by 9690075Sobrien `file_info_table'. This is the *total* and includes both used and unused 9790075Sobrien slots. */ 9890075Sobrienstatic unsigned int file_info_table_allocated; 9990075Sobrien 10090075Sobrien/* Number of entries in the file_info_table which are actually in use. */ 10190075Sobrienstatic unsigned int file_info_table_in_use; 10290075Sobrien 10390075Sobrien/* Size (in elements) of increments by which we may expand the filename 10490075Sobrien table. */ 10590075Sobrien#define FILE_TABLE_INCREMENT 64 10690075Sobrien 107169689Skan/* A structure to hold basic information for the VMS end 108169689Skan routine. */ 109169689Skan 110169689Skantypedef struct vms_func_struct 111169689Skan{ 112169689Skan const char *vms_func_name; 113169689Skan unsigned funcdef_number; 114169689Skan} 115169689Skanvms_func_node; 116169689Skan 117169689Skantypedef struct vms_func_struct *vms_func_ref; 118169689Skan 11990075Sobrienstatic unsigned int func_table_allocated; 12090075Sobrienstatic unsigned int func_table_in_use; 12190075Sobrien#define FUNC_TABLE_INCREMENT 256 12290075Sobrien 123169689Skan/* A pointer to the base of a table that contains frame description 124169689Skan information for each routine. */ 125169689Skanstatic vms_func_ref func_table; 126169689Skan 12790075Sobrien/* Local pointer to the name of the main input file. Initialized in 12890075Sobrien avmdbgout_init. */ 12990075Sobrienstatic const char *primary_filename; 13090075Sobrien 13190075Sobrienstatic char *module_producer; 13290075Sobrienstatic unsigned int module_language; 13390075Sobrien 13490075Sobrien/* A pointer to the base of a table that contains line information 13590075Sobrien for each source code line in .text in the compilation unit. */ 13690075Sobrienstatic dst_line_info_ref line_info_table; 13790075Sobrien 13890075Sobrien/* Number of elements currently allocated for line_info_table. */ 13990075Sobrienstatic unsigned int line_info_table_allocated; 14090075Sobrien 14190075Sobrien/* Number of elements in line_info_table currently in use. */ 14290075Sobrienstatic unsigned int line_info_table_in_use; 14390075Sobrien 14490075Sobrien/* Size (in elements) of increments by which we may expand line_info_table. */ 14590075Sobrien#define LINE_INFO_TABLE_INCREMENT 1024 14690075Sobrien 14790075Sobrien/* Forward declarations for functions defined in this file. */ 148132718Skanstatic char *full_name (const char *); 149132718Skanstatic unsigned int lookup_filename (const char *); 150132718Skanstatic void addr_const_to_string (char *, rtx); 151132718Skanstatic int write_debug_header (DST_HEADER *, const char *, int); 152132718Skanstatic int write_debug_addr (char *, const char *, int); 153132718Skanstatic int write_debug_data1 (unsigned int, const char *, int); 154132718Skanstatic int write_debug_data2 (unsigned int, const char *, int); 155132718Skanstatic int write_debug_data4 (unsigned long, const char *, int); 156132718Skanstatic int write_debug_data8 (unsigned long long, const char *, int); 157132718Skanstatic int write_debug_delta4 (char *, char *, const char *, int); 158132718Skanstatic int write_debug_string (char *, const char *, int); 159132718Skanstatic int write_modbeg (int); 160132718Skanstatic int write_modend (int); 161132718Skanstatic int write_rtnbeg (int, int); 162132718Skanstatic int write_rtnend (int, int); 163132718Skanstatic int write_pclines (int); 164132718Skanstatic int write_srccorr (int, dst_file_info_entry, int); 165132718Skanstatic int write_srccorrs (int); 16690075Sobrien 167132718Skanstatic void vmsdbgout_init (const char *); 168132718Skanstatic void vmsdbgout_finish (const char *); 169132718Skanstatic void vmsdbgout_define (unsigned int, const char *); 170132718Skanstatic void vmsdbgout_undef (unsigned int, const char *); 171132718Skanstatic void vmsdbgout_start_source_file (unsigned int, const char *); 172132718Skanstatic void vmsdbgout_end_source_file (unsigned int); 173132718Skanstatic void vmsdbgout_begin_block (unsigned int, unsigned int); 174132718Skanstatic void vmsdbgout_end_block (unsigned int, unsigned int); 175132718Skanstatic bool vmsdbgout_ignore_block (tree); 176132718Skanstatic void vmsdbgout_source_line (unsigned int, const char *); 177132718Skanstatic void vmsdbgout_begin_prologue (unsigned int, const char *); 178132718Skanstatic void vmsdbgout_end_prologue (unsigned int, const char *); 179132718Skanstatic void vmsdbgout_end_function (unsigned int); 180132718Skanstatic void vmsdbgout_end_epilogue (unsigned int, const char *); 181132718Skanstatic void vmsdbgout_begin_function (tree); 182132718Skanstatic void vmsdbgout_decl (tree); 183132718Skanstatic void vmsdbgout_global_decl (tree); 184132718Skanstatic void vmsdbgout_abstract_function (tree); 18590075Sobrien 18690075Sobrien/* The debug hooks structure. */ 18790075Sobrien 188117395Skanconst struct gcc_debug_hooks vmsdbg_debug_hooks 18990075Sobrien= {vmsdbgout_init, 19090075Sobrien vmsdbgout_finish, 19190075Sobrien vmsdbgout_define, 19290075Sobrien vmsdbgout_undef, 19390075Sobrien vmsdbgout_start_source_file, 19490075Sobrien vmsdbgout_end_source_file, 19590075Sobrien vmsdbgout_begin_block, 19690075Sobrien vmsdbgout_end_block, 19790075Sobrien vmsdbgout_ignore_block, 19890075Sobrien vmsdbgout_source_line, 19990075Sobrien vmsdbgout_begin_prologue, 200117395Skan vmsdbgout_end_prologue, 201117395Skan vmsdbgout_end_epilogue, 202117395Skan vmsdbgout_begin_function, 203117395Skan vmsdbgout_end_function, 20490075Sobrien vmsdbgout_decl, 20590075Sobrien vmsdbgout_global_decl, 206169689Skan debug_nothing_tree_int, /* type_decl */ 207169689Skan debug_nothing_tree_tree, /* imported_module_or_decl */ 208169689Skan debug_nothing_tree, /* deferred_inline_function */ 20990075Sobrien vmsdbgout_abstract_function, 210169689Skan debug_nothing_rtx, /* label */ 211169689Skan debug_nothing_int, /* handle_pch */ 212169689Skan debug_nothing_rtx, /* var_location */ 213169689Skan debug_nothing_void, /* switch_text_section */ 214169689Skan 0 /* start_end_main_source_file */ 21590075Sobrien}; 21690075Sobrien 21790075Sobrien/* Definitions of defaults for assembler-dependent names of various 21890075Sobrien pseudo-ops and section names. 21990075Sobrien Theses may be overridden in the tm.h file (if necessary) for a particular 22090075Sobrien assembler. */ 22190075Sobrien#ifdef UNALIGNED_SHORT_ASM_OP 22290075Sobrien#undef UNALIGNED_SHORT_ASM_OP 22390075Sobrien#endif 22490075Sobrien#define UNALIGNED_SHORT_ASM_OP ".word" 22590075Sobrien 22690075Sobrien#ifdef UNALIGNED_INT_ASM_OP 22790075Sobrien#undef UNALIGNED_INT_ASM_OP 22890075Sobrien#endif 22990075Sobrien#define UNALIGNED_INT_ASM_OP ".long" 23090075Sobrien 23190075Sobrien#ifdef UNALIGNED_LONG_ASM_OP 23290075Sobrien#undef UNALIGNED_LONG_ASM_OP 23390075Sobrien#endif 23490075Sobrien#define UNALIGNED_LONG_ASM_OP ".long" 23590075Sobrien 23690075Sobrien#ifdef UNALIGNED_DOUBLE_INT_ASM_OP 23790075Sobrien#undef UNALIGNED_DOUBLE_INT_ASM_OP 23890075Sobrien#endif 23990075Sobrien#define UNALIGNED_DOUBLE_INT_ASM_OP ".quad" 24090075Sobrien 24190075Sobrien#ifdef ASM_BYTE_OP 24290075Sobrien#undef ASM_BYTE_OP 24390075Sobrien#endif 24490075Sobrien#define ASM_BYTE_OP ".byte" 24590075Sobrien 24690075Sobrien#define NUMBYTES(I) ((I) < 256 ? 1 : (I) < 65536 ? 2 : 4) 24790075Sobrien 24890075Sobrien#define NUMBYTES0(I) ((I) < 128 ? 0 : (I) < 65536 ? 2 : 4) 24990075Sobrien 25090075Sobrien#ifndef UNALIGNED_PTR_ASM_OP 25190075Sobrien#define UNALIGNED_PTR_ASM_OP \ 25290075Sobrien (PTR_SIZE == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP : UNALIGNED_INT_ASM_OP) 25390075Sobrien#endif 25490075Sobrien 25590075Sobrien#ifndef UNALIGNED_OFFSET_ASM_OP 25690075Sobrien#define UNALIGNED_OFFSET_ASM_OP(OFFSET) \ 25790075Sobrien (NUMBYTES(OFFSET) == 4 \ 25890075Sobrien ? UNALIGNED_LONG_ASM_OP \ 25990075Sobrien : (NUMBYTES(OFFSET) == 2 ? UNALIGNED_SHORT_ASM_OP : ASM_BYTE_OP)) 26090075Sobrien#endif 26190075Sobrien 26290075Sobrien/* Definitions of defaults for formats and names of various special 26390075Sobrien (artificial) labels which may be generated within this file (when the -g 26490075Sobrien options is used and VMS_DEBUGGING_INFO is in effect. If necessary, these 26590075Sobrien may be overridden from within the tm.h file, but typically, overriding these 26690075Sobrien defaults is unnecessary. */ 26790075Sobrien 26890075Sobrienstatic char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES]; 26990075Sobrien 27090075Sobrien#ifndef TEXT_END_LABEL 27190075Sobrien#define TEXT_END_LABEL "Lvetext" 27290075Sobrien#endif 27390075Sobrien#ifndef FUNC_BEGIN_LABEL 27490075Sobrien#define FUNC_BEGIN_LABEL "LVFB" 27590075Sobrien#endif 27690075Sobrien#ifndef FUNC_PROLOG_LABEL 27790075Sobrien#define FUNC_PROLOG_LABEL "LVFP" 27890075Sobrien#endif 27990075Sobrien#ifndef FUNC_END_LABEL 28090075Sobrien#define FUNC_END_LABEL "LVFE" 28190075Sobrien#endif 28290075Sobrien#ifndef BLOCK_BEGIN_LABEL 28390075Sobrien#define BLOCK_BEGIN_LABEL "LVBB" 28490075Sobrien#endif 28590075Sobrien#ifndef BLOCK_END_LABEL 28690075Sobrien#define BLOCK_END_LABEL "LVBE" 28790075Sobrien#endif 28890075Sobrien#ifndef LINE_CODE_LABEL 28990075Sobrien#define LINE_CODE_LABEL "LVM" 29090075Sobrien#endif 29190075Sobrien 29290075Sobrien#ifndef ASM_OUTPUT_DEBUG_DELTA2 29390075Sobrien#define ASM_OUTPUT_DEBUG_DELTA2(FILE,LABEL1,LABEL2) \ 29490075Sobrien do \ 29590075Sobrien { \ 29690075Sobrien fprintf ((FILE), "\t%s\t", UNALIGNED_SHORT_ASM_OP); \ 29790075Sobrien assemble_name (FILE, LABEL1); \ 29890075Sobrien fprintf (FILE, "-"); \ 29990075Sobrien assemble_name (FILE, LABEL2); \ 30090075Sobrien } \ 30190075Sobrien while (0) 30290075Sobrien#endif 30390075Sobrien 30490075Sobrien#ifndef ASM_OUTPUT_DEBUG_DELTA4 30590075Sobrien#define ASM_OUTPUT_DEBUG_DELTA4(FILE,LABEL1,LABEL2) \ 30690075Sobrien do \ 30790075Sobrien { \ 30890075Sobrien fprintf ((FILE), "\t%s\t", UNALIGNED_INT_ASM_OP); \ 30990075Sobrien assemble_name (FILE, LABEL1); \ 31090075Sobrien fprintf (FILE, "-"); \ 31190075Sobrien assemble_name (FILE, LABEL2); \ 31290075Sobrien } \ 31390075Sobrien while (0) 31490075Sobrien#endif 31590075Sobrien 31690075Sobrien#ifndef ASM_OUTPUT_DEBUG_ADDR_DELTA 31790075Sobrien#define ASM_OUTPUT_DEBUG_ADDR_DELTA(FILE,LABEL1,LABEL2) \ 31890075Sobrien do \ 31990075Sobrien { \ 32090075Sobrien fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP); \ 32190075Sobrien assemble_name (FILE, LABEL1); \ 32290075Sobrien fprintf (FILE, "-"); \ 32390075Sobrien assemble_name (FILE, LABEL2); \ 32490075Sobrien } \ 32590075Sobrien while (0) 32690075Sobrien#endif 32790075Sobrien 32890075Sobrien#ifndef ASM_OUTPUT_DEBUG_ADDR 32990075Sobrien#define ASM_OUTPUT_DEBUG_ADDR(FILE,LABEL) \ 33090075Sobrien do \ 33190075Sobrien { \ 33290075Sobrien fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP); \ 33390075Sobrien assemble_name (FILE, LABEL); \ 33490075Sobrien } \ 33590075Sobrien while (0) 33690075Sobrien#endif 33790075Sobrien 33890075Sobrien#ifndef ASM_OUTPUT_DEBUG_ADDR_CONST 33990075Sobrien#define ASM_OUTPUT_DEBUG_ADDR_CONST(FILE,ADDR) \ 34090075Sobrien fprintf ((FILE), "\t%s\t%s", UNALIGNED_PTR_ASM_OP, (ADDR)) 34190075Sobrien#endif 34290075Sobrien 34390075Sobrien#ifndef ASM_OUTPUT_DEBUG_DATA1 34490075Sobrien#define ASM_OUTPUT_DEBUG_DATA1(FILE,VALUE) \ 34590075Sobrien fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, (unsigned char) VALUE) 34690075Sobrien#endif 34790075Sobrien 34890075Sobrien#ifndef ASM_OUTPUT_DEBUG_DATA2 34990075Sobrien#define ASM_OUTPUT_DEBUG_DATA2(FILE,VALUE) \ 35090075Sobrien fprintf ((FILE), "\t%s\t0x%x", UNALIGNED_SHORT_ASM_OP, \ 35190075Sobrien (unsigned short) VALUE) 35290075Sobrien#endif 35390075Sobrien 35490075Sobrien#ifndef ASM_OUTPUT_DEBUG_DATA4 35590075Sobrien#define ASM_OUTPUT_DEBUG_DATA4(FILE,VALUE) \ 35690075Sobrien fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_INT_ASM_OP, (unsigned long) VALUE) 35790075Sobrien#endif 35890075Sobrien 35990075Sobrien#ifndef ASM_OUTPUT_DEBUG_DATA 36090075Sobrien#define ASM_OUTPUT_DEBUG_DATA(FILE,VALUE) \ 36190075Sobrien fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_OFFSET_ASM_OP(VALUE), VALUE) 36290075Sobrien#endif 36390075Sobrien 36490075Sobrien#ifndef ASM_OUTPUT_DEBUG_ADDR_DATA 36590075Sobrien#define ASM_OUTPUT_DEBUG_ADDR_DATA(FILE,VALUE) \ 36690075Sobrien fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_PTR_ASM_OP, \ 36790075Sobrien (unsigned long) VALUE) 36890075Sobrien#endif 36990075Sobrien 37090075Sobrien#ifndef ASM_OUTPUT_DEBUG_DATA8 37190075Sobrien#define ASM_OUTPUT_DEBUG_DATA8(FILE,VALUE) \ 37290075Sobrien fprintf ((FILE), "\t%s\t0x%llx", UNALIGNED_DOUBLE_INT_ASM_OP, \ 37390075Sobrien (unsigned long long) VALUE) 37490075Sobrien#endif 37590075Sobrien 37690075Sobrien/* This is similar to the default ASM_OUTPUT_ASCII, except that no trailing 377132718Skan newline is produced. When flag_verbose_asm is asserted, we add commentary 37890075Sobrien at the end of the line, so we must avoid output of a newline here. */ 37990075Sobrien#ifndef ASM_OUTPUT_DEBUG_STRING 38090075Sobrien#define ASM_OUTPUT_DEBUG_STRING(FILE,P) \ 38190075Sobrien do \ 38290075Sobrien { \ 38390075Sobrien register int slen = strlen(P); \ 38490075Sobrien register char *p = (P); \ 38590075Sobrien register int i; \ 38690075Sobrien fprintf (FILE, "\t.ascii \""); \ 38790075Sobrien for (i = 0; i < slen; i++) \ 38890075Sobrien { \ 38990075Sobrien register int c = p[i]; \ 39090075Sobrien if (c == '\"' || c == '\\') \ 39190075Sobrien putc ('\\', FILE); \ 39290075Sobrien if (c >= ' ' && c < 0177) \ 39390075Sobrien putc (c, FILE); \ 39490075Sobrien else \ 39590075Sobrien fprintf (FILE, "\\%o", c); \ 39690075Sobrien } \ 39790075Sobrien fprintf (FILE, "\""); \ 39890075Sobrien } \ 39990075Sobrien while (0) 40090075Sobrien#endif 40190075Sobrien 40290075Sobrien/* Convert a reference to the assembler name of a C-level name. This 40390075Sobrien macro has the same effect as ASM_OUTPUT_LABELREF, but copies to 40490075Sobrien a string rather than writing to a file. */ 40590075Sobrien#ifndef ASM_NAME_TO_STRING 406132718Skan#define ASM_NAME_TO_STRING(STR, NAME) \ 40790075Sobrien do \ 40890075Sobrien { \ 40990075Sobrien if ((NAME)[0] == '*') \ 41090075Sobrien strcpy (STR, NAME+1); \ 41190075Sobrien else \ 41290075Sobrien strcpy (STR, NAME); \ 41390075Sobrien } \ 41490075Sobrien while (0) 41590075Sobrien#endif 41690075Sobrien 41790075Sobrien 41890075Sobrien/* General utility functions. */ 41990075Sobrien 42090075Sobrien/* Convert an integer constant expression into assembler syntax. Addition and 42190075Sobrien subtraction are the only arithmetic that may appear in these expressions. 42290075Sobrien This is an adaptation of output_addr_const in final.c. Here, the target 42390075Sobrien of the conversion is a string buffer. We can't use output_addr_const 42490075Sobrien directly, because it writes to a file. */ 42590075Sobrien 42690075Sobrienstatic void 427132718Skanaddr_const_to_string (char *str, rtx x) 42890075Sobrien{ 42990075Sobrien char buf1[256]; 43090075Sobrien char buf2[256]; 43190075Sobrien 432169689Skan restart: 43390075Sobrien str[0] = '\0'; 43490075Sobrien switch (GET_CODE (x)) 43590075Sobrien { 43690075Sobrien case PC: 437169689Skan gcc_assert (flag_pic); 438169689Skan strcat (str, ","); 43990075Sobrien break; 44090075Sobrien 44190075Sobrien case SYMBOL_REF: 44290075Sobrien ASM_NAME_TO_STRING (buf1, XSTR (x, 0)); 44390075Sobrien strcat (str, buf1); 44490075Sobrien break; 44590075Sobrien 44690075Sobrien case LABEL_REF: 44790075Sobrien ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (XEXP (x, 0))); 44890075Sobrien ASM_NAME_TO_STRING (buf2, buf1); 44990075Sobrien strcat (str, buf2); 45090075Sobrien break; 45190075Sobrien 45290075Sobrien case CODE_LABEL: 45390075Sobrien ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (x)); 45490075Sobrien ASM_NAME_TO_STRING (buf2, buf1); 45590075Sobrien strcat (str, buf2); 45690075Sobrien break; 45790075Sobrien 45890075Sobrien case CONST_INT: 45990075Sobrien sprintf (buf1, HOST_WIDE_INT_PRINT_DEC, INTVAL (x)); 46090075Sobrien strcat (str, buf1); 46190075Sobrien break; 46290075Sobrien 46390075Sobrien case CONST: 464117395Skan /* This used to output parentheses around the expression, but that does 46590075Sobrien not work on the 386 (either ATT or BSD assembler). */ 46690075Sobrien addr_const_to_string (buf1, XEXP (x, 0)); 46790075Sobrien strcat (str, buf1); 46890075Sobrien break; 46990075Sobrien 47090075Sobrien case CONST_DOUBLE: 47190075Sobrien if (GET_MODE (x) == VOIDmode) 47290075Sobrien { 47390075Sobrien /* We can use %d if the number is one word and positive. */ 47490075Sobrien if (CONST_DOUBLE_HIGH (x)) 47590075Sobrien sprintf (buf1, HOST_WIDE_INT_PRINT_DOUBLE_HEX, 47690075Sobrien CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x)); 47790075Sobrien else if (CONST_DOUBLE_LOW (x) < 0) 47890075Sobrien sprintf (buf1, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (x)); 47990075Sobrien else 48090075Sobrien sprintf (buf1, HOST_WIDE_INT_PRINT_DEC, 48190075Sobrien CONST_DOUBLE_LOW (x)); 48290075Sobrien strcat (str, buf1); 48390075Sobrien } 48490075Sobrien else 48590075Sobrien /* We can't handle floating point constants; PRINT_OPERAND must 48690075Sobrien handle them. */ 48790075Sobrien output_operand_lossage ("floating constant misused"); 48890075Sobrien break; 48990075Sobrien 49090075Sobrien case PLUS: 49190075Sobrien /* Some assemblers need integer constants to appear last (eg masm). */ 49290075Sobrien if (GET_CODE (XEXP (x, 0)) == CONST_INT) 49390075Sobrien { 49490075Sobrien addr_const_to_string (buf1, XEXP (x, 1)); 49590075Sobrien strcat (str, buf1); 49690075Sobrien if (INTVAL (XEXP (x, 0)) >= 0) 49790075Sobrien strcat (str, "+"); 49890075Sobrien addr_const_to_string (buf1, XEXP (x, 0)); 49990075Sobrien strcat (str, buf1); 50090075Sobrien } 50190075Sobrien else 50290075Sobrien { 50390075Sobrien addr_const_to_string (buf1, XEXP (x, 0)); 50490075Sobrien strcat (str, buf1); 50590075Sobrien if (INTVAL (XEXP (x, 1)) >= 0) 50690075Sobrien strcat (str, "+"); 50790075Sobrien addr_const_to_string (buf1, XEXP (x, 1)); 50890075Sobrien strcat (str, buf1); 50990075Sobrien } 51090075Sobrien break; 51190075Sobrien 51290075Sobrien case MINUS: 51390075Sobrien /* Avoid outputting things like x-x or x+5-x, since some assemblers 51490075Sobrien can't handle that. */ 51590075Sobrien x = simplify_subtraction (x); 51690075Sobrien if (GET_CODE (x) != MINUS) 51790075Sobrien goto restart; 51890075Sobrien 51990075Sobrien addr_const_to_string (buf1, XEXP (x, 0)); 52090075Sobrien strcat (str, buf1); 52190075Sobrien strcat (str, "-"); 52290075Sobrien if (GET_CODE (XEXP (x, 1)) == CONST_INT 52390075Sobrien && INTVAL (XEXP (x, 1)) < 0) 52490075Sobrien { 52590075Sobrien strcat (str, "("); 52690075Sobrien addr_const_to_string (buf1, XEXP (x, 1)); 52790075Sobrien strcat (str, buf1); 52890075Sobrien strcat (str, ")"); 52990075Sobrien } 53090075Sobrien else 53190075Sobrien { 53290075Sobrien addr_const_to_string (buf1, XEXP (x, 1)); 53390075Sobrien strcat (str, buf1); 53490075Sobrien } 53590075Sobrien break; 53690075Sobrien 53790075Sobrien case ZERO_EXTEND: 53890075Sobrien case SIGN_EXTEND: 53990075Sobrien addr_const_to_string (buf1, XEXP (x, 0)); 54090075Sobrien strcat (str, buf1); 54190075Sobrien break; 54290075Sobrien 54390075Sobrien default: 54490075Sobrien output_operand_lossage ("invalid expression as operand"); 54590075Sobrien } 54690075Sobrien} 54790075Sobrien 54890075Sobrien/* Output the debug header HEADER. Also output COMMENT if flag_verbose_asm is 54990075Sobrien set. Return the header size. Just return the size if DOSIZEONLY is 550117395Skan nonzero. */ 55190075Sobrien 55290075Sobrienstatic int 553132718Skanwrite_debug_header (DST_HEADER *header, const char *comment, int dosizeonly) 55490075Sobrien{ 55590075Sobrien if (!dosizeonly) 55690075Sobrien { 55790075Sobrien ASM_OUTPUT_DEBUG_DATA2 (asm_out_file, 55890075Sobrien header->dst__header_length.dst_w_length); 55990075Sobrien 56090075Sobrien if (flag_verbose_asm) 56190075Sobrien fprintf (asm_out_file, "\t%s record length", ASM_COMMENT_START); 56290075Sobrien fputc ('\n', asm_out_file); 56390075Sobrien 56490075Sobrien ASM_OUTPUT_DEBUG_DATA2 (asm_out_file, 56590075Sobrien header->dst__header_type.dst_w_type); 56690075Sobrien 56790075Sobrien if (flag_verbose_asm) 56890075Sobrien fprintf (asm_out_file, "\t%s record type (%s)", ASM_COMMENT_START, 56990075Sobrien comment); 57090075Sobrien 57190075Sobrien fputc ('\n', asm_out_file); 57290075Sobrien } 57390075Sobrien 57490075Sobrien return 4; 57590075Sobrien} 57690075Sobrien 57790075Sobrien/* Output the address of SYMBOL. Also output COMMENT if flag_verbose_asm is 57890075Sobrien set. Return the address size. Just return the size if DOSIZEONLY is 579117395Skan nonzero. */ 58090075Sobrien 58190075Sobrienstatic int 582132718Skanwrite_debug_addr (char *symbol, const char *comment, int dosizeonly) 58390075Sobrien{ 58490075Sobrien if (!dosizeonly) 58590075Sobrien { 58690075Sobrien ASM_OUTPUT_DEBUG_ADDR (asm_out_file, symbol); 58790075Sobrien if (flag_verbose_asm) 58890075Sobrien fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment); 58990075Sobrien fputc ('\n', asm_out_file); 59090075Sobrien } 59190075Sobrien 59290075Sobrien return PTR_SIZE; 59390075Sobrien} 59490075Sobrien 59590075Sobrien/* Output the single byte DATA1. Also output COMMENT if flag_verbose_asm is 59690075Sobrien set. Return the data size. Just return the size if DOSIZEONLY is 597117395Skan nonzero. */ 59890075Sobrien 59990075Sobrienstatic int 600132718Skanwrite_debug_data1 (unsigned int data1, const char *comment, int dosizeonly) 60190075Sobrien{ 60290075Sobrien if (!dosizeonly) 60390075Sobrien { 60490075Sobrien ASM_OUTPUT_DEBUG_DATA1 (asm_out_file, data1); 60590075Sobrien if (flag_verbose_asm) 60690075Sobrien fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment); 60790075Sobrien fputc ('\n', asm_out_file); 60890075Sobrien } 60990075Sobrien 61090075Sobrien return 1; 61190075Sobrien} 61290075Sobrien 61390075Sobrien/* Output the single word DATA2. Also output COMMENT if flag_verbose_asm is 61490075Sobrien set. Return the data size. Just return the size if DOSIZEONLY is 615117395Skan nonzero. */ 61690075Sobrien 61790075Sobrienstatic int 618132718Skanwrite_debug_data2 (unsigned int data2, const char *comment, int dosizeonly) 61990075Sobrien{ 62090075Sobrien if (!dosizeonly) 62190075Sobrien { 62290075Sobrien ASM_OUTPUT_DEBUG_DATA2 (asm_out_file, data2); 62390075Sobrien if (flag_verbose_asm) 62490075Sobrien fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment); 62590075Sobrien fputc ('\n', asm_out_file); 62690075Sobrien } 62790075Sobrien 62890075Sobrien return 2; 62990075Sobrien} 63090075Sobrien 63190075Sobrien/* Output double word DATA4. Also output COMMENT if flag_verbose_asm is set. 632117395Skan Return the data size. Just return the size if DOSIZEONLY is nonzero. */ 63390075Sobrien 63490075Sobrienstatic int 635132718Skanwrite_debug_data4 (unsigned long data4, const char *comment, int dosizeonly) 63690075Sobrien{ 63790075Sobrien if (!dosizeonly) 63890075Sobrien { 63990075Sobrien ASM_OUTPUT_DEBUG_DATA4 (asm_out_file, data4); 64090075Sobrien if (flag_verbose_asm) 64190075Sobrien fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment); 64290075Sobrien fputc ('\n', asm_out_file); 64390075Sobrien } 644117395Skan 64590075Sobrien return 4; 64690075Sobrien} 64790075Sobrien 64890075Sobrien/* Output quad word DATA8. Also output COMMENT if flag_verbose_asm is set. 649117395Skan Return the data size. Just return the size if DOSIZEONLY is nonzero. */ 65090075Sobrien 65190075Sobrienstatic int 652132718Skanwrite_debug_data8 (unsigned long long data8, const char *comment, 653132718Skan int dosizeonly) 65490075Sobrien{ 65590075Sobrien if (!dosizeonly) 65690075Sobrien { 65790075Sobrien ASM_OUTPUT_DEBUG_DATA8 (asm_out_file, data8); 65890075Sobrien if (flag_verbose_asm) 65990075Sobrien fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment); 66090075Sobrien fputc ('\n', asm_out_file); 66190075Sobrien } 66290075Sobrien 66390075Sobrien return 8; 66490075Sobrien} 66590075Sobrien 66690075Sobrien/* Output the difference between LABEL1 and LABEL2. Also output COMMENT if 66790075Sobrien flag_verbose_asm is set. Return the data size. Just return the size if 668117395Skan DOSIZEONLY is nonzero. */ 66990075Sobrien 67090075Sobrienstatic int 671132718Skanwrite_debug_delta4 (char *label1, char *label2, const char *comment, 672132718Skan int dosizeonly) 67390075Sobrien{ 67490075Sobrien if (!dosizeonly) 67590075Sobrien { 67690075Sobrien ASM_OUTPUT_DEBUG_DELTA4 (asm_out_file, label1, label2); 67790075Sobrien if (flag_verbose_asm) 67890075Sobrien fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment); 67990075Sobrien fputc ('\n', asm_out_file); 68090075Sobrien } 68190075Sobrien 68290075Sobrien return 4; 68390075Sobrien} 68490075Sobrien 68590075Sobrien/* Output a character string STRING. Also write COMMENT if flag_verbose_asm is 68690075Sobrien set. Return the string length. Just return the length if DOSIZEONLY is 687117395Skan nonzero. */ 68890075Sobrien 68990075Sobrienstatic int 690132718Skanwrite_debug_string (char *string, const char *comment, int dosizeonly) 69190075Sobrien{ 69290075Sobrien if (!dosizeonly) 69390075Sobrien { 69490075Sobrien ASM_OUTPUT_DEBUG_STRING (asm_out_file, string); 69590075Sobrien if (flag_verbose_asm) 69690075Sobrien fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment); 69790075Sobrien fputc ('\n', asm_out_file); 69890075Sobrien } 699117395Skan 70090075Sobrien return strlen (string); 70190075Sobrien} 70290075Sobrien 70390075Sobrien/* Output a module begin header and return the header size. Just return the 704117395Skan size if DOSIZEONLY is nonzero. */ 70590075Sobrien 70690075Sobrienstatic int 707132718Skanwrite_modbeg (int dosizeonly) 70890075Sobrien{ 70990075Sobrien DST_MODULE_BEGIN modbeg; 71090075Sobrien DST_MB_TRLR mb_trlr; 71190075Sobrien int i; 71290075Sobrien char *module_name, *m; 71390075Sobrien int modnamelen; 71490075Sobrien int prodnamelen; 71590075Sobrien int totsize = 0; 71690075Sobrien 71790075Sobrien /* Assumes primary filename has Unix syntax file spec. */ 71890075Sobrien module_name = xstrdup (basename ((char *) primary_filename)); 71990075Sobrien 72090075Sobrien m = strrchr (module_name, '.'); 72190075Sobrien if (m) 72290075Sobrien *m = 0; 72390075Sobrien 72490075Sobrien modnamelen = strlen (module_name); 72590075Sobrien for (i = 0; i < modnamelen; i++) 72690075Sobrien module_name[i] = TOUPPER (module_name[i]); 72790075Sobrien 72890075Sobrien prodnamelen = strlen (module_producer); 72990075Sobrien 73090075Sobrien modbeg.dst_a_modbeg_header.dst__header_length.dst_w_length 73190075Sobrien = DST_K_MODBEG_SIZE + modnamelen + DST_K_MB_TRLR_SIZE + prodnamelen - 1; 73290075Sobrien modbeg.dst_a_modbeg_header.dst__header_type.dst_w_type = DST_K_MODBEG; 73390075Sobrien modbeg.dst_b_modbeg_flags.dst_v_modbeg_hide = 0; 73490075Sobrien modbeg.dst_b_modbeg_flags.dst_v_modbeg_version = 1; 73590075Sobrien modbeg.dst_b_modbeg_flags.dst_v_modbeg_unused = 0; 73690075Sobrien modbeg.dst_b_modbeg_unused = 0; 73790075Sobrien modbeg.dst_l_modbeg_language = module_language; 73890075Sobrien modbeg.dst_w_version_major = DST_K_VERSION_MAJOR; 73990075Sobrien modbeg.dst_w_version_minor = DST_K_VERSION_MINOR; 74090075Sobrien modbeg.dst_b_modbeg_name = strlen (module_name); 74190075Sobrien 74290075Sobrien mb_trlr.dst_b_compiler = strlen (module_producer); 74390075Sobrien 74490075Sobrien totsize += write_debug_header (&modbeg.dst_a_modbeg_header, 74590075Sobrien "modbeg", dosizeonly); 74690075Sobrien totsize += write_debug_data1 (*((char *) &modbeg.dst_b_modbeg_flags), 74790075Sobrien "flags", dosizeonly); 74890075Sobrien totsize += write_debug_data1 (modbeg.dst_b_modbeg_unused, 74990075Sobrien "unused", dosizeonly); 75090075Sobrien totsize += write_debug_data4 (modbeg.dst_l_modbeg_language, 75190075Sobrien "language", dosizeonly); 75290075Sobrien totsize += write_debug_data2 (modbeg.dst_w_version_major, 75390075Sobrien "DST major version", dosizeonly); 75490075Sobrien totsize += write_debug_data2 (modbeg.dst_w_version_minor, 75590075Sobrien "DST minor version", dosizeonly); 75690075Sobrien totsize += write_debug_data1 (modbeg.dst_b_modbeg_name, 75790075Sobrien "length of module name", dosizeonly); 75890075Sobrien totsize += write_debug_string (module_name, "module name", dosizeonly); 75990075Sobrien totsize += write_debug_data1 (mb_trlr.dst_b_compiler, 76090075Sobrien "length of compiler name", dosizeonly); 76190075Sobrien totsize += write_debug_string (module_producer, "compiler name", dosizeonly); 76290075Sobrien 76390075Sobrien return totsize; 76490075Sobrien} 76590075Sobrien 76690075Sobrien/* Output a module end trailer and return the trailer size. Just return 767117395Skan the size if DOSIZEONLY is nonzero. */ 76890075Sobrien 76990075Sobrienstatic int 770132718Skanwrite_modend (int dosizeonly) 77190075Sobrien{ 77290075Sobrien DST_MODULE_END modend; 77390075Sobrien int totsize = 0; 77490075Sobrien 77590075Sobrien modend.dst_a_modend_header.dst__header_length.dst_w_length 77690075Sobrien = DST_K_MODEND_SIZE - 1; 77790075Sobrien modend.dst_a_modend_header.dst__header_type.dst_w_type = DST_K_MODEND; 77890075Sobrien 77990075Sobrien totsize += write_debug_header (&modend.dst_a_modend_header, "modend", 78090075Sobrien dosizeonly); 78190075Sobrien 78290075Sobrien return totsize; 78390075Sobrien} 78490075Sobrien 78590075Sobrien/* Output a routine begin header routine RTNNUM and return the header size. 786117395Skan Just return the size if DOSIZEONLY is nonzero. */ 78790075Sobrien 78890075Sobrienstatic int 789132718Skanwrite_rtnbeg (int rtnnum, int dosizeonly) 79090075Sobrien{ 79190075Sobrien char *rtnname; 792117395Skan int rtnnamelen; 79390075Sobrien char *rtnentryname; 79490075Sobrien int totsize = 0; 79590075Sobrien char label[MAX_ARTIFICIAL_LABEL_BYTES]; 79690075Sobrien DST_ROUTINE_BEGIN rtnbeg; 79790075Sobrien DST_PROLOG prolog; 798169689Skan vms_func_ref fde = &func_table[rtnnum]; 79990075Sobrien 800169689Skan rtnname = (char *)fde->vms_func_name; 80190075Sobrien rtnnamelen = strlen (rtnname); 802117395Skan rtnentryname = concat (rtnname, "..en", NULL); 80390075Sobrien 80490075Sobrien if (!strcmp (rtnname, "main")) 80590075Sobrien { 80690075Sobrien DST_HEADER header; 80790075Sobrien const char *go = "TRANSFER$BREAK$GO"; 80890075Sobrien 80990075Sobrien /* This command isn't documented in DSTRECORDS, so it's made to 81090075Sobrien look like what DEC C does */ 81190075Sobrien 81290075Sobrien /* header size - 1st byte + flag byte + STO_LW size 81390075Sobrien + string count byte + string length */ 81490075Sobrien header.dst__header_length.dst_w_length 815117395Skan = DST_K_DST_HEADER_SIZE - 1 + 1 + 4 + 1 + strlen (go); 81690075Sobrien header.dst__header_type.dst_w_type = 0x17; 81790075Sobrien 81890075Sobrien totsize += write_debug_header (&header, "transfer", dosizeonly); 81990075Sobrien 82090075Sobrien /* I think this is a flag byte, but I don't know what this flag means */ 82190075Sobrien totsize += write_debug_data1 (0x1, "flags ???", dosizeonly); 82290075Sobrien 82390075Sobrien /* Routine Begin PD Address */ 82490075Sobrien totsize += write_debug_addr (rtnname, "main procedure descriptor", 82590075Sobrien dosizeonly); 82690075Sobrien totsize += write_debug_data1 (strlen (go), "length of main_name", 82790075Sobrien dosizeonly); 82890075Sobrien totsize += write_debug_string ((char *) go, "main name", dosizeonly); 82990075Sobrien } 83090075Sobrien 831132718Skan /* The header length never includes the length byte. */ 83290075Sobrien rtnbeg.dst_a_rtnbeg_header.dst__header_length.dst_w_length 83390075Sobrien = DST_K_RTNBEG_SIZE + rtnnamelen - 1; 83490075Sobrien rtnbeg.dst_a_rtnbeg_header.dst__header_type.dst_w_type = DST_K_RTNBEG; 83590075Sobrien rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_unused = 0; 83690075Sobrien rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_unalloc = 0; 83790075Sobrien rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_prototype = 0; 83890075Sobrien rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_inlined = 0; 83990075Sobrien rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_no_call = 1; 84090075Sobrien rtnbeg.dst_b_rtnbeg_name = rtnnamelen; 84190075Sobrien 84290075Sobrien totsize += write_debug_header (&rtnbeg.dst_a_rtnbeg_header, "rtnbeg", 84390075Sobrien dosizeonly); 84490075Sobrien totsize += write_debug_data1 (*((char *) &rtnbeg.dst_b_rtnbeg_flags), 84590075Sobrien "flags", dosizeonly); 84690075Sobrien 84790075Sobrien /* Routine Begin Address */ 84890075Sobrien totsize += write_debug_addr (rtnentryname, "routine entry name", dosizeonly); 84990075Sobrien 85090075Sobrien /* Routine Begin PD Address */ 85190075Sobrien totsize += write_debug_addr (rtnname, "routine procedure descriptor", 85290075Sobrien dosizeonly); 85390075Sobrien 85490075Sobrien /* Routine Begin Name */ 85590075Sobrien totsize += write_debug_data1 (rtnbeg.dst_b_rtnbeg_name, 85690075Sobrien "length of routine name", dosizeonly); 85790075Sobrien 85890075Sobrien totsize += write_debug_string (rtnname, "routine name", dosizeonly); 85990075Sobrien 86090075Sobrien free (rtnentryname); 86190075Sobrien 86290075Sobrien if (debug_info_level > DINFO_LEVEL_TERSE) 86390075Sobrien { 86490075Sobrien prolog.dst_a_prolog_header.dst__header_length.dst_w_length 86590075Sobrien = DST_K_PROLOG_SIZE - 1; 86690075Sobrien prolog.dst_a_prolog_header.dst__header_type.dst_w_type = DST_K_PROLOG; 86790075Sobrien 86890075Sobrien totsize += write_debug_header (&prolog.dst_a_prolog_header, "prolog", 86990075Sobrien dosizeonly); 87090075Sobrien 871169689Skan ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL, fde->funcdef_number); 87290075Sobrien totsize += write_debug_addr (label, "prolog breakpoint addr", 87390075Sobrien dosizeonly); 87490075Sobrien } 87590075Sobrien 87690075Sobrien return totsize; 87790075Sobrien} 87890075Sobrien 87990075Sobrien/* Output a routine end trailer for routine RTNNUM and return the header size. 880117395Skan Just return the size if DOSIZEONLY is nonzero. */ 88190075Sobrien 88290075Sobrienstatic int 883132718Skanwrite_rtnend (int rtnnum, int dosizeonly) 88490075Sobrien{ 88590075Sobrien DST_ROUTINE_END rtnend; 88690075Sobrien char label1[MAX_ARTIFICIAL_LABEL_BYTES]; 88790075Sobrien char label2[MAX_ARTIFICIAL_LABEL_BYTES]; 88890075Sobrien int totsize; 889169689Skan vms_func_ref fde = &func_table[rtnnum]; 890169689Skan int corrected_rtnnum = fde->funcdef_number; 89190075Sobrien 89290075Sobrien totsize = 0; 89390075Sobrien 89490075Sobrien rtnend.dst_a_rtnend_header.dst__header_length.dst_w_length 89590075Sobrien = DST_K_RTNEND_SIZE - 1; 89690075Sobrien rtnend.dst_a_rtnend_header.dst__header_type.dst_w_type = DST_K_RTNEND; 89790075Sobrien rtnend.dst_b_rtnend_unused = 0; 89890075Sobrien rtnend.dst_l_rtnend_size = 0; /* Calculated below. */ 89990075Sobrien 90090075Sobrien totsize += write_debug_header (&rtnend.dst_a_rtnend_header, "rtnend", 90190075Sobrien dosizeonly); 90290075Sobrien totsize += write_debug_data1 (rtnend.dst_b_rtnend_unused, "unused", 90390075Sobrien dosizeonly); 90490075Sobrien 905169689Skan ASM_GENERATE_INTERNAL_LABEL (label1, FUNC_BEGIN_LABEL, corrected_rtnnum); 906169689Skan ASM_GENERATE_INTERNAL_LABEL (label2, FUNC_END_LABEL, corrected_rtnnum); 90790075Sobrien totsize += write_debug_delta4 (label2, label1, "routine size", dosizeonly); 90890075Sobrien 90990075Sobrien return totsize; 91090075Sobrien} 91190075Sobrien 91290075Sobrien#define K_DELTA_PC(I) \ 91390075Sobrien ((I) < 128 ? -(I) : (I) < 65536 ? DST_K_DELTA_PC_W : DST_K_DELTA_PC_L) 91490075Sobrien 91590075Sobrien#define K_SET_LINUM(I) \ 91690075Sobrien ((I) < 256 ? DST_K_SET_LINUM_B \ 91790075Sobrien : (I) < 65536 ? DST_K_SET_LINUM : DST_K_SET_LINUM_L) 91890075Sobrien 91990075Sobrien#define K_INCR_LINUM(I) \ 92090075Sobrien ((I) < 256 ? DST_K_INCR_LINUM \ 92190075Sobrien : (I) < 65536 ? DST_K_INCR_LINUM_W : DST_K_INCR_LINUM_L) 92290075Sobrien 92390075Sobrien/* Output the PC to line number correlations and return the size. Just return 924117395Skan the size if DOSIZEONLY is nonzero */ 92590075Sobrien 92690075Sobrienstatic int 927132718Skanwrite_pclines (int dosizeonly) 92890075Sobrien{ 92990075Sobrien unsigned i; 93090075Sobrien int fn; 93190075Sobrien int ln, lastln; 93290075Sobrien int linestart = 0; 93390075Sobrien int max_line; 93490075Sobrien DST_LINE_NUM_HEADER line_num; 93590075Sobrien DST_PCLINE_COMMANDS pcline; 93690075Sobrien char label[MAX_ARTIFICIAL_LABEL_BYTES]; 93790075Sobrien char lastlabel[MAX_ARTIFICIAL_LABEL_BYTES]; 93890075Sobrien int totsize = 0; 93990075Sobrien char buff[256]; 94090075Sobrien 94190075Sobrien max_line = file_info_table[1].max_line; 94290075Sobrien file_info_table[1].listing_line_start = linestart; 94390075Sobrien linestart = linestart + ((max_line / 100000) + 1) * 100000; 94490075Sobrien 94590075Sobrien for (i = 2; i < file_info_table_in_use; i++) 94690075Sobrien { 94790075Sobrien max_line = file_info_table[i].max_line; 94890075Sobrien file_info_table[i].listing_line_start = linestart; 94990075Sobrien linestart = linestart + ((max_line / 10000) + 1) * 10000; 95090075Sobrien } 95190075Sobrien 952132718Skan /* Set starting address to beginning of text section. */ 95390075Sobrien line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 8; 95490075Sobrien line_num.dst_a_line_num_header.dst__header_type.dst_w_type = DST_K_LINE_NUM; 95590075Sobrien pcline.dst_b_pcline_command = DST_K_SET_ABS_PC; 95690075Sobrien 95790075Sobrien totsize += write_debug_header (&line_num.dst_a_line_num_header, 95890075Sobrien "line_num", dosizeonly); 95990075Sobrien totsize += write_debug_data1 (pcline.dst_b_pcline_command, 96090075Sobrien "line_num (SET ABS PC)", dosizeonly); 96190075Sobrien 96290075Sobrien if (dosizeonly) 96390075Sobrien totsize += 4; 96490075Sobrien else 96590075Sobrien { 96690075Sobrien ASM_OUTPUT_DEBUG_ADDR (asm_out_file, TEXT_SECTION_ASM_OP); 96790075Sobrien if (flag_verbose_asm) 96890075Sobrien fprintf (asm_out_file, "\t%s line_num", ASM_COMMENT_START); 96990075Sobrien fputc ('\n', asm_out_file); 97090075Sobrien } 97190075Sobrien 97290075Sobrien fn = line_info_table[1].dst_file_num; 97390075Sobrien ln = (file_info_table[fn].listing_line_start 97490075Sobrien + line_info_table[1].dst_line_num); 97590075Sobrien line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 4 + 4; 97690075Sobrien pcline.dst_b_pcline_command = DST_K_SET_LINUM_L; 97790075Sobrien 97890075Sobrien totsize += write_debug_header (&line_num.dst_a_line_num_header, 97990075Sobrien "line_num", dosizeonly); 98090075Sobrien totsize += write_debug_data1 (pcline.dst_b_pcline_command, 98190075Sobrien "line_num (SET LINUM LONG)", dosizeonly); 98290075Sobrien 983117395Skan sprintf (buff, "line_num (%d)", ln ? ln - 1 : 0); 984117395Skan totsize += write_debug_data4 (ln ? ln - 1 : 0, buff, dosizeonly); 98590075Sobrien 98690075Sobrien lastln = ln; 98790075Sobrien strcpy (lastlabel, TEXT_SECTION_ASM_OP); 98890075Sobrien for (i = 1; i < line_info_table_in_use; i++) 98990075Sobrien { 99090075Sobrien int extrabytes; 99190075Sobrien 99290075Sobrien fn = line_info_table[i].dst_file_num; 99390075Sobrien ln = (file_info_table[fn].listing_line_start 99490075Sobrien + line_info_table[i].dst_line_num); 99590075Sobrien 99690075Sobrien if (ln - lastln > 1) 99790075Sobrien extrabytes = 5; /* NUMBYTES (ln - lastln - 1) + 1; */ 99890075Sobrien else if (ln <= lastln) 99990075Sobrien extrabytes = 5; /* NUMBYTES (ln - 1) + 1; */ 100090075Sobrien else 100190075Sobrien extrabytes = 0; 100290075Sobrien 100390075Sobrien line_num.dst_a_line_num_header.dst__header_length.dst_w_length 100490075Sobrien = 8 + extrabytes; 100590075Sobrien 100690075Sobrien totsize += write_debug_header 100790075Sobrien (&line_num.dst_a_line_num_header, "line_num", dosizeonly); 100890075Sobrien 100990075Sobrien if (ln - lastln > 1) 101090075Sobrien { 101190075Sobrien int lndif = ln - lastln - 1; 101290075Sobrien 101390075Sobrien /* K_INCR_LINUM (lndif); */ 101490075Sobrien pcline.dst_b_pcline_command = DST_K_INCR_LINUM_L; 101590075Sobrien 101690075Sobrien totsize += write_debug_data1 (pcline.dst_b_pcline_command, 101790075Sobrien "line_num (INCR LINUM LONG)", 101890075Sobrien dosizeonly); 101990075Sobrien 102090075Sobrien sprintf (buff, "line_num (%d)", lndif); 102190075Sobrien totsize += write_debug_data4 (lndif, buff, dosizeonly); 102290075Sobrien } 102390075Sobrien else if (ln <= lastln) 102490075Sobrien { 102590075Sobrien /* K_SET_LINUM (ln-1); */ 102690075Sobrien pcline.dst_b_pcline_command = DST_K_SET_LINUM_L; 102790075Sobrien 102890075Sobrien totsize += write_debug_data1 (pcline.dst_b_pcline_command, 102990075Sobrien "line_num (SET LINUM LONG)", 103090075Sobrien dosizeonly); 103190075Sobrien 103290075Sobrien sprintf (buff, "line_num (%d)", ln - 1); 103390075Sobrien totsize += write_debug_data4 (ln - 1, buff, dosizeonly); 103490075Sobrien } 103590075Sobrien 103690075Sobrien pcline.dst_b_pcline_command = DST_K_DELTA_PC_L; 103790075Sobrien 103890075Sobrien totsize += write_debug_data1 (pcline.dst_b_pcline_command, 103990075Sobrien "line_num (DELTA PC LONG)", dosizeonly); 104090075Sobrien 104190075Sobrien ASM_GENERATE_INTERNAL_LABEL (label, LINE_CODE_LABEL, i); 104290075Sobrien totsize += write_debug_delta4 (label, lastlabel, "increment line_num", 104390075Sobrien dosizeonly); 104490075Sobrien 104590075Sobrien lastln = ln; 104690075Sobrien strcpy (lastlabel, label); 104790075Sobrien } 104890075Sobrien 104990075Sobrien return totsize; 105090075Sobrien} 105190075Sobrien 105290075Sobrien/* Output a source correlation for file FILEID using information saved in 105390075Sobrien FILE_INFO_ENTRY and return the size. Just return the size if DOSIZEONLY is 1054117395Skan nonzero. */ 105590075Sobrien 105690075Sobrienstatic int 1057132718Skanwrite_srccorr (int fileid, dst_file_info_entry file_info_entry, 1058132718Skan int dosizeonly) 105990075Sobrien{ 106090075Sobrien int src_command_size; 106190075Sobrien int linesleft = file_info_entry.max_line; 106290075Sobrien int linestart = file_info_entry.listing_line_start; 106390075Sobrien int flen = file_info_entry.flen; 106490075Sobrien int linestodo = 0; 106590075Sobrien DST_SOURCE_CORR src_header; 106690075Sobrien DST_SRC_COMMAND src_command; 106790075Sobrien DST_SRC_COMMAND src_command_sf; 106890075Sobrien DST_SRC_COMMAND src_command_sl; 106990075Sobrien DST_SRC_COMMAND src_command_sr; 107090075Sobrien DST_SRC_COMMAND src_command_dl; 107190075Sobrien DST_SRC_CMDTRLR src_cmdtrlr; 107290075Sobrien char buff[256]; 107390075Sobrien int totsize = 0; 107490075Sobrien 107590075Sobrien if (fileid == 1) 107690075Sobrien { 107790075Sobrien src_header.dst_a_source_corr_header.dst__header_length.dst_w_length 107890075Sobrien = DST_K_SOURCE_CORR_HEADER_SIZE + 1 - 1; 107990075Sobrien src_header.dst_a_source_corr_header.dst__header_type.dst_w_type 108090075Sobrien = DST_K_SOURCE; 108190075Sobrien src_command.dst_b_src_command = DST_K_SRC_FORMFEED; 108290075Sobrien 108390075Sobrien totsize += write_debug_header (&src_header.dst_a_source_corr_header, 108490075Sobrien "source corr", dosizeonly); 108590075Sobrien 108690075Sobrien totsize += write_debug_data1 (src_command.dst_b_src_command, 108790075Sobrien "source_corr (SRC FORMFEED)", 108890075Sobrien dosizeonly); 108990075Sobrien } 109090075Sobrien 109190075Sobrien src_command_size 109290075Sobrien = DST_K_SRC_COMMAND_SIZE + flen + DST_K_SRC_CMDTRLR_SIZE; 109390075Sobrien src_command.dst_b_src_command = DST_K_SRC_DECLFILE; 109490075Sobrien src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_length 109590075Sobrien = src_command_size - 2; 109690075Sobrien src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_flags = 0; 109790075Sobrien src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_fileid 109890075Sobrien = fileid; 109990075Sobrien src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt 110090075Sobrien = file_info_entry.cdt; 110190075Sobrien src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk 110290075Sobrien = file_info_entry.ebk; 110390075Sobrien src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_rms_ffb 110490075Sobrien = file_info_entry.ffb; 110590075Sobrien src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_rms_rfo 110690075Sobrien = file_info_entry.rfo; 110790075Sobrien src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename 110890075Sobrien = file_info_entry.flen; 110990075Sobrien 111090075Sobrien src_header.dst_a_source_corr_header.dst__header_length.dst_w_length 111190075Sobrien = DST_K_SOURCE_CORR_HEADER_SIZE + src_command_size - 1; 111290075Sobrien src_header.dst_a_source_corr_header.dst__header_type.dst_w_type 111390075Sobrien = DST_K_SOURCE; 111490075Sobrien 111590075Sobrien src_cmdtrlr.dst_b_src_df_libmodname = 0; 1116117395Skan 111790075Sobrien totsize += write_debug_header (&src_header.dst_a_source_corr_header, 111890075Sobrien "source corr", dosizeonly); 111990075Sobrien totsize += write_debug_data1 (src_command.dst_b_src_command, 112090075Sobrien "source_corr (DECL SRC FILE)", dosizeonly); 112190075Sobrien totsize += write_debug_data1 112290075Sobrien (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_length, 112390075Sobrien "source_corr (length)", dosizeonly); 112490075Sobrien 112590075Sobrien totsize += write_debug_data1 112690075Sobrien (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_flags, 112790075Sobrien "source_corr (flags)", dosizeonly); 112890075Sobrien 112990075Sobrien totsize += write_debug_data2 113090075Sobrien (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_fileid, 113190075Sobrien "source_corr (fileid)", dosizeonly); 113290075Sobrien 113390075Sobrien totsize += write_debug_data8 113490075Sobrien (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt, 113590075Sobrien "source_corr (creation date)", dosizeonly); 1136117395Skan 113790075Sobrien totsize += write_debug_data4 113890075Sobrien (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk, 113990075Sobrien "source_corr (EOF block number)", dosizeonly); 114090075Sobrien 114190075Sobrien totsize += write_debug_data2 114290075Sobrien (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_rms_ffb, 114390075Sobrien "source_corr (first free byte)", dosizeonly); 114490075Sobrien 114590075Sobrien totsize += write_debug_data1 114690075Sobrien (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_rms_rfo, 114790075Sobrien "source_corr (record and file organization)", dosizeonly); 114890075Sobrien 114990075Sobrien totsize += write_debug_data1 115090075Sobrien (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename, 115190075Sobrien "source_corr (filename length)", dosizeonly); 115290075Sobrien 115390075Sobrien totsize += write_debug_string (file_info_entry.file_name, 115490075Sobrien "source file name", dosizeonly); 115590075Sobrien totsize += write_debug_data1 (src_cmdtrlr.dst_b_src_df_libmodname, 115690075Sobrien "source_corr (libmodname)", dosizeonly); 115790075Sobrien 115890075Sobrien src_command_sf.dst_b_src_command = DST_K_SRC_SETFILE; 115990075Sobrien src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword = fileid; 116090075Sobrien 116190075Sobrien src_command_sr.dst_b_src_command = DST_K_SRC_SETREC_W; 116290075Sobrien src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword = 1; 116390075Sobrien 116490075Sobrien src_command_sl.dst_b_src_command = DST_K_SRC_SETLNUM_L; 116590075Sobrien src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong = linestart + 1; 116690075Sobrien 116790075Sobrien src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W; 116890075Sobrien 116990075Sobrien if (linesleft > 65534) 117090075Sobrien linesleft = linesleft - 65534, linestodo = 65534; 117190075Sobrien else 117290075Sobrien linestodo = linesleft, linesleft = 0; 117390075Sobrien 117490075Sobrien src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo; 117590075Sobrien 117690075Sobrien src_header.dst_a_source_corr_header.dst__header_length.dst_w_length 117790075Sobrien = DST_K_SOURCE_CORR_HEADER_SIZE + 3 + 3 + 5 + 3 - 1; 117890075Sobrien src_header.dst_a_source_corr_header.dst__header_type.dst_w_type 117990075Sobrien = DST_K_SOURCE; 118090075Sobrien 1181117395Skan if (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword) 1182117395Skan { 1183117395Skan totsize += write_debug_header (&src_header.dst_a_source_corr_header, 1184117395Skan "source corr", dosizeonly); 118590075Sobrien 1186117395Skan totsize += write_debug_data1 (src_command_sf.dst_b_src_command, 1187117395Skan "source_corr (src setfile)", dosizeonly); 118890075Sobrien 1189117395Skan totsize += write_debug_data2 1190117395Skan (src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword, 1191117395Skan "source_corr (fileid)", dosizeonly); 119290075Sobrien 1193117395Skan totsize += write_debug_data1 (src_command_sr.dst_b_src_command, 1194117395Skan "source_corr (setrec)", dosizeonly); 119590075Sobrien 1196117395Skan totsize += write_debug_data2 1197117395Skan (src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword, 1198117395Skan "source_corr (recnum)", dosizeonly); 119990075Sobrien 1200117395Skan totsize += write_debug_data1 (src_command_sl.dst_b_src_command, 1201117395Skan "source_corr (setlnum)", dosizeonly); 120290075Sobrien 1203117395Skan totsize += write_debug_data4 1204117395Skan (src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong, 1205117395Skan "source_corr (linenum)", dosizeonly); 120690075Sobrien 120790075Sobrien totsize += write_debug_data1 (src_command_dl.dst_b_src_command, 120890075Sobrien "source_corr (deflines)", dosizeonly); 1209117395Skan 121090075Sobrien sprintf (buff, "source_corr (%d)", 121190075Sobrien src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword); 121290075Sobrien totsize += write_debug_data2 121390075Sobrien (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword, 121490075Sobrien buff, dosizeonly); 1215117395Skan 1216117395Skan while (linesleft > 0) 1217117395Skan { 1218117395Skan src_header.dst_a_source_corr_header.dst__header_length.dst_w_length 1219117395Skan = DST_K_SOURCE_CORR_HEADER_SIZE + 3 - 1; 1220117395Skan src_header.dst_a_source_corr_header.dst__header_type.dst_w_type 1221117395Skan = DST_K_SOURCE; 1222117395Skan src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W; 1223117395Skan 1224117395Skan if (linesleft > 65534) 1225117395Skan linesleft = linesleft - 65534, linestodo = 65534; 1226117395Skan else 1227117395Skan linestodo = linesleft, linesleft = 0; 1228117395Skan 1229117395Skan src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo; 1230117395Skan 1231117395Skan totsize += write_debug_header (&src_header.dst_a_source_corr_header, 1232117395Skan "source corr", dosizeonly); 1233117395Skan totsize += write_debug_data1 (src_command_dl.dst_b_src_command, 1234117395Skan "source_corr (deflines)", dosizeonly); 1235117395Skan sprintf (buff, "source_corr (%d)", 1236117395Skan src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword); 1237117395Skan totsize += write_debug_data2 1238117395Skan (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword, 1239117395Skan buff, dosizeonly); 1240117395Skan } 124190075Sobrien } 124290075Sobrien 124390075Sobrien return totsize; 124490075Sobrien} 124590075Sobrien 124690075Sobrien/* Output all the source correlation entries and return the size. Just return 1247117395Skan the size if DOSIZEONLY is nonzero. */ 124890075Sobrien 124990075Sobrienstatic int 1250132718Skanwrite_srccorrs (int dosizeonly) 125190075Sobrien{ 125290075Sobrien unsigned int i; 125390075Sobrien int totsize = 0; 125490075Sobrien 125590075Sobrien for (i = 1; i < file_info_table_in_use; i++) 125690075Sobrien totsize += write_srccorr (i, file_info_table[i], dosizeonly); 125790075Sobrien 125890075Sobrien return totsize; 1259117395Skan} 126090075Sobrien 126190075Sobrien/* Output a marker (i.e. a label) for the beginning of a function, before 126290075Sobrien the prologue. */ 126390075Sobrien 126490075Sobrienstatic void 1265132718Skanvmsdbgout_begin_prologue (unsigned int line, const char *file) 126690075Sobrien{ 126790075Sobrien char label[MAX_ARTIFICIAL_LABEL_BYTES]; 126890075Sobrien 126990075Sobrien if (write_symbols == VMS_AND_DWARF2_DEBUG) 127090075Sobrien (*dwarf2_debug_hooks.begin_prologue) (line, file); 127190075Sobrien 127290075Sobrien if (debug_info_level > DINFO_LEVEL_NONE) 127390075Sobrien { 127490075Sobrien ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL, 1275117395Skan current_function_funcdef_no); 127690075Sobrien ASM_OUTPUT_LABEL (asm_out_file, label); 127790075Sobrien } 127890075Sobrien} 127990075Sobrien 128090075Sobrien/* Output a marker (i.e. a label) for the beginning of a function, after 128190075Sobrien the prologue. */ 128290075Sobrien 1283117395Skanstatic void 1284132718Skanvmsdbgout_end_prologue (unsigned int line, const char *file) 128590075Sobrien{ 128690075Sobrien char label[MAX_ARTIFICIAL_LABEL_BYTES]; 128790075Sobrien 1288117395Skan if (write_symbols == VMS_AND_DWARF2_DEBUG) 1289117395Skan (*dwarf2_debug_hooks.end_prologue) (line, file); 1290117395Skan 129190075Sobrien if (debug_info_level > DINFO_LEVEL_TERSE) 129290075Sobrien { 129390075Sobrien ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL, 1294117395Skan current_function_funcdef_no); 129590075Sobrien ASM_OUTPUT_LABEL (asm_out_file, label); 1296117395Skan 1297132718Skan /* VMS PCA expects every PC range to correlate to some line and file. */ 1298117395Skan vmsdbgout_source_line (line, file); 129990075Sobrien } 130090075Sobrien} 130190075Sobrien 1302117395Skan/* No output for VMS debug, but make obligatory call to Dwarf2 debug */ 1303117395Skan 1304117395Skanstatic void 1305132718Skanvmsdbgout_end_function (unsigned int line) 1306117395Skan{ 1307117395Skan if (write_symbols == VMS_AND_DWARF2_DEBUG) 1308117395Skan (*dwarf2_debug_hooks.end_function) (line); 1309117395Skan} 1310117395Skan 131190075Sobrien/* Output a marker (i.e. a label) for the absolute end of the generated code 131290075Sobrien for a function definition. This gets called *after* the epilogue code has 131390075Sobrien been generated. */ 131490075Sobrien 131590075Sobrienstatic void 1316132718Skanvmsdbgout_end_epilogue (unsigned int line, const char *file) 131790075Sobrien{ 131890075Sobrien char label[MAX_ARTIFICIAL_LABEL_BYTES]; 131990075Sobrien 132090075Sobrien if (write_symbols == VMS_AND_DWARF2_DEBUG) 1321117395Skan (*dwarf2_debug_hooks.end_epilogue) (line, file); 132290075Sobrien 132390075Sobrien if (debug_info_level > DINFO_LEVEL_NONE) 132490075Sobrien { 132590075Sobrien /* Output a label to mark the endpoint of the code generated for this 132690075Sobrien function. */ 132790075Sobrien ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL, 1328117395Skan current_function_funcdef_no); 132990075Sobrien ASM_OUTPUT_LABEL (asm_out_file, label); 1330117395Skan 1331132718Skan /* VMS PCA expects every PC range to correlate to some line and file. */ 1332117395Skan vmsdbgout_source_line (line, file); 133390075Sobrien } 133490075Sobrien} 133590075Sobrien 133690075Sobrien/* Output a marker (i.e. a label) for the beginning of the generated code for 133790075Sobrien a lexical block. */ 133890075Sobrien 133990075Sobrienstatic void 1340132718Skanvmsdbgout_begin_block (register unsigned line, register unsigned blocknum) 134190075Sobrien{ 134290075Sobrien if (write_symbols == VMS_AND_DWARF2_DEBUG) 134390075Sobrien (*dwarf2_debug_hooks.begin_block) (line, blocknum); 134490075Sobrien 134590075Sobrien if (debug_info_level > DINFO_LEVEL_TERSE) 1346169689Skan targetm.asm_out.internal_label (asm_out_file, BLOCK_BEGIN_LABEL, blocknum); 134790075Sobrien} 134890075Sobrien 134990075Sobrien/* Output a marker (i.e. a label) for the end of the generated code for a 135090075Sobrien lexical block. */ 135190075Sobrien 135290075Sobrienstatic void 1353132718Skanvmsdbgout_end_block (register unsigned line, register unsigned blocknum) 135490075Sobrien{ 135590075Sobrien if (write_symbols == VMS_AND_DWARF2_DEBUG) 135690075Sobrien (*dwarf2_debug_hooks.end_block) (line, blocknum); 135790075Sobrien 135890075Sobrien if (debug_info_level > DINFO_LEVEL_TERSE) 1359169689Skan targetm.asm_out.internal_label (asm_out_file, BLOCK_END_LABEL, blocknum); 136090075Sobrien} 136190075Sobrien 136290075Sobrien/* Not implemented in VMS Debug. */ 136390075Sobrien 136490075Sobrienstatic bool 1365132718Skanvmsdbgout_ignore_block (tree block) 136690075Sobrien{ 136790075Sobrien bool retval = 0; 136890075Sobrien 136990075Sobrien if (write_symbols == VMS_AND_DWARF2_DEBUG) 137090075Sobrien retval = (*dwarf2_debug_hooks.ignore_block) (block); 137190075Sobrien 137290075Sobrien return retval; 137390075Sobrien} 137490075Sobrien 137590075Sobrien/* Add an entry for function DECL into the func_table. */ 137690075Sobrien 137790075Sobrienstatic void 1378132718Skanvmsdbgout_begin_function (tree decl) 137990075Sobrien{ 138090075Sobrien const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0); 1381169689Skan vms_func_ref fde; 138290075Sobrien 138390075Sobrien if (write_symbols == VMS_AND_DWARF2_DEBUG) 138490075Sobrien (*dwarf2_debug_hooks.begin_function) (decl); 138590075Sobrien 138690075Sobrien if (func_table_in_use == func_table_allocated) 138790075Sobrien { 138890075Sobrien func_table_allocated += FUNC_TABLE_INCREMENT; 1389169689Skan func_table 1390169689Skan = (vms_func_ref) xrealloc (func_table, 1391169689Skan func_table_allocated * sizeof (vms_func_node)); 139290075Sobrien } 139390075Sobrien 139490075Sobrien /* Add the new entry to the end of the function name table. */ 1395169689Skan fde = &func_table[func_table_in_use++]; 1396169689Skan fde->vms_func_name = xstrdup (name); 1397169689Skan fde->funcdef_number = current_function_funcdef_no; 1398169689Skan 139990075Sobrien} 140090075Sobrien 140190075Sobrienstatic char fullname_buff [4096]; 140290075Sobrien 140390075Sobrien/* Return the full file specification for FILENAME. The specification must be 140490075Sobrien in VMS syntax in order to be processed by VMS Debug. */ 140590075Sobrien 140690075Sobrienstatic char * 1407132718Skanfull_name (const char *filename) 140890075Sobrien{ 140990075Sobrien#ifdef VMS 141090075Sobrien FILE *fp = fopen (filename, "r"); 141190075Sobrien 141290075Sobrien fgetname (fp, fullname_buff, 1); 141390075Sobrien fclose (fp); 141490075Sobrien#else 141590075Sobrien getcwd (fullname_buff, sizeof (fullname_buff)); 141690075Sobrien 141790075Sobrien strcat (fullname_buff, "/"); 141890075Sobrien strcat (fullname_buff, filename); 141990075Sobrien 142090075Sobrien /* ??? Insert hairy code here to translate Unix style file specification 142190075Sobrien to VMS style. */ 142290075Sobrien#endif 142390075Sobrien 142490075Sobrien return fullname_buff; 142590075Sobrien} 142690075Sobrien 142790075Sobrien/* Lookup a filename (in the list of filenames that we know about here in 142890075Sobrien vmsdbgout.c) and return its "index". The index of each (known) filename is 142990075Sobrien just a unique number which is associated with only that one filename. We 143090075Sobrien need such numbers for the sake of generating labels and references 143190075Sobrien to those files numbers. If the filename given as an argument is not 143290075Sobrien found in our current list, add it to the list and assign it the next 143390075Sobrien available unique index number. In order to speed up searches, we remember 143490075Sobrien the index of the filename was looked up last. This handles the majority of 143590075Sobrien all searches. */ 143690075Sobrien 143790075Sobrienstatic unsigned int 1438132718Skanlookup_filename (const char *file_name) 143990075Sobrien{ 144090075Sobrien static unsigned int last_file_lookup_index = 0; 144190075Sobrien register char *fn; 144290075Sobrien register unsigned i; 144390075Sobrien char *fnam; 144490075Sobrien long long cdt; 144590075Sobrien long ebk; 144690075Sobrien short ffb; 144790075Sobrien char rfo; 144890075Sobrien char flen; 144990075Sobrien struct stat statbuf; 145090075Sobrien 145190075Sobrien if (stat (file_name, &statbuf) == 0) 145290075Sobrien { 145396263Sobrien long gmtoff; 145490075Sobrien#ifdef VMS 145596263Sobrien struct tm *ts; 145696263Sobrien 1457132718Skan /* Adjust for GMT. */ 145896263Sobrien ts = (struct tm *) localtime (&statbuf.st_ctime); 145996263Sobrien gmtoff = ts->tm_gmtoff; 146096263Sobrien 1461132718Skan /* VMS has multiple file format types. */ 146290075Sobrien rfo = statbuf.st_fab_rfm; 146390075Sobrien#else 146496263Sobrien /* Is GMT adjustment an issue with a cross-compiler? */ 146596263Sobrien gmtoff = 0; 146696263Sobrien 1467132718Skan /* Assume stream LF type file. */ 146890075Sobrien rfo = 2; 146990075Sobrien#endif 147096263Sobrien cdt = 10000000 * (statbuf.st_ctime + gmtoff + vms_epoch_offset); 147196263Sobrien ebk = statbuf.st_size / 512 + 1; 147296263Sobrien ffb = statbuf.st_size - ((statbuf.st_size / 512) * 512); 147390075Sobrien fnam = full_name (file_name); 147490075Sobrien flen = strlen (fnam); 147590075Sobrien } 147690075Sobrien else 147790075Sobrien { 147890075Sobrien cdt = 0; 147990075Sobrien ebk = 0; 148090075Sobrien ffb = 0; 148190075Sobrien rfo = 0; 148290075Sobrien fnam = (char *) ""; 148390075Sobrien flen = 0; 148490075Sobrien } 148590075Sobrien 148690075Sobrien /* Check to see if the file name that was searched on the previous call 148790075Sobrien matches this file name. If so, return the index. */ 148890075Sobrien if (last_file_lookup_index != 0) 148990075Sobrien { 149090075Sobrien fn = file_info_table[last_file_lookup_index].file_name; 149190075Sobrien if (strcmp (fnam, fn) == 0) 149290075Sobrien return last_file_lookup_index; 149390075Sobrien } 149490075Sobrien 149590075Sobrien /* Didn't match the previous lookup, search the table */ 149690075Sobrien for (i = 1; i < file_info_table_in_use; ++i) 149790075Sobrien { 149890075Sobrien fn = file_info_table[i].file_name; 149990075Sobrien if (strcmp (fnam, fn) == 0) 150090075Sobrien { 150190075Sobrien last_file_lookup_index = i; 150290075Sobrien return i; 150390075Sobrien } 150490075Sobrien } 150590075Sobrien 1506117395Skan /* Prepare to add a new table entry by making sure there is enough space in 150790075Sobrien the table to do so. If not, expand the current table. */ 150890075Sobrien if (file_info_table_in_use == file_info_table_allocated) 150990075Sobrien { 151090075Sobrien 151190075Sobrien file_info_table_allocated += FILE_TABLE_INCREMENT; 1512132718Skan file_info_table = xrealloc (file_info_table, 1513132718Skan (file_info_table_allocated 1514132718Skan * sizeof (dst_file_info_entry))); 151590075Sobrien } 151690075Sobrien 151790075Sobrien /* Add the new entry to the end of the filename table. */ 151890075Sobrien file_info_table[file_info_table_in_use].file_name = xstrdup (fnam); 151990075Sobrien file_info_table[file_info_table_in_use].max_line = 0; 152090075Sobrien file_info_table[file_info_table_in_use].cdt = cdt; 152190075Sobrien file_info_table[file_info_table_in_use].ebk = ebk; 152290075Sobrien file_info_table[file_info_table_in_use].ffb = ffb; 152390075Sobrien file_info_table[file_info_table_in_use].rfo = rfo; 152490075Sobrien file_info_table[file_info_table_in_use].flen = flen; 152590075Sobrien 152690075Sobrien last_file_lookup_index = file_info_table_in_use++; 152790075Sobrien return last_file_lookup_index; 152890075Sobrien} 152990075Sobrien 153090075Sobrien/* Output a label to mark the beginning of a source code line entry 153190075Sobrien and record information relating to this source line, in 153290075Sobrien 'line_info_table' for later output of the .debug_line section. */ 153390075Sobrien 153490075Sobrienstatic void 1535132718Skanvmsdbgout_source_line (register unsigned line, register const char *filename) 153690075Sobrien{ 153790075Sobrien if (write_symbols == VMS_AND_DWARF2_DEBUG) 153890075Sobrien (*dwarf2_debug_hooks.source_line) (line, filename); 153990075Sobrien 154090075Sobrien if (debug_info_level >= DINFO_LEVEL_TERSE) 154190075Sobrien { 154290075Sobrien dst_line_info_ref line_info; 154390075Sobrien 1544169689Skan targetm.asm_out.internal_label (asm_out_file, LINE_CODE_LABEL, 1545169689Skan line_info_table_in_use); 154690075Sobrien 154790075Sobrien /* Expand the line info table if necessary. */ 154890075Sobrien if (line_info_table_in_use == line_info_table_allocated) 154990075Sobrien { 155090075Sobrien line_info_table_allocated += LINE_INFO_TABLE_INCREMENT; 1551132718Skan line_info_table = xrealloc (line_info_table, 1552132718Skan (line_info_table_allocated 1553132718Skan * sizeof (dst_line_info_entry))); 1554117395Skan } 155590075Sobrien 155690075Sobrien /* Add the new entry at the end of the line_info_table. */ 155790075Sobrien line_info = &line_info_table[line_info_table_in_use++]; 155890075Sobrien line_info->dst_file_num = lookup_filename (filename); 155990075Sobrien line_info->dst_line_num = line; 156090075Sobrien if (line > file_info_table[line_info->dst_file_num].max_line) 156190075Sobrien file_info_table[line_info->dst_file_num].max_line = line; 156290075Sobrien } 156390075Sobrien} 156490075Sobrien 156590075Sobrien/* Record the beginning of a new source file, for later output. 156690075Sobrien At present, unimplemented. */ 156790075Sobrien 156890075Sobrienstatic void 1569132718Skanvmsdbgout_start_source_file (unsigned int lineno, const char *filename) 157090075Sobrien{ 157190075Sobrien if (write_symbols == VMS_AND_DWARF2_DEBUG) 157290075Sobrien (*dwarf2_debug_hooks.start_source_file) (lineno, filename); 157390075Sobrien} 157490075Sobrien 157590075Sobrien/* Record the end of a source file, for later output. 157690075Sobrien At present, unimplemented. */ 157790075Sobrien 157890075Sobrienstatic void 1579132718Skanvmsdbgout_end_source_file (unsigned int lineno ATTRIBUTE_UNUSED) 158090075Sobrien{ 158190075Sobrien if (write_symbols == VMS_AND_DWARF2_DEBUG) 158290075Sobrien (*dwarf2_debug_hooks.end_source_file) (lineno); 158390075Sobrien} 158490075Sobrien 158590075Sobrien/* Set up for Debug output at the start of compilation. */ 158690075Sobrien 158790075Sobrienstatic void 1588132718Skanvmsdbgout_init (const char *main_input_filename) 158990075Sobrien{ 159090075Sobrien const char *language_string = lang_hooks.name; 159190075Sobrien 159290075Sobrien if (write_symbols == VMS_AND_DWARF2_DEBUG) 159390075Sobrien (*dwarf2_debug_hooks.init) (main_input_filename); 159490075Sobrien 159590075Sobrien if (debug_info_level == DINFO_LEVEL_NONE) 159690075Sobrien return; 159790075Sobrien 159890075Sobrien /* Remember the name of the primary input file. */ 159990075Sobrien primary_filename = main_input_filename; 160090075Sobrien 160190075Sobrien /* Allocate the initial hunk of the file_info_table. */ 160290075Sobrien file_info_table 1603132718Skan = xcalloc (FILE_TABLE_INCREMENT, sizeof (dst_file_info_entry)); 160490075Sobrien file_info_table_allocated = FILE_TABLE_INCREMENT; 160590075Sobrien 160690075Sobrien /* Skip the first entry - file numbers begin at 1 */ 160790075Sobrien file_info_table_in_use = 1; 160890075Sobrien 1609169689Skan func_table = (vms_func_ref) xcalloc (FUNC_TABLE_INCREMENT, sizeof (vms_func_node)); 161090075Sobrien func_table_allocated = FUNC_TABLE_INCREMENT; 161190075Sobrien func_table_in_use = 1; 161290075Sobrien 161390075Sobrien /* Allocate the initial hunk of the line_info_table. */ 161490075Sobrien line_info_table 1615132718Skan = xcalloc (LINE_INFO_TABLE_INCREMENT, sizeof (dst_line_info_entry)); 161690075Sobrien line_info_table_allocated = LINE_INFO_TABLE_INCREMENT; 161790075Sobrien /* zero-th entry is allocated, but unused */ 161890075Sobrien line_info_table_in_use = 1; 161990075Sobrien 162090075Sobrien lookup_filename (primary_filename); 162190075Sobrien 162290075Sobrien if (!strcmp (language_string, "GNU C")) 162390075Sobrien module_language = DST_K_C; 162490075Sobrien else if (!strcmp (language_string, "GNU C++")) 162590075Sobrien module_language = DST_K_CXX; 162690075Sobrien else if (!strcmp (language_string, "GNU Ada")) 162790075Sobrien module_language = DST_K_ADA; 162890075Sobrien else if (!strcmp (language_string, "GNU F77")) 162990075Sobrien module_language = DST_K_FORTRAN; 163090075Sobrien else 163190075Sobrien module_language = DST_K_UNKNOWN; 163290075Sobrien 1633117395Skan module_producer = concat (language_string, " ", version_string, NULL); 163490075Sobrien 163590075Sobrien ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0); 163690075Sobrien 163790075Sobrien} 163890075Sobrien 163990075Sobrien/* Not implemented in VMS Debug. */ 164090075Sobrien 164190075Sobrienstatic void 1642132718Skanvmsdbgout_define (unsigned int lineno, const char *buffer) 164390075Sobrien{ 164490075Sobrien if (write_symbols == VMS_AND_DWARF2_DEBUG) 164590075Sobrien (*dwarf2_debug_hooks.define) (lineno, buffer); 164690075Sobrien} 164790075Sobrien 164890075Sobrien/* Not implemented in VMS Debug. */ 164990075Sobrien 165090075Sobrienstatic void 1651132718Skanvmsdbgout_undef (unsigned int lineno, const char *buffer) 165290075Sobrien{ 165390075Sobrien if (write_symbols == VMS_AND_DWARF2_DEBUG) 165490075Sobrien (*dwarf2_debug_hooks.undef) (lineno, buffer); 165590075Sobrien} 165690075Sobrien 165790075Sobrien/* Not implemented in VMS Debug. */ 165890075Sobrien 165990075Sobrienstatic void 1660132718Skanvmsdbgout_decl (tree decl) 166190075Sobrien{ 166290075Sobrien if (write_symbols == VMS_AND_DWARF2_DEBUG) 166390075Sobrien (*dwarf2_debug_hooks.function_decl) (decl); 166490075Sobrien} 166590075Sobrien 166690075Sobrien/* Not implemented in VMS Debug. */ 166790075Sobrien 166890075Sobrienstatic void 1669132718Skanvmsdbgout_global_decl (tree decl) 167090075Sobrien{ 167190075Sobrien if (write_symbols == VMS_AND_DWARF2_DEBUG) 167290075Sobrien (*dwarf2_debug_hooks.global_decl) (decl); 167390075Sobrien} 167490075Sobrien 167590075Sobrien/* Not implemented in VMS Debug. */ 167690075Sobrien 167790075Sobrienstatic void 1678132718Skanvmsdbgout_abstract_function (tree decl) 167990075Sobrien{ 168090075Sobrien if (write_symbols == VMS_AND_DWARF2_DEBUG) 168190075Sobrien (*dwarf2_debug_hooks.outlining_inline_function) (decl); 168290075Sobrien} 168390075Sobrien 168490075Sobrien/* Output stuff that Debug requires at the end of every file and generate the 168590075Sobrien VMS Debug debugging info. */ 168690075Sobrien 168790075Sobrienstatic void 1688132718Skanvmsdbgout_finish (const char *main_input_filename ATTRIBUTE_UNUSED) 168990075Sobrien{ 169090075Sobrien unsigned int i; 169190075Sobrien int totsize; 169290075Sobrien 169390075Sobrien if (write_symbols == VMS_AND_DWARF2_DEBUG) 1694132718Skan (*dwarf2_debug_hooks.finish) (main_input_filename); 169590075Sobrien 169690075Sobrien if (debug_info_level == DINFO_LEVEL_NONE) 169790075Sobrien return; 169890075Sobrien 169990075Sobrien /* Output a terminator label for the .text section. */ 1700169689Skan switch_to_section (text_section); 1701169689Skan targetm.asm_out.internal_label (asm_out_file, TEXT_END_LABEL, 0); 170290075Sobrien 170390075Sobrien /* Output debugging information. 170490075Sobrien Warning! Do not change the name of the .vmsdebug section without 170590075Sobrien changing it in the assembler also. */ 1706169689Skan switch_to_section (get_named_section (NULL, ".vmsdebug", 0)); 170790075Sobrien ASM_OUTPUT_ALIGN (asm_out_file, 0); 170890075Sobrien 170990075Sobrien totsize = write_modbeg (1); 171090075Sobrien for (i = 1; i < func_table_in_use; i++) 171190075Sobrien { 171290075Sobrien totsize += write_rtnbeg (i, 1); 171390075Sobrien totsize += write_rtnend (i, 1); 171490075Sobrien } 171590075Sobrien totsize += write_pclines (1); 171690075Sobrien 171790075Sobrien write_modbeg (0); 171890075Sobrien for (i = 1; i < func_table_in_use; i++) 171990075Sobrien { 172090075Sobrien write_rtnbeg (i, 0); 172190075Sobrien write_rtnend (i, 0); 172290075Sobrien } 172390075Sobrien write_pclines (0); 172490075Sobrien 172590075Sobrien if (debug_info_level > DINFO_LEVEL_TERSE) 172690075Sobrien { 172790075Sobrien totsize = write_srccorrs (1); 172890075Sobrien write_srccorrs (0); 172990075Sobrien } 173090075Sobrien 173190075Sobrien totsize = write_modend (1); 173290075Sobrien write_modend (0); 173390075Sobrien} 173490075Sobrien#endif /* VMS_DEBUGGING_INFO */ 1735