/* Output variables, constants and external declarations, for GNU compiler.
- Copyright (C) 1987, 88, 89, 92-99, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
+ 1998, 1999, 2000 Free Software Foundation, Inc.
This file is part of GNU CC.
tree last_assemble_variable_decl;
-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 *));
-static int const_hash PROTO((tree));
-static int compare_constant PROTO((tree,
+static const char *strip_reg_name PARAMS ((const char *));
+static int contains_pointers_p PARAMS ((tree));
+static void decode_addr_const PARAMS ((tree, struct addr_const *));
+static int const_hash PARAMS ((tree));
+static int compare_constant PARAMS ((tree,
struct constant_descriptor *));
-static char *compare_constant_1 PROTO((tree, char *));
-static struct constant_descriptor *record_constant PROTO((tree));
-static void record_constant_1 PROTO((tree));
-static tree copy_constant PROTO((tree));
-static void output_constant_def_contents PROTO((tree, int, int));
-static void decode_rtx_const PROTO((enum machine_mode, rtx,
+static char *compare_constant_1 PARAMS ((tree, char *));
+static struct constant_descriptor *record_constant PARAMS ((tree));
+static void record_constant_1 PARAMS ((tree));
+static tree copy_constant PARAMS ((tree));
+static void output_constant_def_contents PARAMS ((tree, int, int));
+static void decode_rtx_const PARAMS ((enum machine_mode, rtx,
struct rtx_const *));
-static int const_hash_rtx PROTO((enum machine_mode, rtx));
-static int compare_constant_rtx PROTO((enum machine_mode, rtx,
+static int const_hash_rtx PARAMS ((enum machine_mode, rtx));
+static int compare_constant_rtx PARAMS ((enum machine_mode, rtx,
struct constant_descriptor *));
-static struct constant_descriptor *record_constant_rtx PROTO((enum machine_mode,
+static struct constant_descriptor *record_constant_rtx PARAMS ((enum machine_mode,
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));
-static void output_after_function_constants PROTO((void));
-static void output_constructor PROTO((tree, int));
+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 output_addressed_constants PARAMS ((tree));
+static void output_after_function_constants PARAMS ((void));
+static void output_constructor PARAMS ((tree, int));
#ifdef ASM_WEAKEN_LABEL
-static void remove_from_pending_weak_list PROTO ((char *));
+static void remove_from_pending_weak_list PARAMS ((char *));
#endif
#ifdef ASM_OUTPUT_BSS
-static void asm_output_bss PROTO((FILE *, tree, char *, int, int));
+static void asm_output_bss PARAMS ((FILE *, tree, const char *, int, int));
#endif
#ifdef BSS_SECTION_ASM_OP
#ifdef ASM_OUTPUT_ALIGNED_BSS
-static void asm_output_aligned_bss PROTO((FILE *, tree, char *, int, int));
+static void asm_output_aligned_bss PARAMS ((FILE *, tree, const char *,
+ int, int));
#endif
#endif /* BSS_SECTION_ASM_OP */
-static void mark_pool_constant PROTO((struct pool_constant *));
-static void mark_pool_sym_hash_table PROTO((struct pool_sym **));
-static void mark_const_hash_entry PROTO((void *));
-static void asm_emit_uninitialised PROTO((tree, char *, int, int));
+static void mark_pool_constant PARAMS ((struct pool_constant *));
+static void mark_pool_sym_hash_table PARAMS ((struct pool_sym **));
+static void mark_const_hash_entry PARAMS ((void *));
+static void asm_emit_uninitialised PARAMS ((tree, const char*, int, int));
\f
static enum in_section { no_section, in_text, in_data, in_named
#ifdef BSS_SECTION_ASM_OP
} in_section = no_section;
/* Return a non-zero value if DECL has a section attribute. */
+#ifndef IN_NAMED_SECTION
#define IN_NAMED_SECTION(DECL) \
((TREE_CODE (DECL) == FUNCTION_DECL || TREE_CODE (DECL) == VAR_DECL) \
&& DECL_SECTION_NAME (DECL) != NULL_TREE)
-
+#endif
+
/* Text of section name when in_section == in_named. */
static char *in_named_name;
static void
asm_output_bss (file, decl, name, size, rounded)
FILE *file;
- tree decl;
- char *name;
- int size, rounded;
+ tree decl ATTRIBUTE_UNUSED;
+ const char *name;
+ int size ATTRIBUTE_UNUSED, rounded;
{
ASM_GLOBALIZE_LABEL (file, name);
bss_section ();
asm_output_aligned_bss (file, decl, name, size, align)
FILE *file;
tree decl;
- char *name;
+ const char *name;
int size, align;
{
ASM_GLOBALIZE_LABEL (file, name);
char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
char *new_name = name;
- /* Rename a nested function to avoid conflicts. */
+ /* 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)
{
if (DECL_RTL (decl) == 0)
{
+ DECL_ASSEMBLER_NAME (decl) = get_identifier (name);
DECL_RTL (decl)
= gen_rtx_MEM (DECL_MODE (decl),
gen_rtx_SYMBOL_REF (Pmode, name));
if (DECL_RTL (decl) == 0)
{
/* Can't use just the variable's own name for a variable
- whose scope is less than the whole file.
+ whose scope is less than the whole file, unless it's a member
+ of a local class (which will already be unambiguous).
Concatenate a distinguishing number. */
- if (!top_level && !TREE_PUBLIC (decl) && asmspec == 0)
+ if (!top_level && !TREE_PUBLIC (decl)
+ && ! (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
+ && asmspec == 0)
{
char *label;
name = new_name;
}
+ DECL_ASSEMBLER_NAME (decl)
+ = get_identifier (name[0] == '*' ? name + 1 : name);
DECL_RTL (decl) = gen_rtx_MEM (DECL_MODE (decl),
gen_rtx_SYMBOL_REF (Pmode, name));
MEM_ALIAS_SET (DECL_RTL (decl)) = get_alias_set (decl);
void
assemble_start_function (decl, fnname)
tree decl;
- char *fnname;
+ const char *fnname;
{
int align;
static void
asm_emit_uninitialised (decl, name, size, rounded)
tree decl;
- char * name;
- int size;
+ const char * name;
+ int size ATTRIBUTE_UNUSED;
int rounded ATTRIBUTE_UNUSED;
{
- enum {
+ enum
+ {
asm_dest_common,
asm_dest_bss,
asm_dest_local
}
}
+#ifdef ASM_OUTPUT_SECTION_NAME
+ /* We already know that DECL_SECTION_NAME() == NULL. */
+ if (flag_data_sections != 0 || UNIQUE_SECTION_P (decl))
+ UNIQUE_SECTION (decl, NULL);
+#endif
+
switch (destination)
{
#ifdef ASM_EMIT_BSS
int at_end ATTRIBUTE_UNUSED;
int dont_output_data;
{
- register char *name;
+ register const char *name;
unsigned int align;
tree size_tree = NULL_TREE;
int reloc = 0;
if (! dont_output_data)
{
- int size;
+ unsigned int size;
- if (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
+ if (TREE_CODE (DECL_SIZE_UNIT (decl)) != INTEGER_CST)
goto finish;
- /* This is better than explicit arithmetic, since it avoids overflow. */
- size_tree = size_binop (CEIL_DIV_EXPR,
- DECL_SIZE (decl), size_int (BITS_PER_UNIT));
-
+ size_tree = DECL_SIZE_UNIT (decl);
size = TREE_INT_CST_LOW (size_tree);
- if (TREE_INT_CST_HIGH (size_tree) != 0
- || size != TREE_INT_CST_LOW (size_tree))
+
+ if (compare_tree_int (size_tree, size) != 0)
{
error_with_decl (decl, "size of variable `%s' is too large");
goto finish;
}
name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
-
if (TREE_PUBLIC (decl) && DECL_NAME (decl)
&& ! first_global_object_name
&& ! (DECL_COMMON (decl) && (DECL_INITIAL (decl) == 0
#if ! defined ASM_EMIT_BSS
&& DECL_COMMON (decl)
#endif
- && DECL_SECTION_NAME (decl) == 0
+ && DECL_SECTION_NAME (decl) == NULL_TREE
&& ! dont_output_data)
{
int size = TREE_INT_CST_LOW (size_tree);
* (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
#if !defined(ASM_OUTPUT_ALIGNED_COMMON) && !defined(ASM_OUTPUT_ALIGNED_BSS)
- if ( (DECL_ALIGN (decl) / BITS_PER_UNIT) > rounded)
+ if ((DECL_ALIGN (decl) / BITS_PER_UNIT) > (unsigned int) rounded)
warning_with_decl
(decl, "requested alignment for %s is greater than implemented alignment of %d.",rounded);
#endif
reloc = output_addressed_constants (DECL_INITIAL (decl));
#ifdef ASM_OUTPUT_SECTION_NAME
- if ((flag_data_sections != 0
- && DECL_SECTION_NAME (decl) == NULL_TREE)
+ if ((flag_data_sections != 0 && DECL_SECTION_NAME (decl) == NULL_TREE)
|| UNIQUE_SECTION_P (decl))
UNIQUE_SECTION (decl, reloc);
#endif
const_hash (exp)
tree exp;
{
- register char *p;
+ register const char *p;
register int len, hi, i;
register enum tree_code code = TREE_CODE (exp);
case CONSTRUCTOR:
if (TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)
{
+ char *tmp;
+
len = int_size_in_bytes (TREE_TYPE (exp));
- p = (char *) alloca (len);
- get_set_constructor_bytes (exp, (unsigned char *) p, len);
+ tmp = (char *) alloca (len);
+ get_set_constructor_bytes (exp, (unsigned char *) tmp, len);
+ p = tmp;
break;
}
else
tree exp;
char *p;
{
- register char *strp;
+ register const char *strp;
register int len;
register enum tree_code code = TREE_CODE (exp);
if (flag_writable_strings)
return 0;
- if (*p++ != TYPE_MODE (TREE_TYPE (exp)))
+ if ((enum machine_mode) *p++ != TYPE_MODE (TREE_TYPE (exp)))
return 0;
strp = TREE_STRING_POINTER (exp);
if (TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)
{
int xlen = len = int_size_in_bytes (TREE_TYPE (exp));
+ unsigned char *tmp = (unsigned char *) alloca (len);
- strp = (char *) alloca (len);
- get_set_constructor_bytes (exp, (unsigned char *) strp, len);
+ get_set_constructor_bytes (exp, (unsigned char *) tmp, len);
+ strp = tmp;
if (bcmp ((char *) &xlen, p, sizeof xlen))
return 0;
rtx addr;
{
struct pool_sym *sym;
- char *label = XSTR (addr, 0);
+ const char *label = XSTR (addr, 0);
for (sym = f->varasm->x_const_rtx_sym_hash_table[SYMHASH (label)]; sym; sym = sym->next)
if (sym->label == label)
for (pool = first_pool; pool; pool = pool->next)
{
struct pool_sym *sym;
- char *label;
+ const char *label;
/* skip unmarked entries; no insn refers to them. */
if (!pool->mark)
tree value;
tree endtype;
{
+ /* Give the front-end a chance to convert VALUE to something that
+ looks more like a constant to the back-end. */
+ if (lang_expand_constant)
+ value = (*lang_expand_constant) (value);
+
switch (TREE_CODE (value))
{
case CONSTRUCTOR:
/* Eliminate the NON_LVALUE_EXPR_EXPR that makes a cast not be an lvalue.
That way we get the constant (we hope) inside it. Also, strip off any
- NOP_EXPR that converts between two record, union, array, or set types. */
+ NOP_EXPR that converts between two record, union, array, or set types
+ or a CONVERT_EXPR that converts to a union TYPE. */
while ((TREE_CODE (exp) == NOP_EXPR
&& (TREE_TYPE (exp) == TREE_TYPE (TREE_OPERAND (exp, 0))
|| AGGREGATE_TYPE_P (TREE_TYPE (exp))))
+ || (TREE_CODE (exp) == CONVERT_EXPR
+ && code == UNION_TYPE)
|| TREE_CODE (exp) == NON_LVALUE_EXPR)
- exp = TREE_OPERAND (exp, 0);
+ {
+ exp = TREE_OPERAND (exp, 0);
+ code = TREE_CODE (TREE_TYPE (exp));
+ }
/* Allow a constructor with no elements for any data type.
This means to fill the space with zeros. */
/* Determine size this element should occupy. */
if (field)
{
- if (TREE_CODE (DECL_SIZE (field)) != INTEGER_CST)
+ if (TREE_CODE (DECL_SIZE_UNIT (field)) != INTEGER_CST)
abort ();
- if (TREE_INT_CST_LOW (DECL_SIZE (field)) > 100000)
- {
- /* This avoids overflow trouble. */
- tree size_tree = size_binop (CEIL_DIV_EXPR,
- DECL_SIZE (field),
- size_int (BITS_PER_UNIT));
- fieldsize = TREE_INT_CST_LOW (size_tree);
- }
- else
- {
- fieldsize = TREE_INT_CST_LOW (DECL_SIZE (field));
- fieldsize = (fieldsize + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
- }
+
+ fieldsize = TREE_INT_CST_LOW (DECL_SIZE_UNIT (field));
}
else
fieldsize = int_size_in_bytes (TREE_TYPE (TREE_TYPE (exp)));
assemble_alias (decl, target)
tree decl, target ATTRIBUTE_UNUSED;
{
- char *name;
+ const char *name;
make_decl_rtl (decl, (char *) 0, 1);
name = XSTR (XEXP (DECL_RTL (decl), 0), 0);