/* Output variables, constants and external declarations, for GNU compiler.
- Copyright (C) 1987, 88, 89, 92-98, 1999 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.
#include "flags.h"
#include "function.h"
#include "expr.h"
-#include "output.h"
#include "hard-reg-set.h"
#include "regs.h"
#include "defaults.h"
+#include "output.h"
#include "real.h"
#include "toplev.h"
#include "dbxout.h"
extern FILE *asm_out_file;
/* The (assembler) name of the first globally-visible object output. */
-char *first_global_object_name;
-char *weak_global_object_name;
+const char *first_global_object_name;
+const char *weak_global_object_name;
extern struct obstack *current_obstack;
extern struct obstack *saveable_obstack;
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)
+#define const_rtx_hash_table (cfun->varasm->x_const_rtx_hash_table)
+#define const_rtx_sym_hash_table (cfun->varasm->x_const_rtx_sym_hash_table)
+#define first_pool (cfun->varasm->x_first_pool)
+#define last_pool (cfun->varasm->x_last_pool)
+#define pool_offset (cfun->varasm->x_pool_offset)
+#define const_double_chain (cfun->varasm->x_const_double_chain)
/* Number for making the label on the next
constant that is stored in memory. */
tree last_assemble_variable_decl;
-/* Nonzero if at least one function definition has been seen. */
-
-static int function_defined;
-
-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 const unsigned char *compare_constant_1 PARAMS ((tree, const unsigned 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 ((const 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;
const char *name;
int reloc ATTRIBUTE_UNUSED;
{
- if (decl != NULL_TREE
- && TREE_CODE_CLASS (TREE_CODE (decl)) != 'd')
+ if (decl != NULL_TREE && !DECL_P (decl))
abort ();
if (name == NULL)
name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
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);
make_function_rtl (decl)
tree decl;
{
- char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- char *new_name = name;
+ 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. */
+ /* 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;
-
- name = IDENTIFIER_POINTER (DECL_NAME (decl));
ASM_FORMAT_PRIVATE_NAME (label, name, var_labelno);
- name = ggc_alloc_string (label, -1);
var_labelno++;
+ new_name = label;
}
- else
+ /* 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)
{
- /* 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. */
- if (flag_prefix_function_name)
- {
- size_t name_len = strlen (name);
+ size_t name_len = IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (decl));
+ char *pname;
- new_name = ggc_alloc_string (NULL, name_len + CHKR_PREFIX_SIZE);
- memcpy (new_name, CHKR_PREFIX, CHKR_PREFIX_SIZE);
- memcpy (new_name + CHKR_PREFIX_SIZE, name, name_len + 1);
- name = new_name;
- }
+ 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 (DECL_RTL (decl) == 0)
+ if (name != new_name)
{
- DECL_RTL (decl)
- = gen_rtx_MEM (DECL_MODE (decl),
- gen_rtx_SYMBOL_REF (Pmode, 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. */
+ /* 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);
+ ENCODE_SECTION_INFO (decl);
#endif
- }
- else
- {
- /* ??? 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
- }
-
- /* Record at least one function has been defined. */
- function_defined = 1;
}
+
/* Given NAME, a putative register name, discard any customary prefixes. */
static const char *
static struct { const char *name; int number; } table[]
= ADDITIONAL_REGISTER_NAMES;
- for (i = 0; i < (int)(sizeof (table) / sizeof (table[0])); i++)
+ for (i = 0; i < (int) ARRAY_SIZE (table); i++)
if (! strcmp (asmspec, table[i].name))
return table[i].number;
}
const char *asmspec;
int top_level;
{
- register char *name = 0;
+ const char *name = 0;
+ const char *new_name = 0;
int reg_number;
- reg_number = decode_reg_name (asmspec);
-
- if (DECL_ASSEMBLER_NAME (decl) != NULL_TREE)
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
-
- if (reg_number == -2)
+ /* 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)
{
- /* ASMSPEC is given, and not the name of a register. */
- size_t len = strlen (asmspec);
+ /* If the old RTL had the wrong mode, fix the mode. */
+ if (GET_MODE (DECL_RTL (decl)) != DECL_MODE (decl))
+ {
+ rtx rtl = DECL_RTL (decl);
+ PUT_MODE (rtl, DECL_MODE (decl));
+ }
- name = ggc_alloc_string (NULL, len + 1);
- name[0] = '*';
- memcpy (&name[1], asmspec, len + 1);
+ /* ??? 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;
}
- /* 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)
+ new_name = name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+
+ reg_number = decode_reg_name (asmspec);
+ if (reg_number == -2)
+ /* ASMSPEC is given, and not the name of a register. */
+ new_name = asmspec;
+
+ if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl))
{
/* First detect errors in declaring global registers. */
- if (TREE_CODE (decl) != FUNCTION_DECL
- && DECL_REGISTER (decl) && reg_number == -1)
- error_with_decl (decl,
- "register name not specified for `%s'");
- else if (TREE_CODE (decl) != FUNCTION_DECL
- && DECL_REGISTER (decl) && reg_number < 0)
- error_with_decl (decl,
- "invalid register name for `%s'");
- else if ((reg_number >= 0 || reg_number == -3)
- && (TREE_CODE (decl) == FUNCTION_DECL
- && ! DECL_REGISTER (decl)))
- error_with_decl (decl,
- "register name given for non-register variable `%s'");
- else if (TREE_CODE (decl) != FUNCTION_DECL
- && DECL_REGISTER (decl)
- && TYPE_MODE (TREE_TYPE (decl)) == BLKmode)
+ if (reg_number == -1)
+ error_with_decl (decl, "register name not specified for `%s'");
+ else if (reg_number < 0)
+ error_with_decl (decl, "invalid register name for `%s'");
+ else if (TYPE_MODE (TREE_TYPE (decl)) == BLKmode)
error_with_decl (decl,
"data type of `%s' isn't suitable for a register");
- else if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl)
- && ! HARD_REGNO_MODE_OK (reg_number,
- TYPE_MODE (TREE_TYPE (decl))))
+ else if (! HARD_REGNO_MODE_OK (reg_number, TYPE_MODE (TREE_TYPE (decl))))
error_with_decl (decl,
- "register number for `%s' isn't suitable for data type");
+ "register specified for `%s' isn't suitable for data type");
/* Now handle properly declared static register variables. */
- else if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl))
+ else
{
int nregs;
DECL_INITIAL (decl) = 0;
error ("global register variable has initial value");
}
- if (fixed_regs[reg_number] == 0
- && function_defined && top_level)
- error ("global register variable follows a function definition");
if (TREE_THIS_VOLATILE (decl))
warning ("volatile register variables don't work as you might wish");
while (nregs > 0)
globalize_reg (reg_number + --nregs);
}
+
+ /* As a register variable, it has no section. */
+ return;
}
- /* Specifying a section attribute on a variable forces it into a
- non-.bss section, and thus it cannot be common. */
- else if (TREE_CODE (decl) == VAR_DECL
- && DECL_SECTION_NAME (decl) != NULL_TREE
- && DECL_INITIAL (decl) == NULL_TREE
- && DECL_COMMON (decl))
- DECL_COMMON (decl) = 0;
-
- /* Now handle ordinary static variables and functions (in memory).
- Also handle vars declared register invalidly. */
- 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.
- Concatenate a distinguishing number. */
- if (!top_level && !TREE_PUBLIC (decl) && asmspec == 0)
- {
- char *label;
+ }
- ASM_FORMAT_PRIVATE_NAME (label, name, var_labelno);
- name = ggc_alloc_string (label, -1);
- var_labelno++;
- }
+ /* Now handle ordinary static variables and functions (in memory).
+ Also handle vars declared register invalidly. */
- if (name == 0)
- abort ();
+ if (reg_number >= 0 || reg_number == -3)
+ error_with_decl (decl,
+ "register name given for non-register variable `%s'");
- /* When -fprefix-function-name is used, the functions
- names are prefixed. Only nested function names are not
- prefixed. */
- if (flag_prefix_function_name && TREE_CODE (decl) == FUNCTION_DECL)
- {
- size_t name_len = strlen (name);
- char *new_name;
+ /* Specifying a section attribute on a variable forces it into a
+ non-.bss section, and thus it cannot be common. */
+ if (TREE_CODE (decl) == VAR_DECL
+ && DECL_SECTION_NAME (decl) != NULL_TREE
+ && DECL_INITIAL (decl) == NULL_TREE
+ && DECL_COMMON (decl))
+ DECL_COMMON (decl) = 0;
+
+ /* Can't use just the variable's own name for a variable
+ 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)
+ && ! (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
+ && asmspec == 0)
+ {
+ char *label;
+ ASM_FORMAT_PRIVATE_NAME (label, name, var_labelno);
+ var_labelno++;
+ new_name = label;
+ }
- new_name = ggc_alloc_string (NULL, name_len + CHKR_PREFIX_SIZE);
- memcpy (new_name, CHKR_PREFIX, CHKR_PREFIX_SIZE);
- memcpy (new_name + CHKR_PREFIX_SIZE, name, name_len + 1);
- name = new_name;
- }
+ /* When -fprefix-function-name is used, the functions
+ names are prefixed. Only nested function names are not
+ prefixed. */
+ else if (flag_prefix_function_name && TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ size_t name_len = IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (decl));
+ char *pname;
- 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);
-
- /* If this variable is to be treated as volatile, show its
- tree node has side effects. If it has side effects, either
- because of this test or from TREE_THIS_VOLATILE also
- being set, show the MEM is volatile. */
- if (flag_volatile_global && TREE_CODE (decl) == VAR_DECL
- && TREE_PUBLIC (decl))
- TREE_SIDE_EFFECTS (decl) = 1;
- else if (flag_volatile_static && TREE_CODE (decl) == VAR_DECL
- && (TREE_PUBLIC (decl) || TREE_STATIC (decl)))
- TREE_SIDE_EFFECTS (decl) = 1;
-
- if (TREE_SIDE_EFFECTS (decl))
- MEM_VOLATILE_P (DECL_RTL (decl)) = 1;
-
- if (TREE_READONLY (decl))
- RTX_UNCHANGING_P (DECL_RTL (decl)) = 1;
- MEM_SET_IN_STRUCT_P (DECL_RTL (decl),
- AGGREGATE_TYPE_P (TREE_TYPE (decl)));
-
- /* 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
- }
+ 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;
}
- else
+
+ if (name != new_name)
{
- /* If the old RTL had the wrong mode, fix the mode. */
- if (GET_MODE (DECL_RTL (decl)) != DECL_MODE (decl))
- {
- rtx rtl = DECL_RTL (decl);
- PUT_MODE (rtl, DECL_MODE (decl));
- }
+ DECL_ASSEMBLER_NAME (decl) = get_identifier (new_name);
+ name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ }
- /* ??? 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);
+ /* If this variable is to be treated as volatile, show its
+ tree node has side effects. */
+ if ((flag_volatile_global && TREE_CODE (decl) == VAR_DECL
+ && TREE_PUBLIC (decl))
+ || ((flag_volatile_static && TREE_CODE (decl) == VAR_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));
+ if (TREE_CODE (decl) != FUNCTION_DECL)
+ set_mem_attributes (DECL_RTL (decl), decl, 1);
+
+ /* 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
- }
}
/* Make the rtl for variable VAR be volatile.
void
assemble_start_function (decl, fnname)
tree decl;
- char *fnname;
+ const char *fnname;
{
int align;
if (! first_global_object_name)
{
const char *p;
- char **name;
+ char *name;
+
+ STRIP_NAME_ENCODING (p, fnname);
+ name = permalloc (strlen (p) + 1);
+ strcpy (name, p);
if (! DECL_WEAK (decl) && ! DECL_ONE_ONLY (decl))
- name = &first_global_object_name;
+ first_global_object_name = name;
else
- name = &weak_global_object_name;
-
- STRIP_NAME_ENCODING (p, fnname);
- *name = permalloc (strlen (p) + 1);
- strcpy (*name, p);
+ weak_global_object_name = name;
}
#ifdef ASM_WEAKEN_LABEL
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, 0);
+#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;
enum in_section saved_in_section;
app_disable ();
- if (! dont_output_data)
+ if (! dont_output_data
+ && ! host_integerp (DECL_SIZE_UNIT (decl), 1))
{
- int size;
-
- if (TREE_CODE (DECL_SIZE (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_INT_CST_LOW (size_tree);
- if (TREE_INT_CST_HIGH (size_tree) != 0
- || size != TREE_INT_CST_LOW (size_tree))
- {
- error_with_decl (decl, "size of variable `%s' is too large");
- goto finish;
- }
+ 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
&& ! DECL_ONE_ONLY (decl))
{
const char *p;
+ char *xname;
STRIP_NAME_ENCODING (p, name);
- first_global_object_name = permalloc (strlen (p) + 1);
- strcpy (first_global_object_name, p);
+ xname = permalloc (strlen (p) + 1);
+ strcpy (xname, p);
+ first_global_object_name = xname;
}
/* Compute the alignment of this data. */
#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);
- int rounded = size;
+ unsigned HOST_WIDE_INT size = tree_low_cst (DECL_SIZE_UNIT (decl), 1);
+ unsigned HOST_WIDE_INT rounded = size;
/* Don't allocate zero bytes of common,
since that means "undefined external" in the linker. */
- if (size == 0) rounded = 1;
+ if (size == 0)
+ rounded = 1;
+
/* Round size up to multiple of BIGGEST_ALIGNMENT bits
so that each uninitialized object starts on such a boundary. */
rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1;
rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
* (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
-#if !defined(ASM_OUTPUT_ALIGNED_COMMON) && !defined(ASM_OUTPUT_ALIGNED_BSS)
- if ( (DECL_ALIGN (decl) / BITS_PER_UNIT) > rounded)
+/* Don't continue this line--convex cc version 4.1 would lose. */
+#if !defined(ASM_OUTPUT_ALIGNED_COMMON) && !defined(ASM_OUTPUT_ALIGNED_DECL_COMMON) && !defined(ASM_OUTPUT_ALIGNED_BSS)
+ if ((unsigned HOST_WIDE_INT) DECL_ALIGN (decl) / BITS_PER_UNIT > 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
{
if (DECL_INITIAL (decl))
/* Output the actual data. */
- output_constant (DECL_INITIAL (decl), TREE_INT_CST_LOW (size_tree));
+ output_constant (DECL_INITIAL (decl),
+ tree_low_cst (DECL_SIZE_UNIT (decl), 1));
else
/* Leave space for it. */
- assemble_zeros (TREE_INT_CST_LOW (size_tree));
+ assemble_zeros (tree_low_cst (DECL_SIZE_UNIT (decl), 1));
}
finish:
tree decl ATTRIBUTE_UNUSED;
{
#ifdef ASM_OUTPUT_EXTERNAL
- if (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd'
- && DECL_EXTERNAL (decl) && TREE_PUBLIC (decl))
+ if (DECL_P (decl) && DECL_EXTERNAL (decl) && TREE_PUBLIC (decl))
{
rtx rtl = DECL_RTL (decl);
/* Search the chain for an existing CONST_DOUBLE with the right value.
If one is found, return it. */
- if (current_function != 0)
+ if (cfun != 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)
push_obstacks_nochange ();
rtl_in_saveable_obstack ();
- r = gen_rtx_CONST_DOUBLE (mode, NULL_RTX, i0, i1);
+ r = gen_rtx_CONST_DOUBLE (mode, const0_rtx, i0, i1);
pop_obstacks ();
/* Don't touch const_double_chain if not inside any function. */
const_double_chain = r;
}
- /* Store const0_rtx in mem-slot since this CONST_DOUBLE is on the chain.
- Actual use of mem-slot is only through force_const_mem. */
-
- CONST_DOUBLE_MEM (r) = const0_rtx;
-
return r;
}
u.d = d;
- /* Detect special cases. */
-
- if (REAL_VALUES_IDENTICAL (dconst0, d))
+ /* Detect special cases. But be careful we don't use a CONST_DOUBLE
+ that's from a parent function since it may be in its constant pool. */
+ if (REAL_VALUES_IDENTICAL (dconst0, d)
+ && (cfun == 0 || decl_function_context (current_function_decl) == 0))
return CONST0_RTX (mode);
+
/* Check for NaN first, because some ports (specifically the i386) do not
emit correct ieee-fp code by default, and thus will generate a core
dump here if we pass a NaN to REAL_VALUES_EQUAL and if REAL_VALUES_EQUAL
does a floating point comparison. */
- else if (! REAL_VALUE_ISNAN (d) && REAL_VALUES_EQUAL (dconst1, d))
+ else if ((! REAL_VALUE_ISNAN (d) && REAL_VALUES_EQUAL (dconst1, d))
+ && (cfun == 0
+ || decl_function_context (current_function_decl) == 0))
return CONST1_RTX (mode);
if (sizeof u == sizeof (HOST_WIDE_INT))
/* Search the chain for an existing CONST_DOUBLE with the right value.
If one is found, return it. */
- if (current_function != 0)
+ if (cfun != 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)
PUT_MODE (r, mode);
bcopy ((char *) &u, (char *) &CONST_DOUBLE_LOW (r), sizeof u);
- /* Don't touch const_double_chain if not inside any function. */
+ /* If we aren't inside a function, don't put r on the
+ const_double_chain. */
if (current_function_decl != 0)
{
CONST_DOUBLE_CHAIN (r) = const_double_chain;
const_double_chain = r;
}
+ else
+ CONST_DOUBLE_CHAIN (r) = NULL_RTX;
/* Store const0_rtx in CONST_DOUBLE_MEM since this CONST_DOUBLE is on the
chain, but has not been allocated memory. Actual use of CONST_DOUBLE_MEM
while (1)
{
if (TREE_CODE (target) == COMPONENT_REF
- && (TREE_CODE (DECL_FIELD_BITPOS (TREE_OPERAND (target, 1)))
- == INTEGER_CST))
+ && host_integerp (byte_position (TREE_OPERAND (target, 1)), 0))
+
{
- offset += TREE_INT_CST_LOW (DECL_FIELD_BITPOS (TREE_OPERAND (target, 1))) / BITS_PER_UNIT;
+ offset += int_byte_position (TREE_OPERAND (target, 1));
target = TREE_OPERAND (target, 0);
}
else if (TREE_CODE (target) == ARRAY_REF)
{
- if (TREE_CODE (TREE_OPERAND (target, 1)) != INTEGER_CST
- || TREE_CODE (TYPE_SIZE (TREE_TYPE (target))) != INTEGER_CST)
- abort ();
- offset += ((TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (target)))
- * TREE_INT_CST_LOW (TREE_OPERAND (target, 1)))
- / BITS_PER_UNIT);
+ offset += (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (target)), 1)
+ * tree_low_cst (TREE_OPERAND (target, 1), 0));
target = TREE_OPERAND (target, 0);
}
else
struct constant_descriptor *next;
char *label;
rtx rtl;
- char contents[1];
+ unsigned char contents[1];
};
#define HASHBITS 30
while (desc)
{
- ggc_mark_string (desc->label);
+ ggc_mark_string ((const char *)desc->label);
ggc_mark_rtx (desc->rtl);
desc = desc->next;
}
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);
switch (code)
{
case INTEGER_CST:
- p = (char *) &TREE_INT_CST_LOW (exp);
- len = 2 * sizeof TREE_INT_CST_LOW (exp);
+ p = (char *) &TREE_INT_CST (exp);
+ len = sizeof TREE_INT_CST (exp);
break;
case REAL_CST:
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
return const_hash (TREE_OPERAND (exp, 0)) * 7 + 2;
default:
- abort ();
+ /* A language specific constant. Just hash the code. */
+ return code % MAX_HASH_TABLE;
}
/* Compute hashing function */
against a subdescriptor, and if it succeeds it returns the
address of the subdescriptor for the next operand. */
-static char *
+static const unsigned char *
compare_constant_1 (exp, p)
tree exp;
- char *p;
+ const unsigned char *p;
{
- register char *strp;
+ register const unsigned char *strp;
register int len;
register enum tree_code code = TREE_CODE (exp);
if (*p++ != TYPE_PRECISION (TREE_TYPE (exp)))
return 0;
- strp = (char *) &TREE_INT_CST_LOW (exp);
- len = 2 * sizeof TREE_INT_CST_LOW (exp);
+ strp = (unsigned char *) &TREE_INT_CST (exp);
+ len = sizeof TREE_INT_CST (exp);
break;
case REAL_CST:
if (*p++ != TYPE_PRECISION (TREE_TYPE (exp)))
return 0;
- strp = (char *) &TREE_REAL_CST (exp);
+ strp = (unsigned char *) &TREE_REAL_CST (exp);
len = sizeof TREE_REAL_CST (exp);
break;
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);
+ strp = (unsigned char *)TREE_STRING_POINTER (exp);
len = TREE_STRING_LENGTH (exp);
if (bcmp ((char *) &TREE_STRING_LENGTH (exp), p,
sizeof TREE_STRING_LENGTH (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, tmp, len);
+ strp = (unsigned char *) tmp;
if (bcmp ((char *) &xlen, p, sizeof xlen))
return 0;
struct addr_const value;
decode_addr_const (exp, &value);
- strp = (char *) &value.offset;
+ strp = (unsigned char *) &value.offset;
len = sizeof value.offset;
/* Compare the offset. */
while (--len >= 0)
return 0;
/* Compare symbol name. */
- strp = XSTR (value.base, 0);
- len = strlen (strp) + 1;
+ strp = (unsigned char *) XSTR (value.base, 0);
+ len = strlen ((char *) strp) + 1;
}
break;
return compare_constant_1 (TREE_OPERAND (exp, 0), p);
default:
- abort ();
+ if (lang_expand_constant)
+ {
+ exp = (*lang_expand_constant) (exp);
+ return compare_constant_1 (exp, p);
+ }
+ return 0;
}
/* Compare constant contents. */
record_constant_1 (exp)
tree exp;
{
- register char *strp;
+ register unsigned char *strp;
register int len;
register enum tree_code code = TREE_CODE (exp);
{
case INTEGER_CST:
obstack_1grow (&permanent_obstack, TYPE_PRECISION (TREE_TYPE (exp)));
- strp = (char *) &TREE_INT_CST_LOW (exp);
- len = 2 * sizeof TREE_INT_CST_LOW (exp);
+ strp = (unsigned char *) &TREE_INT_CST (exp);
+ len = sizeof TREE_INT_CST (exp);
break;
case REAL_CST:
obstack_1grow (&permanent_obstack, TYPE_PRECISION (TREE_TYPE (exp)));
- strp = (char *) &TREE_REAL_CST (exp);
+ strp = (unsigned char *) &TREE_REAL_CST (exp);
len = sizeof TREE_REAL_CST (exp);
break;
return;
obstack_1grow (&permanent_obstack, TYPE_MODE (TREE_TYPE (exp)));
- strp = TREE_STRING_POINTER (exp);
+ strp = (unsigned char *) TREE_STRING_POINTER (exp);
len = TREE_STRING_LENGTH (exp);
obstack_grow (&permanent_obstack, (char *) &TREE_STRING_LENGTH (exp),
sizeof TREE_STRING_LENGTH (exp));
/* Record the offset. */
obstack_grow (&permanent_obstack,
(char *) &value.offset, sizeof value.offset);
- /* Record the symbol name. */
- obstack_grow (&permanent_obstack, XSTR (value.base, 0),
- strlen (XSTR (value.base, 0)) + 1);
+
+ switch (GET_CODE (value.base))
+ {
+ case SYMBOL_REF:
+ /* Record the symbol name. */
+ obstack_grow (&permanent_obstack, XSTR (value.base, 0),
+ strlen (XSTR (value.base, 0)) + 1);
+ break;
+ case LABEL_REF:
+ /* Record the address of the CODE_LABEL. It may not have
+ been emitted yet, so it's UID may be zero. But pointer
+ identity is good enough. */
+ obstack_grow (&permanent_obstack, &XEXP (value.base, 0),
+ sizeof (rtx));
+ break;
+ default:
+ abort ();
+ }
}
return;
return;
default:
- abort ();
+ if (lang_expand_constant)
+ {
+ exp = (*lang_expand_constant) (exp);
+ record_constant_1 (exp);
+ }
+ return;
}
/* Record constant contents. */
= gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)),
gen_rtx_SYMBOL_REF (Pmode, desc->label));
- RTX_UNCHANGING_P (desc->rtl) = 1;
- if (AGGREGATE_TYPE_P (TREE_TYPE (exp)))
- MEM_SET_IN_STRUCT_P (desc->rtl, 1);
-
+ set_mem_attributes (desc->rtl, exp, 1);
pop_obstacks ();
found = 0;
case SYMBOL_REF:
/* Use the string's address, not the SYMBOL_REF's address,
for the sake of addresses of library routines. */
- value->un.addr.base = XSTR (value->un.addr.base, 0);
+ value->un.addr.base = (rtx) XSTR (value->un.addr.base, 0);
break;
case LABEL_REF:
/* We have a symbol name; construct the SYMBOL_REF and the MEM. */
def = gen_rtx_MEM (mode, gen_rtx_SYMBOL_REF (Pmode, found));
-
+ set_mem_attributes (def, type_for_mode (mode, 0), 1);
RTX_UNCHANGING_P (def) = 1;
+
/* Mark the symbol_ref as belonging to this constants pool. */
CONSTANT_POOL_ADDRESS_P (XEXP (def, 0)) = 1;
current_function_uses_const_pool = 1;
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)
+ for (sym = f->varasm->x_const_rtx_sym_hash_table[SYMHASH (label)]; sym;
+ sym = sym->next)
if (sym->label == label)
return sym->pool;
get_pool_constant (addr)
rtx addr;
{
- return (find_pool_constant (current_function, addr))->constant;
+ return (find_pool_constant (cfun, addr))->constant;
}
/* Likewise, but for the constant pool of a specific function. */
get_pool_mode (addr)
rtx addr;
{
- return (find_pool_constant (current_function, addr))->mode;
+ return (find_pool_constant (cfun, addr))->mode;
}
enum machine_mode
get_pool_offset (addr)
rtx addr;
{
- return (find_pool_constant (current_function, addr))->offset;
+ return (find_pool_constant (cfun, addr))->offset;
}
/* Return the size of the constant pool. */
for (pool = first_pool; pool; pool = pool->next)
{
+ rtx tmp;
+
x = pool->constant;
if (! pool->mark)
is eliminated by optimization. If so, write a constant of zero
instead. Note that this can also happen by turning the
CODE_LABEL into a NOTE. */
- if (((GET_CODE (x) == LABEL_REF
- && (INSN_DELETED_P (XEXP (x, 0))
- || GET_CODE (XEXP (x, 0)) == NOTE)))
- || (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF
- && (INSN_DELETED_P (XEXP (XEXP (XEXP (x, 0), 0), 0))
- || GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == NOTE)))
- x = const0_rtx;
+ /* ??? This seems completely and utterly wrong. Certainly it's
+ not true for NOTE_INSN_DELETED_LABEL, but I disbelieve proper
+ functioning even with INSN_DELETED_P and friends. */
+
+ tmp = x;
+ switch (GET_CODE (x))
+ {
+ case CONST:
+ if (GET_CODE (XEXP (x, 0)) != PLUS
+ || GET_CODE (XEXP (XEXP (x, 0), 0)) != LABEL_REF)
+ break;
+ tmp = XEXP (XEXP (x, 0), 0);
+ /* FALLTHRU */
+
+ case LABEL_REF:
+ tmp = XEXP (x, 0);
+ if (INSN_DELETED_P (tmp)
+ || (GET_CODE (tmp) == NOTE
+ && NOTE_LINE_NUMBER (tmp) == NOTE_INSN_DELETED))
+ {
+ abort ();
+ x = const0_rtx;
+ }
+ break;
+
+ default:
+ break;
+ }
/* First switch to correct section. */
#ifdef SELECT_RTX_SECTION
pool->mark = 0;
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ if (INSN_P (insn))
mark_constants (PATTERN (insn));
for (insn = current_function_epilogue_delay_list;
insn;
insn = XEXP (insn, 1))
- if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ if (INSN_P (insn))
mark_constants (PATTERN (insn));
/* It's possible that the only reference to a symbol is in a symbol
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)
if (GET_CODE (x) == SYMBOL_REF)
{
if (CONSTANT_POOL_ADDRESS_P (x))
- find_pool_constant (current_function, x)->mark = 1;
+ find_pool_constant (cfun, x)->mark = 1;
return;
}
/* Never search inside a CONST_DOUBLE, because CONST_DOUBLE_MEM may be
/* Insns may appear inside a SEQUENCE. Only check the patterns of
insns, not any notes that may be attached. We don't want to mark
a constant just because it happens to appear in a REG_EQUIV note. */
- if (GET_RTX_CLASS (GET_CODE (x)) == 'i')
+ if (INSN_P (x))
{
mark_constants (PATTERN (x));
return;
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:
return null_pointer_node;
case ADDR_EXPR:
- return TREE_OPERAND (value, 0);
+ return staticp (TREE_OPERAND (value, 0)) ? TREE_OPERAND (value, 0) : 0;
case NON_LVALUE_EXPR:
return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
/* 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. */
tree exp;
int size;
{
+ tree type = TREE_TYPE (exp);
register tree link, field = 0;
- HOST_WIDE_INT min_index = 0;
+ tree min_index = 0;
/* Number of bytes output or skipped so far.
In other words, current position within the constructor. */
- int total_bytes = 0;
+ HOST_WIDE_INT total_bytes = 0;
/* Non-zero means BYTE contains part of a byte, to be output. */
int byte_buffer_in_use = 0;
- register int byte;
+ register int byte = 0;
if (HOST_BITS_PER_WIDE_INT < BITS_PER_UNIT)
abort ();
- if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
- field = TYPE_FIELDS (TREE_TYPE (exp));
+ if (TREE_CODE (type) == RECORD_TYPE)
+ field = TYPE_FIELDS (type);
- if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE
- && TYPE_DOMAIN (TREE_TYPE (exp)) != 0)
- min_index
- = TREE_INT_CST_LOW (TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (exp))));
+ if (TREE_CODE (type) == ARRAY_TYPE
+ && TYPE_DOMAIN (type) != 0)
+ min_index = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
/* As LINK goes through the elements of the constant,
FIELD goes through the structure fields, if the constant is a structure.
tree val = TREE_VALUE (link);
tree index = 0;
- /* the element in a union constructor specifies the proper field. */
-
- if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
- || TREE_CODE (TREE_TYPE (exp)) == UNION_TYPE)
- {
- /* if available, use the type given by link */
- if (TREE_PURPOSE (link) != 0)
- field = TREE_PURPOSE (link);
- }
+ /* The element in a union constructor specifies the proper field
+ or index. */
+ if ((TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE
+ || TREE_CODE (type) == QUAL_UNION_TYPE)
+ && TREE_PURPOSE (link) != 0)
+ field = TREE_PURPOSE (link);
- if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
+ else if (TREE_CODE (type) == ARRAY_TYPE)
index = TREE_PURPOSE (link);
/* Eliminate the marker that makes a cast not be an lvalue. */
if (index && TREE_CODE (index) == RANGE_EXPR)
{
register int fieldsize
- = int_size_in_bytes (TREE_TYPE (TREE_TYPE (exp)));
- HOST_WIDE_INT lo_index = TREE_INT_CST_LOW (TREE_OPERAND (index, 0));
- HOST_WIDE_INT hi_index = TREE_INT_CST_LOW (TREE_OPERAND (index, 1));
+ = int_size_in_bytes (TREE_TYPE (type));
+ HOST_WIDE_INT lo_index = tree_low_cst (TREE_OPERAND (index, 0), 0);
+ HOST_WIDE_INT hi_index = tree_low_cst (TREE_OPERAND (index, 1), 0);
HOST_WIDE_INT index;
+
for (index = lo_index; index <= hi_index; index++)
{
/* Output the element's initial value. */
register int fieldsize;
/* Since this structure is static,
we know the positions are constant. */
- int bitpos = (field ? (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field))
- / BITS_PER_UNIT)
- : 0);
+ HOST_WIDE_INT pos = field ? int_byte_position (field) : 0;
+
if (index != 0)
- bitpos = (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (val)))
- / BITS_PER_UNIT
- * (TREE_INT_CST_LOW (index) - min_index));
+ pos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (val)), 1)
+ * (tree_low_cst (index, 0) - tree_low_cst (min_index, 0)));
/* Output any buffered-up bit-fields preceding this element. */
if (byte_buffer_in_use)
/* Advance to offset of this element.
Note no alignment needed in an array, since that is guaranteed
if each element has the proper size. */
- if ((field != 0 || index != 0) && bitpos != total_bytes)
+ if ((field != 0 || index != 0) && pos != total_bytes)
{
- assemble_zeros (bitpos - total_bytes);
- total_bytes = bitpos;
+ assemble_zeros (pos - total_bytes);
+ total_bytes = pos;
}
+ else if (field != 0 && DECL_PACKED (field))
+ /* Some assemblers automaticallly align a datum according to its
+ size if no align directive is specified. The datum, however,
+ may be declared with 'packed' attribute, so we have to disable
+ such a feature. */
+ ASM_OUTPUT_ALIGN (asm_out_file, 0);
+
/* Determine size this element should occupy. */
if (field)
- {
- if (TREE_CODE (DECL_SIZE (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_low_cst (DECL_SIZE_UNIT (field), 1);
else
- fieldsize = int_size_in_bytes (TREE_TYPE (TREE_TYPE (exp)));
+ fieldsize = int_size_in_bytes (TREE_TYPE (type));
/* Output the element's initial value. */
if (val == 0)
{
/* Element that is a bit-field. */
- int next_offset = TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field));
- int end_offset
- = (next_offset + TREE_INT_CST_LOW (DECL_SIZE (field)));
+ HOST_WIDE_INT next_offset = int_bit_position (field);
+ HOST_WIDE_INT end_offset
+ = (next_offset + tree_low_cst (DECL_SIZE (field), 1));
if (val == 0)
val = integer_zero_node;
int this_time;
int shift;
HOST_WIDE_INT value;
- int next_byte = next_offset / BITS_PER_UNIT;
- int next_bit = next_offset % BITS_PER_UNIT;
+ HOST_WIDE_INT next_byte = next_offset / BITS_PER_UNIT;
+ HOST_WIDE_INT next_bit = next_offset % BITS_PER_UNIT;
/* Advance from byte to byte
within this element when necessary. */
first (of the bits that are significant)
and put them into bytes from the most significant end. */
shift = end_offset - next_offset - this_time;
+
/* Don't try to take a bunch of bits that cross
the word boundary in the INTEGER_CST. We can
only select bits from the LOW or HIGH part
/* Now get the bits from the appropriate constant word. */
if (shift < HOST_BITS_PER_WIDE_INT)
- {
- value = TREE_INT_CST_LOW (val);
- }
+ value = TREE_INT_CST_LOW (val);
else if (shift < 2 * HOST_BITS_PER_WIDE_INT)
{
value = TREE_INT_CST_HIGH (val);
}
else
abort ();
+
/* Get the result. This works only when:
1 <= this_time <= HOST_BITS_PER_WIDE_INT. */
byte |= (((value >> shift)
take first the least significant bits of the value
and pack them starting at the least significant
bits of the bytes. */
- shift = (next_offset
- - TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field)));
+ shift = next_offset - int_bit_position (field);
+
/* Don't try to take a bunch of bits that cross
the word boundary in the INTEGER_CST. We can
only select bits from the LOW or HIGH part
not from both. */
if (shift < HOST_BITS_PER_WIDE_INT
&& shift + this_time > HOST_BITS_PER_WIDE_INT)
- {
- this_time = (HOST_BITS_PER_WIDE_INT - shift);
- }
+ this_time = (HOST_BITS_PER_WIDE_INT - shift);
/* Now get the bits from the appropriate constant word. */
if (shift < HOST_BITS_PER_WIDE_INT)
}
else
abort ();
+
/* Get the result. This works only when:
1 <= this_time <= HOST_BITS_PER_WIDE_INT. */
byte |= (((value >> shift)
& (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
<< next_bit);
}
+
next_offset += this_time;
byte_buffer_in_use = 1;
}
}
}
+
if (byte_buffer_in_use)
{
ASM_OUTPUT_BYTE (asm_out_file, byte);
total_bytes++;
}
+
if (total_bytes < size)
assemble_zeros (size - total_bytes);
}
int
add_weak (name, value)
- char *name;
- char *value;
+ const char *name;
+ const char *value;
{
struct weak_syms *weak;
#ifdef ASM_WEAKEN_LABEL
static void
remove_from_pending_weak_list (name)
- char *name ATTRIBUTE_UNUSED;
+ const char *name ATTRIBUTE_UNUSED;
{
#ifdef HANDLE_PRAGMA_WEAK
if (HANDLE_PRAGMA_WEAK)
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);
mark_const_hash_entry);
ggc_add_string_root (&in_named_name, 1);
}
+
+/* Extra support for EH values. */
+void
+assemble_eh_label (name)
+ const char *name;
+{
+#ifdef ASM_OUTPUT_EH_LABEL
+ ASM_OUTPUT_EH_LABEL (asm_out_file, name);
+#else
+ assemble_label (name);
+#endif
+}
+
+/* Assemble an alignment pseudo op for an ALIGN-bit boundary. */
+
+void
+assemble_eh_align (align)
+ int align;
+{
+#ifdef ASM_OUTPUT_EH_ALIGN
+ if (align > BITS_PER_UNIT)
+ ASM_OUTPUT_EH_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
+#else
+ assemble_align (align);
+#endif
+}
+
+
+/* On some platforms, we may want to specify a special mechansim to
+ output EH data when generating with a function.. */
+int
+assemble_eh_integer (x, size, force)
+ rtx x;
+ int size;
+ int force;
+{
+
+ switch (size)
+ {
+#ifdef ASM_OUTPUT_EH_CHAR
+ case 1:
+ ASM_OUTPUT_EH_CHAR (asm_out_file, x);
+ return 1;
+#endif
+
+#ifdef ASM_OUTPUT_EH_SHORT
+ case 2:
+ ASM_OUTPUT_EH_SHORT (asm_out_file, x);
+ return 1;
+#endif
+
+#ifdef ASM_OUTPUT_EH_INT
+ case 4:
+ ASM_OUTPUT_EH_INT (asm_out_file, x);
+ return 1;
+#endif
+
+#ifdef ASM_OUTPUT_EH_DOUBLE_INT
+ case 8:
+ ASM_OUTPUT_EH_DOUBLE_INT (asm_out_file, x);
+ return 1;
+#endif
+
+ default:
+ break;
+ }
+ return (assemble_integer (x, size, force));
+}
+
+
+