#include "config.h"
#include "system.h"
#include "tree.h"
#include "rtl.h"
#include "flags.h"
#include "toplev.h"
#include "output.h"
#ifdef XCOFF_DEBUGGING_INFO
#include <dbxstclass.h>
#include "xcoffout.h"
#include "dbxout.h"
#if defined (USG) || !defined (HAVE_STAB_H)
#include "gstab.h"
#else
#include <stab.h>
#ifndef N_CATCH
#define N_CATCH 0x54
#endif
#endif
static int xcoff_begin_function_line = -1;
static int xcoff_inlining = 0;
char *xcoff_current_include_file;
static char *xcoff_current_function_file;
char *xcoff_bss_section_name;
char *xcoff_private_data_section_name;
char *xcoff_read_only_section_name;
char *xcoff_lastfile;
#define ABS_OR_RELATIVE_LINENO(LINENO) \
((xcoff_inlining) ? (LINENO) : (LINENO) - xcoff_begin_function_line)
#define ASM_OUTPUT_SOURCE_LINE(FILE,LINENUM) \
do { \
if (xcoff_begin_function_line >= 0) \
fprintf (FILE, "\t.line\t%d\n", ABS_OR_RELATIVE_LINENO (LINENUM)); \
} while (0)
#define ASM_OUTPUT_LFB(FILE,LINENUM) \
{ \
if (xcoff_begin_function_line == -1) \
{ \
xcoff_begin_function_line = (LINENUM) - 1;\
fprintf (FILE, "\t.bf\t%d\n", (LINENUM)); \
} \
xcoff_current_function_file \
= (xcoff_current_include_file \
? xcoff_current_include_file : main_input_filename); \
}
#define ASM_OUTPUT_LFE(FILE,LINENUM) \
do { \
fprintf (FILE, "\t.ef\t%d\n", (LINENUM)); \
xcoff_begin_function_line = -1; \
} while (0)
#define ASM_OUTPUT_LBB(FILE,LINENUM,BLOCKNUM) \
fprintf (FILE, "\t.bb\t%d\n", ABS_OR_RELATIVE_LINENO (LINENUM))
#define ASM_OUTPUT_LBE(FILE,LINENUM,BLOCKNUM) \
fprintf (FILE, "\t.eb\t%d\n", ABS_OR_RELATIVE_LINENO (LINENUM))
static void assign_type_number PROTO((tree, char *, int));
static void xcoffout_block PROTO((tree, int, tree));
static void
assign_type_number (syms, name, number)
tree syms;
char *name;
int number;
{
tree decl;
for (decl = syms; decl; decl = TREE_CHAIN (decl))
if (DECL_NAME (decl)
&& strcmp (IDENTIFIER_POINTER (DECL_NAME (decl)), name) == 0)
{
TREE_ASM_WRITTEN (decl) = 1;
TYPE_SYMTAB_ADDRESS (TREE_TYPE (decl)) = number;
}
}
void
xcoff_output_standard_types (syms)
tree syms;
{
assign_type_number (syms, "int", -1);
assign_type_number (syms, "char", -2);
assign_type_number (syms, "short int", -3);
assign_type_number (syms, "long int", (TARGET_64BIT ? -31 : -4));
assign_type_number (syms, "unsigned char", -5);
assign_type_number (syms, "signed char", -6);
assign_type_number (syms, "short unsigned int", -7);
assign_type_number (syms, "unsigned int", -8);
assign_type_number (syms, "long unsigned int", (TARGET_64BIT ? -32 : -10));
assign_type_number (syms, "void", -11);
assign_type_number (syms, "float", -12);
assign_type_number (syms, "double", -13);
assign_type_number (syms, "long double", -14);
assign_type_number (syms, "wchar", -30);
assign_type_number (syms, "long long int", -31);
assign_type_number (syms, "long long unsigned int", -32);
}
#define UNKNOWN_STAB(STR) \
do { \
error ("Unknown stab %s: : 0x%x\n", STR, stab); \
fflush (stderr); \
} while (0)
int
stab_to_sclass (stab)
int stab;
{
switch (stab)
{
case N_GSYM:
return C_GSYM;
case N_FNAME:
UNKNOWN_STAB ("N_FNAME");
abort();
case N_FUN:
return C_FUN;
case N_STSYM:
case N_LCSYM:
return C_STSYM;
#ifdef N_MAIN
case N_MAIN:
UNKNOWN_STAB ("N_MAIN");
abort ();
#endif
case N_RSYM:
return C_RSYM;
case N_SSYM:
UNKNOWN_STAB ("N_SSYM");
abort ();
case N_RPSYM:
return C_RPSYM;
case N_PSYM:
return C_PSYM;
case N_LSYM:
return C_LSYM;
case N_DECL:
return C_DECL;
case N_ENTRY:
return C_ENTRY;
case N_SO:
UNKNOWN_STAB ("N_SO");
abort ();
case N_SOL:
UNKNOWN_STAB ("N_SOL");
abort ();
case N_SLINE:
UNKNOWN_STAB ("N_SLINE");
abort ();
#ifdef N_DSLINE
case N_DSLINE:
UNKNOWN_STAB ("N_DSLINE");
abort ();
#endif
#ifdef N_BSLINE
case N_BSLINE:
UNKNOWN_STAB ("N_BSLINE");
abort ();
#endif
#if 0
case N_BROWS:
UNKNOWN_STAB ("N_BROWS");
abort ();
#endif
#ifdef N_BINCL
case N_BINCL:
UNKNOWN_STAB ("N_BINCL");
abort ();
#endif
#ifdef N_EINCL
case N_EINCL:
UNKNOWN_STAB ("N_EINCL");
abort ();
#endif
#ifdef N_EXCL
case N_EXCL:
UNKNOWN_STAB ("N_EXCL");
abort ();
#endif
case N_LBRAC:
UNKNOWN_STAB ("N_LBRAC");
abort ();
case N_RBRAC:
UNKNOWN_STAB ("N_RBRAC");
abort ();
case N_BCOMM:
return C_BCOMM;
case N_ECOMM:
return C_ECOMM;
case N_ECOML:
return C_ECOML;
case N_LENG:
UNKNOWN_STAB ("N_LENG");
abort ();
case N_PC:
UNKNOWN_STAB ("N_PC");
abort ();
#ifdef N_M2C
case N_M2C:
UNKNOWN_STAB ("N_M2C");
abort ();
#endif
#ifdef N_SCOPE
case N_SCOPE:
UNKNOWN_STAB ("N_SCOPE");
abort ();
#endif
case N_CATCH:
UNKNOWN_STAB ("N_CATCH");
abort ();
default:
UNKNOWN_STAB ("default");
abort ();
}
}
void
xcoffout_source_file (file, filename, inline_p)
FILE *file;
char *filename;
int inline_p;
{
if (filename
&& (xcoff_lastfile == 0 || strcmp (filename, xcoff_lastfile)
|| (inline_p && ! xcoff_inlining)
|| (! inline_p && xcoff_inlining)))
{
if (xcoff_current_include_file)
{
fprintf (file, "\t.ei\t");
output_quoted_string (file, xcoff_current_include_file);
fprintf (file, "\n");
xcoff_current_include_file = NULL;
}
xcoff_inlining=inline_p;
if (strcmp (main_input_filename, filename) || inline_p)
{
fprintf (file, "\t.bi\t");
output_quoted_string (file, filename);
fprintf (file, "\n");
xcoff_current_include_file = filename;
}
xcoff_lastfile = filename;
}
}
void
xcoffout_source_line (file, filename, note)
FILE *file;
char *filename;
rtx note;
{
xcoffout_source_file (file, filename, RTX_INTEGRATED_P (note));
ASM_OUTPUT_SOURCE_LINE (file, NOTE_LINE_NUMBER (note));
}
static int do_block = 0;
static int next_block_number;
static void
xcoffout_block (block, depth, args)
register tree block;
int depth;
tree args;
{
while (block)
{
if (TREE_USED (block))
{
if (next_block_number == do_block)
{
if (debug_info_level != DINFO_LEVEL_TERSE || depth == 0)
dbxout_syms (BLOCK_VARS (block));
if (args)
dbxout_reg_parms (args);
return;
}
else if (next_block_number >= do_block)
return;
next_block_number++;
xcoffout_block (BLOCK_SUBBLOCKS (block), depth + 1, NULL_TREE);
}
block = BLOCK_CHAIN (block);
}
}
void
xcoffout_begin_block (file, line, n)
FILE *file;
int line;
int n;
{
tree decl = current_function_decl;
if (n != 1)
ASM_OUTPUT_LBB (file, line, n);
do_block = n;
next_block_number = 0;
xcoffout_block (DECL_INITIAL (decl), 0, DECL_ARGUMENTS (decl));
}
void
xcoffout_end_block (file, line, n)
FILE *file;
int line;
int n;
{
if (n != 1)
ASM_OUTPUT_LBE (file, line, n);
}
void
xcoffout_declare_function (file, decl, name)
FILE *file;
tree decl;
char *name;
{
char *n = name;
int i;
if (*n == '*')
n++;
else
for (i = 0; name[i]; ++i)
{
if (name[i] == '[')
{
n = (char *) alloca (i + 1);
strncpy (n, name, i);
n[i] = '\0';
break;
}
}
xcoffout_source_file (file, DECL_SOURCE_FILE (decl), 0);
dbxout_symbol (decl, 0);
fprintf (file, "\t.function .%s,.%s,16,044,FE..%s-.%s\n", n, n, n, n);
}
void
xcoffout_begin_function (file, last_linenum)
FILE *file;
int last_linenum;
{
ASM_OUTPUT_LFB (file, last_linenum);
dbxout_parms (DECL_ARGUMENTS (current_function_decl));
do_block = 0;
next_block_number = 0;
xcoffout_block (DECL_INITIAL (current_function_decl), 0,
DECL_ARGUMENTS (current_function_decl));
ASM_OUTPUT_SOURCE_LINE (file, last_linenum);
}
void
xcoffout_end_function (file, last_linenum)
FILE *file;
int last_linenum;
{
ASM_OUTPUT_LFE (file, last_linenum);
}
void
xcoffout_end_epilogue (file)
FILE *file;
{
char *fname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
if (*fname == '*')
++fname;
fprintf (file, "FE..");
ASM_OUTPUT_LABEL (file, fname);
}
#endif