#include "expr.h"
#include "hard-reg-set.h"
#include "regs.h"
-#include "defaults.h"
#include "output.h"
#include "real.h"
#include "toplev.h"
#endif
/* Define the prefix to use when check_memory_usage_flag is enable. */
-#ifdef NO_DOLLAR_IN_LABEL
-#ifdef NO_DOT_IN_LABEL
-#define CHKR_PREFIX "chkr_prefix_"
-#else /* !NO_DOT_IN_LABEL */
-#define CHKR_PREFIX "chkr."
-#endif
-#else /* !NO_DOLLAR_IN_LABEL */
-#define CHKR_PREFIX "chkr$"
-#endif
+#define CHKR_PREFIX "_CHKR_"
#define CHKR_PREFIX_SIZE (sizeof (CHKR_PREFIX) - 1)
/* File in which assembler code is being written. */
static struct pool_constant *find_pool_constant PARAMS ((struct function *, rtx));
static void mark_constant_pool PARAMS ((void));
static void mark_constants PARAMS ((rtx));
+static int mark_constant PARAMS ((rtx *current_rtx, void *data));
static int output_addressed_constants PARAMS ((tree));
static void output_after_function_constants PARAMS ((void));
static unsigned HOST_WIDE_INT array_size_for_constructor PARAMS ((tree));
}
}
-#ifdef ASM_OUTPUT_SECTION_NAME
-#ifndef UNIQUE_SECTION
-#define UNIQUE_SECTION(DECL,RELOC) \
-do { \
- int len; \
- const char *name; \
- char *string; \
- \
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (DECL)); \
- /* Strip off any encoding in name. */ \
- STRIP_NAME_ENCODING (name, name); \
- \
- len = strlen (name) + 1; \
- string = alloca (len + 1); \
- sprintf (string, ".%s", name); \
- \
- DECL_SECTION_NAME (DECL) = build_string (len, string); \
-} while (0)
-#endif
-#ifndef UNIQUE_SECTION_P
-#define UNIQUE_SECTION_P(DECL) 0
-#endif
-#endif
-
#ifdef BSS_SECTION_ASM_OP
/* Tell the assembler to switch to the bss section. */
#endif
}
\f
-/* Create the rtl to represent a function, for a function definition.
- DECL is a FUNCTION_DECL node which describes which function.
- The rtl is stored into DECL. */
-
-void
-make_function_rtl (decl)
- tree decl;
-{
- const char *name;
- const char *new_name;
-
- if (DECL_RTL (decl) != 0)
- {
- /* ??? Another way to do this would be to do what halfpic.c does
- and maintain a hashed table of such critters. */
- /* ??? Another way to do this would be to pass a flag bit to
- ENCODE_SECTION_INFO saying whether this is a new decl or not. */
- /* Let the target reassign the RTL if it wants.
- This is necessary, for example, when one machine specific
- decl attribute overrides another. */
-#ifdef REDO_SECTION_INFO_P
- if (REDO_SECTION_INFO_P (decl))
- ENCODE_SECTION_INFO (decl);
-#endif
- return;
- }
-
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- new_name = name;
-
- /* Rename a nested function to avoid conflicts, unless it's a member of
- a local class, in which case the class name is already unique. */
- if (decl_function_context (decl) != 0
- && ! TYPE_P (DECL_CONTEXT (decl))
- && DECL_INITIAL (decl) != 0
- && DECL_RTL (decl) == 0)
- {
- char *label;
- ASM_FORMAT_PRIVATE_NAME (label, name, var_labelno);
- var_labelno++;
- new_name = label;
- }
- /* When -fprefix-function-name is used, every function name is
- prefixed. Even static functions are prefixed because they
- could be declared latter. Note that a nested function name
- is not prefixed. */
- else if (flag_prefix_function_name)
- {
- size_t name_len = IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (decl));
- char *pname;
-
- pname = alloca (name_len + CHKR_PREFIX_SIZE + 1);
- memcpy (pname, CHKR_PREFIX, CHKR_PREFIX_SIZE);
- memcpy (pname + CHKR_PREFIX_SIZE, name, name_len + 1);
- new_name = pname;
- }
-
- if (name != new_name)
- {
- DECL_ASSEMBLER_NAME (decl) = get_identifier (new_name);
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- }
-
- DECL_RTL (decl)
- = gen_rtx_MEM (DECL_MODE (decl),
- gen_rtx_SYMBOL_REF (Pmode, name));
-
- /* Optionally set flags or add text to the name to record
- information such as that it is a function name. If the name
- is changed, the macro ASM_OUTPUT_LABELREF will have to know
- how to strip this information. */
-#ifdef ENCODE_SECTION_INFO
- ENCODE_SECTION_INFO (decl);
-#endif
-}
-
-
/* Given NAME, a putative register name, discard any customary prefixes. */
static const char *
return -1;
}
\f
-/* Create the DECL_RTL for a declaration for a static or external variable
- or static or external function.
- ASMSPEC, if not 0, is the string which the user specified
- as the assembler symbol name.
- TOP_LEVEL is nonzero if this is a file-scope variable.
+/* Create the DECL_RTL for a VAR_DECL or FUNCTION_DECL. DECL should
+ have static storage duration. In other words, it should not be an
+ automatic variable, including PARM_DECLs.
+
+ There is, however, one exception: this function handles variables
+ explicitly placed in a particular register by the user.
+
+ ASMSPEC, if not 0, is the string which the user specified as the
+ assembler symbol name.
This is never called for PARM_DECL nodes. */
void
-make_decl_rtl (decl, asmspec, top_level)
+make_decl_rtl (decl, asmspec)
tree decl;
const char *asmspec;
- int top_level;
{
+ int top_level = (DECL_CONTEXT (decl) == NULL_TREE);
const char *name = 0;
const char *new_name = 0;
int reg_number;
+ /* Check that we are not being given an automatic variable. */
+ /* A weak alias has TREE_PUBLIC set but not the other bits. */
+ if (TREE_CODE (decl) == PARM_DECL
+ || TREE_CODE (decl) == RESULT_DECL
+ || (TREE_CODE (decl) == VAR_DECL
+ && !TREE_STATIC (decl)
+ && !TREE_PUBLIC (decl)
+ && !DECL_EXTERNAL (decl)
+ && !DECL_REGISTER (decl)))
+ abort ();
+ /* And that we were not given a type or a label. */
+ else if (TREE_CODE (decl) == TYPE_DECL
+ || TREE_CODE (decl) == LABEL_DECL)
+ abort ();
+
/* For a duplicate declaration, we can be called twice on the
same DECL node. Don't discard the RTL already made. */
- if (DECL_RTL (decl) != 0)
+ if (DECL_RTL_SET_P (decl))
{
/* If the old RTL had the wrong mode, fix the mode. */
if (GET_MODE (DECL_RTL (decl)) != DECL_MODE (decl))
{
int nregs;
- if (DECL_INITIAL (decl) != 0 && top_level)
+ if (DECL_INITIAL (decl) != 0 && TREE_STATIC (decl))
{
DECL_INITIAL (decl) = 0;
error ("global register variable has initial value");
usage is somewhat suspect, we nevertheless use the following
kludge to avoid setting DECL_RTL to frame_pointer_rtx. */
- DECL_RTL (decl)
- = gen_rtx_REG (DECL_MODE (decl), FIRST_PSEUDO_REGISTER);
+ SET_DECL_RTL (decl,
+ gen_rtx_REG (DECL_MODE (decl),
+ FIRST_PSEUDO_REGISTER));
REGNO (DECL_RTL (decl)) = reg_number;
REG_USERVAR_P (DECL_RTL (decl)) = 1;
- if (top_level)
+ if (TREE_STATIC (decl))
{
/* Make this register global, so not usable for anything
else. */
Concatenate a distinguishing number. */
if (!top_level && !TREE_PUBLIC (decl)
&& ! (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
- && asmspec == 0)
+ && asmspec == 0
+ && name == IDENTIFIER_POINTER (DECL_NAME (decl)))
{
char *label;
ASM_FORMAT_PRIVATE_NAME (label, name, var_labelno);
if (name != new_name)
{
- DECL_ASSEMBLER_NAME (decl) = get_identifier (new_name);
+ SET_DECL_ASSEMBLER_NAME (decl, get_identifier (new_name));
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
}
&& (TREE_PUBLIC (decl) || TREE_STATIC (decl)))))
TREE_SIDE_EFFECTS (decl) = 1;
- DECL_RTL (decl) = gen_rtx_MEM (DECL_MODE (decl),
- gen_rtx_SYMBOL_REF (Pmode, name));
+ SET_DECL_RTL (decl, gen_rtx_MEM (DECL_MODE (decl),
+ gen_rtx_SYMBOL_REF (Pmode, name)));
+ SYMBOL_REF_WEAK (XEXP (DECL_RTL (decl), 0)) = DECL_WEAK (decl);
if (TREE_CODE (decl) != FUNCTION_DECL)
set_mem_attributes (DECL_RTL (decl), decl, 1);
last_assemble_variable_decl = 0;
- if (GET_CODE (DECL_RTL (decl)) == REG)
+ if (DECL_RTL_SET_P (decl) && GET_CODE (DECL_RTL (decl)) == REG)
{
/* Do output symbol info for global register variables, but do nothing
else for them. */
assemble_external (decl)
tree decl ATTRIBUTE_UNUSED;
{
+ /* Because most platforms do not define ASM_OUTPUT_EXTERNAL, the
+ main body of this code is only rarely exercised. To provide some
+ testing, on all platforms, we make sure that the ASM_OUT_FILE is
+ open. If it's not, we should not be calling this function. */
+ if (!asm_out_file)
+ abort ();
+
#ifdef ASM_OUTPUT_EXTERNAL
if (DECL_P (decl) && DECL_EXTERNAL (decl) && TREE_PUBLIC (decl))
{
abort ();
}
- set_float_handler (NULL_PTR);
+ set_float_handler (NULL);
}
\f
/* Here we combine duplicate floating constants to make
represented as a 64 bit value -1, and not as 0x00000000ffffffff.
The later confuses the sparc backend. */
- if (BITS_PER_WORD < HOST_BITS_PER_WIDE_INT && BITS_PER_WORD == width
+ if (width < HOST_BITS_PER_WIDE_INT
&& (i0 & ((HOST_WIDE_INT) 1 << (width - 1))))
i0 |= ((HOST_WIDE_INT) (-1) << width);
value->offset = offset;
}
\f
+enum kind { RTX_DOUBLE, RTX_INT };
struct rtx_const
{
-#ifdef ONLY_INT_FIELDS
- unsigned int kind : 16;
- unsigned int mode : 16;
-#else
- enum kind kind : 16;
- enum machine_mode mode : 16;
-#endif
+ ENUM_BITFIELD(kind) kind : 16;
+ ENUM_BITFIELD(machine_mode) mode : 16;
union {
union real_extract du;
struct addr_const addr;
default:
/* A language specific constant. Just hash the code. */
- return code % MAX_HASH_TABLE;
+ return (int) code % MAX_HASH_TABLE;
}
/* Compute hashing function */
f->varasm = NULL;
}
\f
-enum kind { RTX_DOUBLE, RTX_INT };
/* Express an rtx for a constant integer (perhaps symbolic)
as the sum of a symbol or label plus an explicit integer.
pool_offset += align - 1;
pool_offset &= ~ (align - 1);
+ if (GET_CODE (x) == LABEL_REF)
+ LABEL_PRESERVE_P (XEXP (x, 0)) = 1;
+
/* Allocate a pool constant descriptor, fill it in, and chain it in. */
pool = (struct pool_constant *) ggc_alloc (sizeof (struct pool_constant));
}
/* Look through the instructions for this function, and mark all the
- entries in the constant pool which are actually being used. */
+ entries in the constant pool which are actually being used.
+ Emit used deferred strings. */
static void
mark_constant_pool ()
insn = XEXP (insn, 1))
if (INSN_P (insn))
mark_constants (PATTERN (insn));
-
- /* It's possible that the only reference to a symbol is in a symbol
- that's in the constant pool. This happens in Fortran under some
- situations. (When the constant contains the address of another
- constant, and only the first is used directly in an insn.)
- This is potentially suboptimal if there's ever a possibility of
- backwards (in pool order) 2'd level references. However, it's
- not clear that 2'd level references can happen. */
- for (pool = first_pool; pool; pool = pool->next)
- {
- struct pool_constant *tem;
- const char *label;
-
- /* skip unmarked entries; no insn refers to them. */
- if (!pool->mark)
- continue;
-
- /* Skip everything except SYMBOL_REFs. */
- if (GET_CODE (pool->constant) != SYMBOL_REF)
- continue;
- label = XSTR (pool->constant, 0);
-
- /* Be sure the symbol's value is marked. */
- for (tem = const_rtx_sym_hash_table[SYMHASH (label)]; tem;
- tem = tem->next)
- if (tem->label == label)
- tem->mark = 1;
- /* If we didn't find it, there's something truly wrong here, but it
- will be announced by the assembler. */
- }
}
+/* Look through appropriate parts of X, marking all entries in the
+ constant pool which are actually being used. Entries that are only
+ referenced by other constants are also marked as used. Emit
+ deferred strings that are used. */
+
static void
mark_constants (x)
- register rtx x;
+ rtx x;
{
register int i;
register const char *format_ptr;
if (GET_CODE (x) == SYMBOL_REF)
{
- 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);
- }
- }
+ mark_constant (&x, NULL);
return;
}
/* Never search inside a CONST_DOUBLE, because CONST_DOUBLE_MEM may be
}
}
}
+
+/* Given a SYMBOL_REF CURRENT_RTX, mark it and all constants it refers
+ to as used. Emit referenced deferred strings. This function can
+ be used with for_each_rtx () to mark all SYMBOL_REFs in an rtx. */
+
+static int
+mark_constant (current_rtx, data)
+ rtx *current_rtx;
+ void *data ATTRIBUTE_UNUSED;
+{
+ rtx x = *current_rtx;
+
+ if (x == NULL_RTX)
+ return 0;
+ else if (GET_CODE(x) == CONST_DOUBLE)
+ /* Never search inside a CONST_DOUBLE because CONST_DOUBLE_MEM may
+ be a MEM but does not constitute a use of that MEM. */
+ return -1;
+ else if (GET_CODE (x) == SYMBOL_REF)
+ {
+ if (CONSTANT_POOL_ADDRESS_P (x))
+ {
+ struct pool_constant *pool = find_pool_constant (cfun, x);
+ if (pool->mark == 0) {
+ pool->mark = 1;
+ for_each_rtx (&(pool->constant), &mark_constant, NULL);
+ }
+ else
+ return -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 0;
+}
\f
/* Find all the constants whose addresses are referenced inside of EXP,
and make sure assembler code with a label has been output for each one.
directly. Give the front-end a chance to convert EXP to a
language-independent representation. */
if (lang_expand_constant)
- exp = (*lang_expand_constant) (exp);
+ {
+ exp = (*lang_expand_constant) (exp);
+ code = TREE_CODE (TREE_TYPE (exp));
+ }
if (size == 0 || flag_syntax_only)
return;
{
const char *name;
- make_decl_rtl (decl, (char *) 0, 1);
- name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
+ /* We must force creation of DECL_RTL for debug info generation, even though
+ we don't use it here. */
+ make_decl_rtl (decl, NULL);
+
+ name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
#ifdef ASM_OUTPUT_DEF
/* Make name accessible from other files, if appropriate. */
#endif
}
-/* This determines whether or not we support link-once semantics. */
-#ifndef SUPPORTS_ONE_ONLY
-#ifdef MAKE_DECL_ONE_ONLY
-#define SUPPORTS_ONE_ONLY 1
-#else
-#define SUPPORTS_ONE_ONLY 0
-#endif
-#endif
-
/* Returns 1 if the target configuration supports defining public symbols
so that one of them will be chosen at link time instead of generating a
multiply-defined symbol error, whether through the use of weak symbols or