#include "config.h"
#include "system.h"
#include "tree.h"
#include "rtl.h"
#include "flags.h"
#include "toplev.h"
#include "output.h"
#include "ggc.h"
#include "target.h"
#ifdef XCOFF_DEBUGGING_INFO
#include "dbxstclass.h"
#include "xcoffout.h"
#include "dbxout.h"
#include "gstab.h"
static int xcoff_begin_function_line = -1;
static int xcoff_inlining = 0;
const char *xcoff_current_include_file;
static const char *xcoff_current_function_file;
char *xcoff_bss_section_name;
char *xcoff_private_data_section_name;
char *xcoff_read_only_section_name;
const 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 PARAMS ((tree, const char *, int));
static void xcoffout_block PARAMS ((tree, int, tree));
static void xcoffout_source_file PARAMS ((FILE *, const char *, int));
static void
assign_type_number (syms, name, number)
tree syms;
const 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) \
internal_error ("no sclass for %s stab (0x%x)\n", STR, stab)
int
stab_to_sclass (stab)
int stab;
{
switch (stab)
{
case N_GSYM:
return C_GSYM;
case N_FNAME:
UNKNOWN_STAB ("N_FNAME");
case N_FUN:
return C_FUN;
case N_STSYM:
case N_LCSYM:
return C_STSYM;
case N_MAIN:
UNKNOWN_STAB ("N_MAIN");
case N_RSYM:
return C_RSYM;
case N_SSYM:
UNKNOWN_STAB ("N_SSYM");
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");
case N_SOL:
UNKNOWN_STAB ("N_SOL");
case N_SLINE:
UNKNOWN_STAB ("N_SLINE");
case N_DSLINE:
UNKNOWN_STAB ("N_DSLINE");
case N_BSLINE:
UNKNOWN_STAB ("N_BSLINE");
case N_BINCL:
UNKNOWN_STAB ("N_BINCL");
case N_EINCL:
UNKNOWN_STAB ("N_EINCL");
case N_EXCL:
UNKNOWN_STAB ("N_EXCL");
case N_LBRAC:
UNKNOWN_STAB ("N_LBRAC");
case N_RBRAC:
UNKNOWN_STAB ("N_RBRAC");
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");
case N_PC:
UNKNOWN_STAB ("N_PC");
case N_M2C:
UNKNOWN_STAB ("N_M2C");
case N_SCOPE:
UNKNOWN_STAB ("N_SCOPE");
case N_CATCH:
UNKNOWN_STAB ("N_CATCH");
case N_OPT:
UNKNOWN_STAB ("N_OPT");
default:
UNKNOWN_STAB ("?");
}
}
static void
xcoffout_source_file (file, filename, inline_p)
FILE *file;
const 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 (line, filename)
unsigned int line;
const char *filename;
{
bool inline_p = (strcmp (xcoff_current_function_file, filename) != 0
|| (int) line < xcoff_begin_function_line);
xcoffout_source_file (asm_out_file, filename, inline_p);
ASM_OUTPUT_SOURCE_LINE (asm_out_file, line);
}
static int do_block = 0;
static void
xcoffout_block (block, depth, args)
tree block;
int depth;
tree args;
{
while (block)
{
if (TREE_USED (block))
{
if (BLOCK_NUMBER (block) == 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 (BLOCK_NUMBER (block) >= do_block)
return;
xcoffout_block (BLOCK_SUBBLOCKS (block), depth + 1, NULL_TREE);
}
block = BLOCK_CHAIN (block);
}
}
void
xcoffout_begin_block (line, n)
unsigned int line;
unsigned int n;
{
tree decl = current_function_decl;
if (n != 1)
ASM_OUTPUT_LBB (asm_out_file, line, n);
do_block = n;
xcoffout_block (DECL_INITIAL (decl), 0, DECL_ARGUMENTS (decl));
}
void
xcoffout_end_block (line, n)
unsigned int line;
unsigned int n;
{
if (n != 1)
ASM_OUTPUT_LBE (asm_out_file, line, n);
}
void
xcoffout_declare_function (file, decl, name)
FILE *file;
tree decl;
const char *name;
{
int i;
if (*name == '*')
name++;
else
for (i = 0; name[i]; ++i)
{
if (name[i] == '[')
{
char *n = (char *) alloca (i + 1);
strncpy (n, name, i);
n[i] = '\0';
name = n;
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",
name, name, name, name);
}
void
xcoffout_begin_prologue (line, file)
unsigned int line;
const char *file ATTRIBUTE_UNUSED;
{
ASM_OUTPUT_LFB (asm_out_file, line);
dbxout_parms (DECL_ARGUMENTS (current_function_decl));
do_block = BLOCK_NUMBER (DECL_INITIAL (current_function_decl));
xcoffout_block (DECL_INITIAL (current_function_decl), 0,
DECL_ARGUMENTS (current_function_decl));
ASM_OUTPUT_SOURCE_LINE (asm_out_file, line);
}
void
xcoffout_end_function (last_linenum)
unsigned int last_linenum;
{
ASM_OUTPUT_LFE (asm_out_file, last_linenum);
}
void
xcoffout_end_epilogue (line, file)
unsigned int line ATTRIBUTE_UNUSED;
const char *file ATTRIBUTE_UNUSED;
{
const char *fname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
if (*fname == '*')
++fname;
fprintf (asm_out_file, "FE..");
ASM_OUTPUT_LABEL (asm_out_file, fname);
}
#endif