#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.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 "xcoff.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_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 xcoffout_block (tree, int, tree);
static void xcoffout_source_file (FILE *, const char *, int);
struct xcoff_type_number
{
const char *name;
int number;
};
static const struct xcoff_type_number xcoff_type_numbers[] = {
{ "int", -1 },
{ "char", -2 },
{ "short int", -3 },
{ "long int", -4 },
{ "unsigned char", -5 },
{ "signed char", -6 },
{ "short unsigned int", -7 },
{ "unsigned int", -8 },
{ "long unsigned int", -10 },
{ "void", -11 },
{ "float", -12 },
{ "double", -13 },
{ "long double", -14 },
{ "wchar", -30 },
{ "long long int", -31 },
{ "long long unsigned int", -32 },
};
int
xcoff_assign_fundamental_type_number (tree decl)
{
const char *name;
size_t i;
if (DECL_NAME (decl) == 0 || ! DECL_IS_BUILTIN (decl))
return 0;
name = IDENTIFIER_POINTER (DECL_NAME (decl));
for (i = 0; i < ARRAY_SIZE (xcoff_type_numbers); i++)
if (!strcmp (xcoff_type_numbers[i].name, name))
goto found;
return 0;
found:
if (int_size_in_bytes (TREE_TYPE (decl)) == 8)
{
if (xcoff_type_numbers[i].number == -4)
return -31;
if (xcoff_type_numbers[i].number == -10)
return -32;
}
return xcoff_type_numbers[i].number;
}
#define UNKNOWN_STAB(STR) \
internal_error ("no sclass for %s stab (0x%x)\n", STR, stab)
int
stab_to_sclass (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 *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 (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_LINE (asm_out_file, line);
}
static int do_block = 0;
static void
xcoffout_block (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 (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 (unsigned int line, unsigned int n)
{
if (n != 1)
ASM_OUTPUT_LBE (asm_out_file, line, n);
}
void
xcoffout_declare_function (FILE *file, tree decl, const char *name)
{
size_t len;
if (*name == '*')
name++;
len = strlen (name);
if (name[len - 1] == ']')
{
char *n = alloca (len - 3);
memcpy (n, name, len - 4);
n[len - 4] = '\0';
name = n;
}
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 (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_LINE (asm_out_file, line);
}
void
xcoffout_end_function (unsigned int last_linenum)
{
ASM_OUTPUT_LFE (asm_out_file, last_linenum);
}
void
xcoffout_end_epilogue (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