(dbxout_symbol_location): Subroutine broken out from dbxout_symbol.

(dbxout_symbol_location): Subroutine broken out from
dbxout_symbol.  Handle CONCAT here.
(dbxout_symbol_name): New subroutine.  Handle anonymous decls too.
(dbxout_reg_parms): Simplify using dbxout_symbol_location.
Handle CONCAT.

From-SVN: r4921
This commit is contained in:
Richard Stallman 1993-07-15 02:15:41 +00:00
parent ec4738c0ca
commit 477008025c
1 changed files with 219 additions and 192 deletions

View File

@ -263,6 +263,8 @@ void dbxout_symbol ();
static void dbxout_type_name ();
static void dbxout_type ();
static void dbxout_typedefs ();
static void dbxout_symbol_name ();
static void dbxout_symbol_location ();
static void dbxout_prepare_symbol ();
static void dbxout_finish_symbol ();
static void dbxout_continue ();
@ -1667,188 +1669,242 @@ dbxout_symbol (decl, local)
leaf_renumber_regs_insn (DECL_RTL (decl));
#endif
/* Don't mention a variable at all
if it was completely optimized into nothingness.
dbxout_symbol_location (decl, type, 0, DECL_RTL (decl));
}
}
/* Output the stab for DECL, a VAR_DECL, RESULT_DECL or PARM_DECL.
Add SUFFIX to its name, if SUFFIX is not 0.
Describe the variable as residing in HOME
(usually HOME is DECL_RTL (DECL), but not always). */
If DECL was from an inline function, then it's rtl
is not identically the rtl that was used in this
particular compilation. */
if (GET_CODE (DECL_RTL (decl)) == REG)
static void
dbxout_symbol_location (decl, type, suffix, home)
tree decl, type;
char *suffix;
rtx home;
{
int letter = 0;
int regno = -1;
/* Don't mention a variable at all
if it was completely optimized into nothingness.
If the decl was from an inline function, then it's rtl
is not identically the rtl that was used in this
particular compilation. */
if (GET_CODE (home) == REG)
{
regno = REGNO (home);
if (regno >= FIRST_PSEUDO_REGISTER)
return;
}
else if (GET_CODE (home) == SUBREG)
{
rtx value = home;
int offset = 0;
while (GET_CODE (value) == SUBREG)
{
regno = REGNO (DECL_RTL (decl));
offset += SUBREG_WORD (value);
value = SUBREG_REG (value);
}
if (GET_CODE (value) == REG)
{
regno = REGNO (value);
if (regno >= FIRST_PSEUDO_REGISTER)
return;
regno += offset;
}
else if (GET_CODE (DECL_RTL (decl)) == SUBREG)
alter_subreg (home);
}
/* The kind-of-variable letter depends on where
the variable is and on the scope of its name:
G and N_GSYM for static storage and global scope,
S for static storage and file scope,
V for static storage and local scope,
for those two, use N_LCSYM if data is in bss segment,
N_STSYM if in data segment, N_FUN otherwise.
(We used N_FUN originally, then changed to N_STSYM
to please GDB. However, it seems that confused ld.
Now GDB has been fixed to like N_FUN, says Kingdon.)
no letter at all, and N_LSYM, for auto variable,
r and N_RSYM for register variable. */
if (GET_CODE (home) == MEM
&& GET_CODE (XEXP (home, 0)) == SYMBOL_REF)
{
if (TREE_PUBLIC (decl))
{
rtx value = DECL_RTL (decl);
int offset = 0;
while (GET_CODE (value) == SUBREG)
{
offset += SUBREG_WORD (value);
value = SUBREG_REG (value);
}
if (GET_CODE (value) == REG)
{
regno = REGNO (value);
if (regno >= FIRST_PSEUDO_REGISTER)
return;
regno += offset;
}
alter_subreg (DECL_RTL (decl));
letter = 'G';
current_sym_code = N_GSYM;
}
/* The kind-of-variable letter depends on where
the variable is and on the scope of its name:
G and N_GSYM for static storage and global scope,
S for static storage and file scope,
V for static storage and local scope,
for those two, use N_LCSYM if data is in bss segment,
N_STSYM if in data segment, N_FUN otherwise.
(We used N_FUN originally, then changed to N_STSYM
to please GDB. However, it seems that confused ld.
Now GDB has been fixed to like N_FUN, says Kingdon.)
no letter at all, and N_LSYM, for auto variable,
r and N_RSYM for register variable. */
if (GET_CODE (DECL_RTL (decl)) == MEM
&& GET_CODE (XEXP (DECL_RTL (decl), 0)) == SYMBOL_REF)
else
{
if (TREE_PUBLIC (decl))
{
letter = 'G';
current_sym_code = N_GSYM;
}
current_sym_addr = XEXP (home, 0);
letter = decl_function_context (decl) ? 'V' : 'S';
if (!DECL_INITIAL (decl))
current_sym_code = N_LCSYM;
else if (TREE_READONLY (decl) && ! TREE_THIS_VOLATILE (decl))
/* This is not quite right, but it's the closest
of all the codes that Unix defines. */
current_sym_code = DBX_STATIC_CONST_VAR_CODE;
else
{
current_sym_addr = XEXP (DECL_RTL (decl), 0);
letter = decl_function_context (decl) ? 'V' : 'S';
if (!DECL_INITIAL (decl))
current_sym_code = N_LCSYM;
else if (TREE_READONLY (decl) && ! TREE_THIS_VOLATILE (decl))
/* This is not quite right, but it's the closest
of all the codes that Unix defines. */
current_sym_code = DBX_STATIC_CONST_VAR_CODE;
else
{
/* Ultrix `as' seems to need this. */
/* Ultrix `as' seems to need this. */
#ifdef DBX_STATIC_STAB_DATA_SECTION
data_section ();
data_section ();
#endif
current_sym_code = N_STSYM;
}
current_sym_code = N_STSYM;
}
}
else if (regno >= 0)
}
else if (regno >= 0)
{
letter = 'r';
current_sym_code = N_RSYM;
current_sym_value = DBX_REGISTER_NUMBER (regno);
}
else if (GET_CODE (home) == MEM
&& (GET_CODE (XEXP (home, 0)) == MEM
|| (GET_CODE (XEXP (home, 0)) == REG
&& REGNO (XEXP (home, 0)) != FRAME_POINTER_REGNUM)))
/* If the value is indirect by memory or by a register
that isn't the frame pointer
then it means the object is variable-sized and address through
that register or stack slot. DBX has no way to represent this
so all we can do is output the variable as a pointer.
If it's not a parameter, ignore it.
(VAR_DECLs like this can be made by integrate.c.) */
{
if (GET_CODE (XEXP (home, 0)) == REG)
{
letter = 'r';
current_sym_code = N_RSYM;
current_sym_value = DBX_REGISTER_NUMBER (regno);
}
else if (GET_CODE (DECL_RTL (decl)) == MEM
&& (GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM
|| (GET_CODE (XEXP (DECL_RTL (decl), 0)) == REG
&& REGNO (XEXP (DECL_RTL (decl), 0)) != FRAME_POINTER_REGNUM)))
/* If the value is indirect by memory or by a register
that isn't the frame pointer
then it means the object is variable-sized and address through
that register or stack slot. DBX has no way to represent this
so all we can do is output the variable as a pointer.
If it's not a parameter, ignore it.
(VAR_DECLs like this can be made by integrate.c.) */
{
if (GET_CODE (XEXP (DECL_RTL (decl), 0)) == REG)
{
letter = 'r';
current_sym_code = N_RSYM;
current_sym_value = DBX_REGISTER_NUMBER (REGNO (XEXP (DECL_RTL (decl), 0)));
}
else
{
current_sym_code = N_LSYM;
/* DECL_RTL looks like (MEM (MEM (PLUS (REG...) (CONST_INT...)))).
We want the value of that CONST_INT. */
current_sym_value
= DEBUGGER_AUTO_OFFSET (XEXP (XEXP (DECL_RTL (decl), 0), 0));
}
/* Effectively do build_pointer_type, but don't cache this type,
since it might be temporary whereas the type it points to
might have been saved for inlining. */
/* Don't use REFERENCE_TYPE because dbx can't handle that. */
type = make_node (POINTER_TYPE);
TREE_TYPE (type) = TREE_TYPE (decl);
}
else if (GET_CODE (DECL_RTL (decl)) == MEM
&& GET_CODE (XEXP (DECL_RTL (decl), 0)) == REG)
{
current_sym_code = N_LSYM;
current_sym_value = DEBUGGER_AUTO_OFFSET (XEXP (DECL_RTL (decl), 0));
}
else if (GET_CODE (DECL_RTL (decl)) == MEM
&& GET_CODE (XEXP (DECL_RTL (decl), 0)) == PLUS
&& GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 1)) == CONST_INT)
{
current_sym_code = N_LSYM;
/* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...)))
We want the value of that CONST_INT. */
current_sym_value = DEBUGGER_AUTO_OFFSET (XEXP (DECL_RTL (decl), 0));
}
else if (GET_CODE (DECL_RTL (decl)) == MEM
&& GET_CODE (XEXP (DECL_RTL (decl), 0)) == CONST)
{
/* Handle an obscure case which can arise when optimizing and
when there are few available registers. (This is *always*
the case for i386/i486 targets). The DECL_RTL looks like
(MEM (CONST ...)) even though this variable is a local `auto'
or a local `register' variable. In effect, what has happened
is that the reload pass has seen that all assignments and
references for one such a local variable can be replaced by
equivalent assignments and references to some static storage
variable, thereby avoiding the need for a register. In such
cases we're forced to lie to debuggers and tell them that
this variable was itself `static'. */
current_sym_code = N_LCSYM;
letter = 'V';
current_sym_addr = XEXP (XEXP (DECL_RTL (decl), 0), 0);
current_sym_value = DBX_REGISTER_NUMBER (REGNO (XEXP (home, 0)));
}
else
/* Address might be a MEM, when DECL is a variable-sized object.
Or it might be const0_rtx, meaning previous passes
want us to ignore this variable. */
break;
{
current_sym_code = N_LSYM;
/* RTL looks like (MEM (MEM (PLUS (REG...) (CONST_INT...)))).
We want the value of that CONST_INT. */
current_sym_value
= DEBUGGER_AUTO_OFFSET (XEXP (XEXP (home, 0), 0));
}
/* Ok, start a symtab entry and output the variable name. */
FORCE_TEXT;
/* Effectively do build_pointer_type, but don't cache this type,
since it might be temporary whereas the type it points to
might have been saved for inlining. */
/* Don't use REFERENCE_TYPE because dbx can't handle that. */
type = make_node (POINTER_TYPE);
TREE_TYPE (type) = TREE_TYPE (decl);
}
else if (GET_CODE (home) == MEM
&& GET_CODE (XEXP (home, 0)) == REG)
{
current_sym_code = N_LSYM;
current_sym_value = DEBUGGER_AUTO_OFFSET (XEXP (home, 0));
}
else if (GET_CODE (home) == MEM
&& GET_CODE (XEXP (home, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (home, 0), 1)) == CONST_INT)
{
current_sym_code = N_LSYM;
/* RTL looks like (MEM (PLUS (REG...) (CONST_INT...)))
We want the value of that CONST_INT. */
current_sym_value = DEBUGGER_AUTO_OFFSET (XEXP (home, 0));
}
else if (GET_CODE (home) == MEM
&& GET_CODE (XEXP (home, 0)) == CONST)
{
/* Handle an obscure case which can arise when optimizing and
when there are few available registers. (This is *always*
the case for i386/i486 targets). The RTL looks like
(MEM (CONST ...)) even though this variable is a local `auto'
or a local `register' variable. In effect, what has happened
is that the reload pass has seen that all assignments and
references for one such a local variable can be replaced by
equivalent assignments and references to some static storage
variable, thereby avoiding the need for a register. In such
cases we're forced to lie to debuggers and tell them that
this variable was itself `static'. */
current_sym_code = N_LCSYM;
letter = 'V';
current_sym_addr = XEXP (XEXP (home, 0), 0);
}
else if (GET_CODE (home) == CONCAT)
{
tree subtype = TREE_TYPE (type);
/* If the variable's storage is in two parts,
output each as a separate stab with a modified name. */
if (WORDS_BIG_ENDIAN)
dbxout_symbol_location (decl, subtype, "$imag", XEXP (home, 0));
else
dbxout_symbol_location (decl, subtype, "$real", XEXP (home, 0));
/* Cast avoids warning in old compilers. */
current_sym_code = (STAB_CODE_TYPE) 0;
current_sym_value = 0;
current_sym_addr = 0;
dbxout_prepare_symbol (decl);
if (WORDS_BIG_ENDIAN)
dbxout_symbol_location (decl, subtype, "$real", XEXP (home, 1));
else
dbxout_symbol_location (decl, subtype, "$imag", XEXP (home, 1));
return;
}
else
/* Address might be a MEM, when DECL is a variable-sized object.
Or it might be const0_rtx, meaning previous passes
want us to ignore this variable. */
return;
/* Ok, start a symtab entry and output the variable name. */
FORCE_TEXT;
#ifdef DBX_STATIC_BLOCK_START
DBX_STATIC_BLOCK_START (asmfile, current_sym_code);
DBX_STATIC_BLOCK_START (asmfile, current_sym_code);
#endif
/* One slight hitch: if this is a VAR_DECL which is a static
class member, we must put out the mangled name instead of the
DECL_NAME. */
{
char *name;
/* Note also that static member (variable) names DO NOT begin
with underscores in .stabs directives. */
if (DECL_LANG_SPECIFIC (decl))
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
else
name = IDENTIFIER_POINTER (DECL_NAME (decl));
fprintf (asmfile, "%s \"%s:", ASM_STABS_OP, name);
}
if (letter) putc (letter, asmfile);
dbxout_type (type, 0, 0);
dbxout_finish_symbol (decl);
dbxout_symbol_name (decl, suffix, letter);
dbxout_type (type, 0, 0);
dbxout_finish_symbol (decl);
#ifdef DBX_STATIC_BLOCK_END
DBX_STATIC_BLOCK_END (asmfile, current_sym_code);
DBX_STATIC_BLOCK_END (asmfile, current_sym_code);
#endif
break;
}
}
/* Output the symbol name of DECL for a stabs, with suffix SUFFIX.
Then output LETTER to indicate the kind of location the symbol has. */
static void
dbxout_symbol_name (decl, suffix, letter)
tree decl;
char *suffix;
int letter;
{
/* One slight hitch: if this is a VAR_DECL which is a static
class member, we must put out the mangled name instead of the
DECL_NAME. */
char *name;
/* Note also that static member (variable) names DO NOT begin
with underscores in .stabs directives. */
if (DECL_LANG_SPECIFIC (decl))
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
else
name = IDENTIFIER_POINTER (DECL_NAME (decl));
if (name == 0)
name = "(anon)";
fprintf (asmfile, "%s \"%s%s:", ASM_STABS_OP, name,
(suffix ? suffix : ""));
if (letter) putc (letter, asmfile);
}
static void
@ -2149,26 +2205,12 @@ dbxout_reg_parms (parms)
&& REGNO (DECL_RTL (parms)) >= 0
&& REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER
&& PARM_PASSED_IN_MEMORY (parms))
{
current_sym_code = N_RSYM;
current_sym_value = DBX_REGISTER_NUMBER (REGNO (DECL_RTL (parms)));
current_sym_addr = 0;
FORCE_TEXT;
if (DECL_NAME (parms))
{
current_sym_nchars = 2 + IDENTIFIER_LENGTH (DECL_NAME (parms));
fprintf (asmfile, "%s \"%s:r", ASM_STABS_OP,
IDENTIFIER_POINTER (DECL_NAME (parms)));
}
else
{
current_sym_nchars = 8;
fprintf (asmfile, "%s \"(anon):r", ASM_STABS_OP);
}
dbxout_type (TREE_TYPE (parms), 0, 0);
dbxout_finish_symbol (parms);
}
dbxout_symbol_location (parms, TREE_TYPE (parms),
0, DECL_RTL (parms));
else if (GET_CODE (DECL_RTL (parms)) == CONCAT
&& PARM_PASSED_IN_MEMORY (parms))
dbxout_symbol_location (parms, TREE_TYPE (parms),
0, DECL_RTL (parms));
/* Report parms that live in memory but not where they were passed. */
else if (GET_CODE (DECL_RTL (parms)) == MEM
&& GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS
@ -2188,23 +2230,8 @@ dbxout_reg_parms (parms)
#endif
if (INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)) != offset) {...}
#endif
current_sym_code = N_LSYM;
current_sym_value = DEBUGGER_AUTO_OFFSET (XEXP (DECL_RTL (parms), 0));
current_sym_addr = 0;
FORCE_TEXT;
if (DECL_NAME (parms))
{
current_sym_nchars = 2 + IDENTIFIER_LENGTH (DECL_NAME (parms));
fprintf (asmfile, "%s \"%s:", ASM_STABS_OP,
IDENTIFIER_POINTER (DECL_NAME (parms)));
}
else
{
current_sym_nchars = 8;
fprintf (asmfile, "%s \"(anon):", ASM_STABS_OP);
}
dbxout_type (TREE_TYPE (parms), 0, 0);
dbxout_finish_symbol (parms);
dbxout_symbol_location (parms, TREE_TYPE (parms),
0, DECL_RTL (parms));
}
#if 0
else if (GET_CODE (DECL_RTL (parms)) == MEM