varasm.c (struct deferred_string): New structure.
* varasm.c (struct deferred_string): New structure. (const_str_htab): New variable. (STRHASH): New macro. (mark_const_str_htab_1, mark_const_str_htab, const_str_htab_hash, constr_str_htab_eq, const_str_htab_del): New functions. (output_constant_def): Add DEFER argument, defer string constants until mark_constant_pool time if requested. (mark_constant_pool): Walk the insn chain even if const_str_htab is not empty. (mark_constants): If a SYMBOL_REF for deferred string is found, output it and remove from hash table. (output_addressed_constants): Set DEFER to 0 in call to output_constant_def. * rtl.h (STRING_POOL_ADDRESS_P): Define. (output_constant_def): Adjust prototype. * expr.c (expand_expr): Set DEFER to 1 in call to output_constant_def. * gcc.c-torture/execute/20000801-4.c: Make sure the second string is output. From-SVN: r37459
This commit is contained in:
parent
10e927efe9
commit
bd7cf17efd
6 changed files with 186 additions and 19 deletions
|
@ -1,3 +1,22 @@
|
|||
2000-11-14 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* varasm.c (struct deferred_string): New structure.
|
||||
(const_str_htab): New variable.
|
||||
(STRHASH): New macro.
|
||||
(mark_const_str_htab_1, mark_const_str_htab, const_str_htab_hash,
|
||||
constr_str_htab_eq, const_str_htab_del): New functions.
|
||||
(output_constant_def): Add DEFER argument, defer string
|
||||
constants until mark_constant_pool time if requested.
|
||||
(mark_constant_pool): Walk the insn chain even if const_str_htab is
|
||||
not empty.
|
||||
(mark_constants): If a SYMBOL_REF for deferred string is found,
|
||||
output it and remove from hash table.
|
||||
(output_addressed_constants): Set DEFER to 0 in call to
|
||||
output_constant_def.
|
||||
* rtl.h (STRING_POOL_ADDRESS_P): Define.
|
||||
(output_constant_def): Adjust prototype.
|
||||
* expr.c (expand_expr): Set DEFER to 1 in call to output_constant_def.
|
||||
|
||||
2000-11-14 Chandrakala Chavva <cchavva@redhat.com>
|
||||
|
||||
* optabs.c (expand_complex_ab):: Use overflow-trapping optabs for
|
||||
|
|
|
@ -6143,7 +6143,7 @@ expand_expr (exp, target, tmode, modifier)
|
|||
case COMPLEX_CST:
|
||||
case STRING_CST:
|
||||
if (! TREE_CST_RTL (exp))
|
||||
output_constant_def (exp);
|
||||
output_constant_def (exp, 1);
|
||||
|
||||
/* TREE_CST_RTL probably contains a constant address.
|
||||
On RISC machines where a constant address isn't valid,
|
||||
|
@ -6456,7 +6456,7 @@ expand_expr (exp, target, tmode, modifier)
|
|||
&& ! mostly_zeros_p (exp))))
|
||||
|| (modifier == EXPAND_INITIALIZER && TREE_CONSTANT (exp)))
|
||||
{
|
||||
rtx constructor = output_constant_def (exp);
|
||||
rtx constructor = output_constant_def (exp, 1);
|
||||
|
||||
if (modifier != EXPAND_CONST_ADDRESS
|
||||
&& modifier != EXPAND_INITIALIZER
|
||||
|
|
|
@ -168,7 +168,9 @@ typedef struct rtx_def
|
|||
either changing how we compute the frame address or saving and
|
||||
restoring registers in the prologue and epilogue.
|
||||
1 in a MEM if the MEM refers to a scalar, rather than a member of
|
||||
an aggregate. */
|
||||
an aggregate.
|
||||
1 in a SYMBOL_REF if it addresses something in the per-function
|
||||
constant string pool. */
|
||||
unsigned frame_related : 1;
|
||||
|
||||
/* The first element of the operands of this rtx.
|
||||
|
@ -904,6 +906,9 @@ extern const char * const note_insn_name[NOTE_INSN_MAX - NOTE_INSN_BIAS];
|
|||
/* 1 in a SYMBOL_REF if it addresses this function's constants pool. */
|
||||
#define CONSTANT_POOL_ADDRESS_P(RTX) ((RTX)->unchanging)
|
||||
|
||||
/* 1 in a SYMBOL_REF if it addresses this function's string constant pool. */
|
||||
#define STRING_POOL_ADDRESS_P(RTX) ((RTX)->frame_related)
|
||||
|
||||
/* Flag in a SYMBOL_REF for machine-specific purposes. */
|
||||
#define SYMBOL_REF_FLAG(RTX) ((RTX)->volatil)
|
||||
|
||||
|
@ -1587,7 +1592,7 @@ extern rtx gen_rtx_MEM PARAMS ((enum machine_mode, rtx));
|
|||
extern rtx find_next_ref PARAMS ((rtx, rtx));
|
||||
extern rtx *find_single_use PARAMS ((rtx, rtx, rtx *));
|
||||
|
||||
extern rtx output_constant_def PARAMS ((union tree_node *));
|
||||
extern rtx output_constant_def PARAMS ((union tree_node *, int));
|
||||
extern rtx immed_real_const PARAMS ((union tree_node *));
|
||||
extern union tree_node *make_tree PARAMS ((union tree_node *, rtx));
|
||||
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2000-11-14 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* gcc.c-torture/execute/20000801-4.c: Make sure the second string is
|
||||
output.
|
||||
|
||||
2000-11-13 Joseph S. Myers <jsm28@cam.ac.uk>
|
||||
|
||||
* gcc.dg/wtr-label-1.c, gcc.dg/990214-1.c: Add semicolons after
|
||||
|
|
|
@ -14,11 +14,14 @@ foo (void)
|
|||
return 0 == s[1];
|
||||
}
|
||||
|
||||
char *t;
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
{
|
||||
char s[] = "x";
|
||||
t = s;
|
||||
}
|
||||
if (foo ())
|
||||
exit (0);
|
||||
|
|
165
gcc/varasm.c
165
gcc/varasm.c
|
@ -44,6 +44,7 @@ Boston, MA 02111-1307, USA. */
|
|||
#include "dbxout.h"
|
||||
#include "sdbout.h"
|
||||
#include "obstack.h"
|
||||
#include "hashtab.h"
|
||||
#include "c-pragma.h"
|
||||
#include "ggc.h"
|
||||
#include "tm_p.h"
|
||||
|
@ -185,6 +186,11 @@ static void asm_output_aligned_bss PARAMS ((FILE *, tree, const char *,
|
|||
#endif /* BSS_SECTION_ASM_OP */
|
||||
static void mark_pool_constant PARAMS ((struct pool_constant *));
|
||||
static void mark_const_hash_entry PARAMS ((void *));
|
||||
static int mark_const_str_htab_1 PARAMS ((void **, void *));
|
||||
static void mark_const_str_htab PARAMS ((void *));
|
||||
static hashval_t const_str_htab_hash PARAMS ((const void *x));
|
||||
static int const_str_htab_eq PARAMS ((const void *x, const void *y));
|
||||
static void const_str_htab_del PARAMS ((void *));
|
||||
static void asm_emit_uninitialised PARAMS ((tree, const char*, int, int));
|
||||
|
||||
static enum in_section { no_section, in_text, in_data, in_named
|
||||
|
@ -2342,6 +2348,17 @@ struct constant_descriptor
|
|||
#define MAX_HASH_TABLE 1009
|
||||
static struct constant_descriptor *const_hash_table[MAX_HASH_TABLE];
|
||||
|
||||
#define STRHASH(x) ((hashval_t)((long)(x) >> 3))
|
||||
|
||||
struct deferred_string
|
||||
{
|
||||
char *label;
|
||||
tree exp;
|
||||
int labelno;
|
||||
};
|
||||
|
||||
static htab_t const_str_htab;
|
||||
|
||||
/* Mark a const_hash_table descriptor for GC. */
|
||||
|
||||
static void
|
||||
|
@ -2358,6 +2375,58 @@ mark_const_hash_entry (ptr)
|
|||
}
|
||||
}
|
||||
|
||||
/* Mark the hash-table element X (which is really a pointer to an
|
||||
struct deferred_string *). */
|
||||
|
||||
static int
|
||||
mark_const_str_htab_1 (x, data)
|
||||
void **x;
|
||||
void *data ATTRIBUTE_UNUSED;
|
||||
{
|
||||
ggc_mark_tree (((struct deferred_string *) *x)->exp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Mark a const_str_htab for GC. */
|
||||
|
||||
static void
|
||||
mark_const_str_htab (htab)
|
||||
void *htab;
|
||||
{
|
||||
htab_traverse (*((htab_t *) htab), mark_const_str_htab_1, NULL);
|
||||
}
|
||||
|
||||
/* Returns a hash code for X (which is a really a
|
||||
struct deferred_string *). */
|
||||
|
||||
static hashval_t
|
||||
const_str_htab_hash (x)
|
||||
const void *x;
|
||||
{
|
||||
return STRHASH (((struct deferred_string *) x)->label);
|
||||
}
|
||||
|
||||
/* Returns non-zero if the value represented by X (which is really a
|
||||
struct deferred_string *) is the same as that given by Y
|
||||
(which is really a char *). */
|
||||
|
||||
static int
|
||||
const_str_htab_eq (x, y)
|
||||
const void *x;
|
||||
const void *y;
|
||||
{
|
||||
return (((struct deferred_string *) x)->label == (char *) y);
|
||||
}
|
||||
|
||||
/* Delete the hash table entry dfsp. */
|
||||
|
||||
static void
|
||||
const_str_htab_del (dfsp)
|
||||
void *dfsp;
|
||||
{
|
||||
free (dfsp);
|
||||
}
|
||||
|
||||
/* Compute a hash code for a constant expression. */
|
||||
|
||||
static int
|
||||
|
@ -3056,18 +3125,25 @@ copy_constant (exp)
|
|||
Otherwise, output such a constant in memory (or defer it for later)
|
||||
and generate an rtx for it.
|
||||
|
||||
If DEFER is non-zero, the output of string constants can be deferred
|
||||
and output only if referenced in the function after all optimizations.
|
||||
|
||||
The TREE_CST_RTL of EXP is set up to point to that rtx.
|
||||
The const_hash_table records which constants already have label strings. */
|
||||
|
||||
rtx
|
||||
output_constant_def (exp)
|
||||
output_constant_def (exp, defer)
|
||||
tree exp;
|
||||
int defer;
|
||||
{
|
||||
register int hash;
|
||||
register struct constant_descriptor *desc;
|
||||
struct deferred_string **defstr;
|
||||
char label[256];
|
||||
int reloc;
|
||||
int found = 1;
|
||||
int after_function = 0;
|
||||
int labelno = -1;
|
||||
|
||||
if (TREE_CST_RTL (exp))
|
||||
return TREE_CST_RTL (exp);
|
||||
|
@ -3095,7 +3171,8 @@ output_constant_def (exp)
|
|||
future calls to this function to find. */
|
||||
|
||||
/* Create a string containing the label name, in LABEL. */
|
||||
ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
|
||||
labelno = const_labelno++;
|
||||
ASM_GENERATE_INTERNAL_LABEL (label, "LC", labelno);
|
||||
|
||||
desc = record_constant (exp);
|
||||
desc->next = const_hash_table[hash];
|
||||
|
@ -3121,18 +3198,34 @@ output_constant_def (exp)
|
|||
ENCODE_SECTION_INFO (exp);
|
||||
#endif
|
||||
|
||||
#ifdef CONSTANT_AFTER_FUNCTION_P
|
||||
if (current_function_decl != 0
|
||||
&& CONSTANT_AFTER_FUNCTION_P (exp))
|
||||
after_function = 1;
|
||||
#endif
|
||||
|
||||
if (found
|
||||
&& STRING_POOL_ADDRESS_P (XEXP (desc->rtl, 0))
|
||||
&& (!defer || defer_addressed_constants_flag || after_function))
|
||||
{
|
||||
defstr = (struct deferred_string **)
|
||||
htab_find_slot_with_hash (const_str_htab, desc->label,
|
||||
STRHASH (desc->label), NO_INSERT);
|
||||
if (defstr)
|
||||
{
|
||||
/* If the string is currently deferred but we need to output it now,
|
||||
remove it from deferred string hash table. */
|
||||
found = 0;
|
||||
labelno = (*defstr)->labelno;
|
||||
STRING_POOL_ADDRESS_P (XEXP (desc->rtl, 0)) = 0;
|
||||
htab_clear_slot (const_str_htab, (void **) defstr);
|
||||
}
|
||||
}
|
||||
|
||||
/* If this is the first time we've seen this particular constant,
|
||||
output it (or defer its output for later). */
|
||||
if (! found)
|
||||
{
|
||||
int after_function = 0;
|
||||
|
||||
#ifdef CONSTANT_AFTER_FUNCTION_P
|
||||
if (current_function_decl != 0
|
||||
&& CONSTANT_AFTER_FUNCTION_P (exp))
|
||||
after_function = 1;
|
||||
#endif
|
||||
|
||||
if (defer_addressed_constants_flag || after_function)
|
||||
{
|
||||
struct deferred_constant *p;
|
||||
|
@ -3140,7 +3233,7 @@ output_constant_def (exp)
|
|||
|
||||
p->exp = copy_constant (exp);
|
||||
p->reloc = reloc;
|
||||
p->labelno = const_labelno++;
|
||||
p->labelno = labelno;
|
||||
if (after_function)
|
||||
{
|
||||
p->next = after_function_constants;
|
||||
|
@ -3156,8 +3249,30 @@ output_constant_def (exp)
|
|||
{
|
||||
/* Do no output if -fsyntax-only. */
|
||||
if (! flag_syntax_only)
|
||||
output_constant_def_contents (exp, reloc, const_labelno);
|
||||
++const_labelno;
|
||||
{
|
||||
if (TREE_CODE (exp) != STRING_CST
|
||||
|| !defer
|
||||
|| flag_writable_strings
|
||||
|| (defstr = (struct deferred_string **)
|
||||
htab_find_slot_with_hash (const_str_htab,
|
||||
desc->label,
|
||||
STRHASH (desc->label),
|
||||
INSERT)) == NULL)
|
||||
output_constant_def_contents (exp, reloc, labelno);
|
||||
else
|
||||
{
|
||||
struct deferred_string *p;
|
||||
|
||||
p = (struct deferred_string *)
|
||||
xmalloc (sizeof (struct deferred_string));
|
||||
|
||||
p->exp = copy_constant (exp);
|
||||
p->label = desc->label;
|
||||
p->labelno = labelno;
|
||||
*defstr = p;
|
||||
STRING_POOL_ADDRESS_P (XEXP (desc->rtl, 0)) = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3806,7 +3921,7 @@ mark_constant_pool ()
|
|||
register rtx insn;
|
||||
struct pool_constant *pool;
|
||||
|
||||
if (first_pool == 0)
|
||||
if (first_pool == 0 && htab_elements (const_str_htab) == 0)
|
||||
return;
|
||||
|
||||
for (pool = first_pool; pool; pool = pool->next)
|
||||
|
@ -3867,6 +3982,22 @@ mark_constants (x)
|
|||
{
|
||||
if (CONSTANT_POOL_ADDRESS_P (x))
|
||||
find_pool_constant (cfun, x)->mark = 1;
|
||||
else if (STRING_POOL_ADDRESS_P (x))
|
||||
{
|
||||
struct deferred_string **defstr;
|
||||
|
||||
defstr = (struct deferred_string **)
|
||||
htab_find_slot_with_hash (const_str_htab, XSTR (x, 0),
|
||||
STRHASH (XSTR (x, 0)), NO_INSERT);
|
||||
if (defstr)
|
||||
{
|
||||
struct deferred_string *p = *defstr;
|
||||
|
||||
STRING_POOL_ADDRESS_P (x) = 0;
|
||||
output_constant_def_contents (p->exp, 0, p->labelno);
|
||||
htab_clear_slot (const_str_htab, (void **) defstr);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* Never search inside a CONST_DOUBLE, because CONST_DOUBLE_MEM may be
|
||||
|
@ -3943,7 +4074,7 @@ output_addressed_constants (exp)
|
|||
|| TREE_CODE (constant) == CONSTRUCTOR)
|
||||
/* No need to do anything here
|
||||
for addresses of variables or functions. */
|
||||
output_constant_def (constant);
|
||||
output_constant_def (constant, 0);
|
||||
}
|
||||
reloc = 1;
|
||||
break;
|
||||
|
@ -4757,8 +4888,12 @@ make_decl_one_only (decl)
|
|||
void
|
||||
init_varasm_once ()
|
||||
{
|
||||
const_str_htab = htab_create (128, const_str_htab_hash, const_str_htab_eq,
|
||||
const_str_htab_del);
|
||||
ggc_add_root (const_hash_table, MAX_HASH_TABLE, sizeof const_hash_table[0],
|
||||
mark_const_hash_entry);
|
||||
ggc_add_root (&const_str_htab, 1, sizeof const_str_htab,
|
||||
mark_const_str_htab);
|
||||
ggc_add_string_root (&in_named_name, 1);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue