summaryrefslogtreecommitdiff
path: root/gcc/varasm.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/varasm.c')
-rw-r--r--gcc/varasm.c247
1 files changed, 112 insertions, 135 deletions
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 0be810aa2a9..e7df584a147 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -85,6 +85,48 @@ extern struct obstack *rtl_obstack;
extern struct obstack permanent_obstack;
#define obstack_chunk_alloc xmalloc
+struct addr_const;
+struct constant_descriptor;
+struct rtx_const;
+struct pool_constant;
+
+#define MAX_RTX_HASH_TABLE 61
+
+struct varasm_status
+{
+ /* Hash facility for making memory-constants
+ from constant rtl-expressions. It is used on RISC machines
+ where immediate integer arguments and constant addresses are restricted
+ so that such constants must be stored in memory.
+
+ This pool of constants is reinitialized for each function
+ so each function gets its own constants-pool that comes right before
+ it. */
+ struct constant_descriptor **x_const_rtx_hash_table;
+ struct pool_sym **x_const_rtx_sym_hash_table;
+
+ /* Pointers to first and last constant in pool. */
+ struct pool_constant *x_first_pool, *x_last_pool;
+
+ /* Current offset in constant pool (does not include any machine-specific
+ header. */
+ int x_pool_offset;
+
+ /* Chain of all CONST_DOUBLE rtx's constructed for the current function.
+ They are chained through the CONST_DOUBLE_CHAIN.
+ A CONST_DOUBLE rtx has CONST_DOUBLE_MEM != cc0_rtx iff it is on this chain.
+ In that case, CONST_DOUBLE_MEM is either a MEM,
+ or const0_rtx if no MEM has been made for this CONST_DOUBLE yet. */
+ rtx x_const_double_chain;
+};
+
+#define const_rtx_hash_table (current_function->varasm->x_const_rtx_hash_table)
+#define const_rtx_sym_hash_table (current_function->varasm->x_const_rtx_sym_hash_table)
+#define first_pool (current_function->varasm->x_first_pool)
+#define last_pool (current_function->varasm->x_last_pool)
+#define pool_offset (current_function->varasm->x_pool_offset)
+#define const_double_chain (current_function->varasm->x_const_double_chain)
+
/* Number for making the label on the next
constant that is stored in memory. */
@@ -111,11 +153,6 @@ tree last_assemble_variable_decl;
static int function_defined;
-struct addr_const;
-struct constant_descriptor;
-struct rtx_const;
-struct pool_constant;
-
static const char *strip_reg_name PROTO((const char *));
static int contains_pointers_p PROTO((tree));
static void decode_addr_const PROTO((tree, struct addr_const *));
@@ -134,7 +171,7 @@ static int compare_constant_rtx PROTO((enum machine_mode, rtx,
struct constant_descriptor *));
static struct constant_descriptor *record_constant_rtx PROTO((enum machine_mode,
rtx));
-static struct pool_constant *find_pool_constant PROTO((rtx));
+static struct pool_constant *find_pool_constant PROTO((struct function *, rtx));
static void mark_constant_pool PROTO((void));
static void mark_constants PROTO((rtx));
static int output_addressed_constants PROTO((tree));
@@ -1960,17 +1997,6 @@ assemble_real (d, mode)
/* Here we combine duplicate floating constants to make
CONST_DOUBLE rtx's, and force those out to memory when necessary. */
-/* Chain of all CONST_DOUBLE rtx's constructed for the current function.
- They are chained through the CONST_DOUBLE_CHAIN.
- A CONST_DOUBLE rtx has CONST_DOUBLE_MEM != cc0_rtx iff it is on this chain.
- In that case, CONST_DOUBLE_MEM is either a MEM,
- or const0_rtx if no MEM has been made for this CONST_DOUBLE yet.
-
- (CONST_DOUBLE_MEM is used only for top-level functions.
- See force_const_mem for explanation.) */
-
-static rtx const_double_chain;
-
/* Return a CONST_DOUBLE or CONST_INT for a value specified as a pair of ints.
For an integer, I0 is the low-order word and I1 is the high-order word.
For a real number, I0 is the word with the low address
@@ -2045,11 +2071,11 @@ immed_double_const (i0, i1, mode)
/* Search the chain for an existing CONST_DOUBLE with the right value.
If one is found, return it. */
-
- for (r = const_double_chain; r; r = CONST_DOUBLE_CHAIN (r))
- if (CONST_DOUBLE_LOW (r) == i0 && CONST_DOUBLE_HIGH (r) == i1
- && GET_MODE (r) == mode)
- return r;
+ if (current_function != 0)
+ for (r = const_double_chain; r; r = CONST_DOUBLE_CHAIN (r))
+ if (CONST_DOUBLE_LOW (r) == i0 && CONST_DOUBLE_HIGH (r) == i1
+ && GET_MODE (r) == mode)
+ return r;
/* No; make a new one and add it to the chain.
@@ -2064,9 +2090,8 @@ immed_double_const (i0, i1, mode)
r = gen_rtx_CONST_DOUBLE (mode, NULL_RTX, i0, i1);
pop_obstacks ();
- /* Don't touch const_double_chain in nested function; see force_const_mem.
- Also, don't touch it if not inside any function. */
- if (outer_function_chain == 0 && current_function_decl != 0)
+ /* Don't touch const_double_chain if not inside any function. */
+ if (current_function_decl != 0)
{
CONST_DOUBLE_CHAIN (r) = const_double_chain;
const_double_chain = r;
@@ -2118,11 +2143,11 @@ immed_real_const_1 (d, mode)
/* Search the chain for an existing CONST_DOUBLE with the right value.
If one is found, return it. */
-
- for (r = const_double_chain; r; r = CONST_DOUBLE_CHAIN (r))
- if (! bcmp ((char *) &CONST_DOUBLE_LOW (r), (char *) &u, sizeof u)
- && GET_MODE (r) == mode)
- return r;
+ if (current_function != 0)
+ for (r = const_double_chain; r; r = CONST_DOUBLE_CHAIN (r))
+ if (! bcmp ((char *) &CONST_DOUBLE_LOW (r), (char *) &u, sizeof u)
+ && GET_MODE (r) == mode)
+ return r;
/* No; make a new one and add it to the chain.
@@ -2131,17 +2156,15 @@ immed_real_const_1 (d, mode)
we will be leaving this constant on the chain, so we cannot tolerate
freed memory. So switch to saveable_obstack for this allocation
and then switch back if we were in current_obstack. */
-
push_obstacks_nochange ();
rtl_in_saveable_obstack ();
r = rtx_alloc (CONST_DOUBLE);
+ pop_obstacks ();
PUT_MODE (r, mode);
bcopy ((char *) &u, (char *) &CONST_DOUBLE_LOW (r), sizeof u);
- pop_obstacks ();
- /* Don't touch const_double_chain in nested function; see force_const_mem.
- Also, don't touch it if not inside any function. */
- if (outer_function_chain == 0 && current_function_decl != 0)
+ /* Don't touch const_double_chain if not inside any function. */
+ if (current_function_decl != 0)
{
CONST_DOUBLE_CHAIN (r) = const_double_chain;
const_double_chain = r;
@@ -2175,11 +2198,6 @@ clear_const_double_mem ()
{
register rtx r, next;
- /* Don't touch CONST_DOUBLE_MEM for nested functions.
- See force_const_mem for explanation. */
- if (outer_function_chain != 0)
- return;
-
for (r = const_double_chain; r; r = next)
{
next = CONST_DOUBLE_CHAIN (r);
@@ -3110,20 +3128,6 @@ output_constant_def_contents (exp, reloc, labelno)
}
-/* Similar hash facility for making memory-constants
- from constant rtl-expressions. It is used on RISC machines
- where immediate integer arguments and constant addresses are restricted
- so that such constants must be stored in memory.
-
- This pool of constants is reinitialized for each function
- so each function gets its own constants-pool that comes right before it.
-
- All structures allocated here are discarded when functions are saved for
- inlining, so they do not need to be allocated permanently. */
-
-#define MAX_RTX_HASH_TABLE 61
-static struct constant_descriptor **const_rtx_hash_table;
-
/* Structure to represent sufficient information about a constant so that
it can be output when the constant pool is output, so that function
integration can be done, and to simplify handling on machines that reference
@@ -3141,15 +3145,6 @@ struct pool_constant
int mark;
};
-/* Pointers to first and last constant in pool. */
-
-static struct pool_constant *first_pool, *last_pool;
-
-/* Current offset in constant pool (does not include any machine-specific
- header. */
-
-static int pool_offset;
-
/* Structure used to maintain hash table mapping symbols used to their
corresponding constants. */
@@ -3160,63 +3155,35 @@ struct pool_sym
struct pool_sym *next;
};
-static struct pool_sym **const_rtx_sym_hash_table;
-
/* Hash code for a SYMBOL_REF with CONSTANT_POOL_ADDRESS_P true.
The argument is XSTR (... , 0) */
#define SYMHASH(LABEL) \
((((unsigned long) (LABEL)) & ((1 << HASHBITS) - 1)) % MAX_RTX_HASH_TABLE)
-/* Initialize constant pool hashing for next function. */
+/* Initialize constant pool hashing for a new function. */
void
-init_const_rtx_hash_table ()
+init_varasm_status (f)
+ struct function *f;
{
- const_rtx_hash_table
+ struct varasm_status *p;
+ p = (struct varasm_status *) xmalloc (sizeof (struct varasm_status));
+ f->varasm = p;
+ p->x_const_rtx_hash_table
= ((struct constant_descriptor **)
- oballoc (MAX_RTX_HASH_TABLE * sizeof (struct constant_descriptor *)));
- const_rtx_sym_hash_table
+ xmalloc (MAX_RTX_HASH_TABLE * sizeof (struct constant_descriptor *)));
+ p->x_const_rtx_sym_hash_table
= ((struct pool_sym **)
- oballoc (MAX_RTX_HASH_TABLE * sizeof (struct pool_sym *)));
- bzero ((char *) const_rtx_hash_table,
+ xmalloc (MAX_RTX_HASH_TABLE * sizeof (struct pool_sym *)));
+ bzero ((char *) p->x_const_rtx_hash_table,
MAX_RTX_HASH_TABLE * sizeof (struct constant_descriptor *));
- bzero ((char *) const_rtx_sym_hash_table,
+ bzero ((char *) p->x_const_rtx_sym_hash_table,
MAX_RTX_HASH_TABLE * sizeof (struct pool_sym *));
- first_pool = last_pool = 0;
- pool_offset = 0;
-}
-
-/* Save and restore status for a nested function. */
-
-void
-save_varasm_status (p, context)
- struct function *p;
- tree context;
-{
- p->const_rtx_hash_table = const_rtx_hash_table;
- p->const_rtx_sym_hash_table = const_rtx_sym_hash_table;
- p->first_pool = first_pool;
- p->last_pool = last_pool;
- p->pool_offset = pool_offset;
- p->const_double_chain = const_double_chain;
-
- /* If we are pushing to toplevel, we can't reuse const_double_chain. */
- if (context == NULL_TREE)
- const_double_chain = 0;
-}
-
-void
-restore_varasm_status (p)
- struct function *p;
-{
- const_rtx_hash_table = p->const_rtx_hash_table;
- const_rtx_sym_hash_table = p->const_rtx_sym_hash_table;
- first_pool = p->first_pool;
- last_pool = p->last_pool;
- pool_offset = p->pool_offset;
- const_double_chain = p->const_double_chain;
+ p->x_first_pool = p->x_last_pool = 0;
+ p->x_pool_offset = 0;
+ p->x_const_double_chain = 0;
}
enum kind { RTX_DOUBLE, RTX_INT };
@@ -3439,15 +3406,10 @@ force_const_mem (mode, x)
modes in an alternating fashion, we will allocate a lot of different
memory locations, but this should be extremely rare. */
- /* Don't use CONST_DOUBLE_MEM in a nested function.
- Nested functions have their own constant pools,
- so they can't share the same values in CONST_DOUBLE_MEM
- with the containing function. */
- if (outer_function_chain == 0)
- if (GET_CODE (x) == CONST_DOUBLE
- && GET_CODE (CONST_DOUBLE_MEM (x)) == MEM
- && GET_MODE (CONST_DOUBLE_MEM (x)) == mode)
- return CONST_DOUBLE_MEM (x);
+ if (GET_CODE (x) == CONST_DOUBLE
+ && GET_CODE (CONST_DOUBLE_MEM (x)) == MEM
+ && GET_MODE (CONST_DOUBLE_MEM (x)) == mode)
+ return CONST_DOUBLE_MEM (x);
/* Compute hash code of X. Search the descriptors for that hash code
to see if any of them describes X. If yes, the descriptor records
@@ -3558,16 +3520,15 @@ force_const_mem (mode, x)
CONSTANT_POOL_ADDRESS_P (XEXP (def, 0)) = 1;
current_function_uses_const_pool = 1;
- if (outer_function_chain == 0)
- if (GET_CODE (x) == CONST_DOUBLE)
- {
- if (CONST_DOUBLE_MEM (x) == cc0_rtx)
- {
- CONST_DOUBLE_CHAIN (x) = const_double_chain;
- const_double_chain = x;
- }
- CONST_DOUBLE_MEM (x) = def;
- }
+ if (GET_CODE (x) == CONST_DOUBLE)
+ {
+ if (CONST_DOUBLE_MEM (x) == cc0_rtx)
+ {
+ CONST_DOUBLE_CHAIN (x) = const_double_chain;
+ const_double_chain = x;
+ }
+ CONST_DOUBLE_MEM (x) = def;
+ }
return def;
}
@@ -3576,13 +3537,14 @@ force_const_mem (mode, x)
the corresponding pool_constant structure. */
static struct pool_constant *
-find_pool_constant (addr)
+find_pool_constant (f, addr)
+ struct function *f;
rtx addr;
{
struct pool_sym *sym;
char *label = XSTR (addr, 0);
- for (sym = const_rtx_sym_hash_table[SYMHASH (label)]; sym; sym = sym->next)
+ for (sym = f->varasm->x_const_rtx_sym_hash_table[SYMHASH (label)]; sym; sym = sym->next)
if (sym->label == label)
return sym->pool;
@@ -3595,7 +3557,17 @@ rtx
get_pool_constant (addr)
rtx addr;
{
- return (find_pool_constant (addr))->constant;
+ return (find_pool_constant (current_function, addr))->constant;
+}
+
+/* Likewise, but for the constant pool of a specific function. */
+
+rtx
+get_pool_constant_for_function (f, addr)
+ struct function *f;
+ rtx addr;
+{
+ return (find_pool_constant (f, addr))->constant;
}
/* Similar, return the mode. */
@@ -3604,7 +3576,15 @@ enum machine_mode
get_pool_mode (addr)
rtx addr;
{
- return (find_pool_constant (addr))->mode;
+ return (find_pool_constant (current_function, addr))->mode;
+}
+
+enum machine_mode
+get_pool_mode_for_function (f, addr)
+ struct function *f;
+ rtx addr;
+{
+ return (find_pool_constant (f, addr))->mode;
}
/* Similar, return the offset in the constant pool. */
@@ -3613,7 +3593,7 @@ int
get_pool_offset (addr)
rtx addr;
{
- return (find_pool_constant (addr))->offset;
+ return (find_pool_constant (current_function, addr))->offset;
}
/* Return the size of the constant pool. */
@@ -3786,14 +3766,11 @@ mark_constants (x)
if (GET_CODE (x) == SYMBOL_REF)
{
if (CONSTANT_POOL_ADDRESS_P (x))
- find_pool_constant (x)->mark = 1;
+ find_pool_constant (current_function, x)->mark = 1;
return;
}
/* Never search inside a CONST_DOUBLE, because CONST_DOUBLE_MEM may be
- a MEM, but does not constitute a use of that MEM. This is particularly
- important inside a nested function, because CONST_DOUBLE_MEM may be
- a reference to a MEM in the parent's constant pool. See the comment
- in force_const_mem. */
+ a MEM, but does not constitute a use of that MEM. */
else if (GET_CODE (x) == CONST_DOUBLE)
return;