/* Output variables, constants and external declarations, for GNU compiler.
- Copyright (C) 1987, 88, 89, 92-7, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92-97, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
and are responsible for combining constants with the same value. */
#include "config.h"
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
+#include "system.h"
#include <setjmp.h>
/* #include <stab.h> */
#include "rtl.h"
#include "regs.h"
#include "defaults.h"
#include "real.h"
+#include "toplev.h"
+#include "dbxout.h"
+#include "sdbout.h"
#include "obstack.h"
#include "c-pragma.h"
#include "xcoffout.h"
#endif
-#include <ctype.h>
-
#ifndef TRAMPOLINE_ALIGNMENT
#define TRAMPOLINE_ALIGNMENT FUNCTION_BOUNDARY
#endif
/* The (assembler) name of the first globally-visible object output. */
char *first_global_object_name;
+char *weak_global_object_name;
extern struct obstack *current_obstack;
extern struct obstack *saveable_obstack;
tree last_assemble_variable_decl;
-
-#ifdef HANDLE_PRAGMA_WEAK
-/* Any weak symbol declarations waiting to be emitted. */
-
-struct weak_syms
-{
- struct weak_syms *next;
- char *name;
- char *value;
-};
-
-static struct weak_syms *weak_decls;
-#endif
-
/* Nonzero if at least one function definition has been seen. */
static int function_defined;
static int output_addressed_constants PROTO((tree));
static void output_after_function_constants PROTO((void));
static void output_constructor PROTO((tree, int));
+#ifdef ASM_OUTPUT_BSS
+static void asm_output_bss PROTO((FILE *, tree, 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));
+#endif
+#endif /* BSS_SECTION_ASM_OP */
\f
static enum in_section { no_section, in_text, in_data, in_named
#ifdef BSS_SECTION_ASM_OP
static struct { char *name; int number; } table[]
= ADDITIONAL_REGISTER_NAMES;
- for (i = 0; i < sizeof (table) / sizeof (table[0]); i++)
+ for (i = 0; i < (int)(sizeof (table) / sizeof (table[0])); i++)
if (! strcmp (asmspec, table[i].name))
return table[i].number;
}
same DECL node. Don't discard the RTL already made. */
if (DECL_RTL (decl) == 0)
{
- DECL_RTL (decl) = 0;
-
/* First detect errors in declaring global registers. */
if (TREE_CODE (decl) != FUNCTION_DECL
&& DECL_REGISTER (decl) && reg_number == -1)
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
if (TREE_PUBLIC (decl))
{
- if (!first_global_object_name && ! DECL_WEAK (decl)
- && ! DECL_ONE_ONLY (decl))
+ if (! first_global_object_name)
{
char *p;
+ char **name;
+
+ if (! DECL_WEAK (decl) && ! DECL_ONE_ONLY (decl))
+ name = &first_global_object_name;
+ else
+ name = &weak_global_object_name;
STRIP_NAME_ENCODING (p, fnname);
- first_global_object_name = permalloc (strlen (p) + 1);
- strcpy (first_global_object_name, p);
+ *name = permalloc (strlen (p) + 1);
+ strcpy (*name, p);
}
#ifdef ASM_WEAKEN_LABEL
void
assemble_variable (decl, top_level, at_end, dont_output_data)
tree decl;
- int top_level;
+ int top_level ATTRIBUTE_UNUSED;
int at_end;
int dont_output_data;
{
strcpy (first_global_object_name, p);
}
+ /* Compute the alignment of this data. */
+
+ align = DECL_ALIGN (decl);
+
+ /* In the case for initialing an array whose length isn't specified,
+ where we have not yet been able to do the layout,
+ figure out the proper alignment now. */
+ if (dont_output_data && DECL_SIZE (decl) == 0
+ && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
+ align = MAX (align, TYPE_ALIGN (TREE_TYPE (TREE_TYPE (decl))));
+
+ /* Some object file formats have a maximum alignment which they support.
+ In particular, a.out format supports a maximum alignment of 4. */
+#ifndef MAX_OFILE_ALIGNMENT
+#define MAX_OFILE_ALIGNMENT BIGGEST_ALIGNMENT
+#endif
+ if (align > MAX_OFILE_ALIGNMENT)
+ {
+ warning_with_decl (decl,
+ "alignment of `%s' is greater than maximum object file alignment. Using %d.",
+ MAX_OFILE_ALIGNMENT/BITS_PER_UNIT);
+ align = MAX_OFILE_ALIGNMENT;
+ }
+
+ /* On some machines, it is good to increase alignment sometimes. */
+#ifdef DATA_ALIGNMENT
+ align = DATA_ALIGNMENT (TREE_TYPE (decl), align);
+#endif
+#ifdef CONSTANT_ALIGNMENT
+ if (DECL_INITIAL (decl) != 0 && DECL_INITIAL (decl) != error_mark_node)
+ align = CONSTANT_ALIGNMENT (DECL_INITIAL (decl), align);
+#endif
+
+ /* Reset the alignment in case we have made it tighter, so we can benefit
+ from it in get_pointer_alignment. */
+ DECL_ALIGN (decl) = align;
+
/* Handle uninitialized definitions. */
if ((DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node)
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)
+ warning_with_decl
+ (decl, "requested alignment for %s is greater than implemented alignment of %d.",rounded);
+#endif
+
#ifdef DBX_DEBUGGING_INFO
/* File-scope global variables are output here. */
if (write_symbols == DBX_DEBUG && top_level)
reloc = output_addressed_constants (DECL_INITIAL (decl));
#ifdef ASM_OUTPUT_SECTION_NAME
- if (UNIQUE_SECTION_P (decl))
+ if ((flag_data_sections != 0
+ && DECL_SECTION_NAME (decl) == NULL_TREE)
+ || UNIQUE_SECTION_P (decl))
UNIQUE_SECTION (decl, reloc);
#endif
if (in_section != saved_in_section)
variable_section (decl, reloc);
- /* Compute and output the alignment of this data. */
-
- align = DECL_ALIGN (decl);
- /* In the case for initialing an array whose length isn't specified,
- where we have not yet been able to do the layout,
- figure out the proper alignment now. */
- if (dont_output_data && DECL_SIZE (decl) == 0
- && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
- align = MAX (align, TYPE_ALIGN (TREE_TYPE (TREE_TYPE (decl))));
-
- /* Some object file formats have a maximum alignment which they support.
- In particular, a.out format supports a maximum alignment of 4. */
-#ifndef MAX_OFILE_ALIGNMENT
-#define MAX_OFILE_ALIGNMENT BIGGEST_ALIGNMENT
-#endif
- if (align > MAX_OFILE_ALIGNMENT)
- {
- warning_with_decl (decl,
- "alignment of `%s' is greater than maximum object file alignment");
- align = MAX_OFILE_ALIGNMENT;
- }
-#ifdef DATA_ALIGNMENT
- /* On some machines, it is good to increase alignment sometimes. */
- align = DATA_ALIGNMENT (TREE_TYPE (decl), align);
-#endif
-#ifdef CONSTANT_ALIGNMENT
- if (DECL_INITIAL (decl))
- align = CONSTANT_ALIGNMENT (DECL_INITIAL (decl), align);
-#endif
-
- /* Reset the alignment in case we have made it tighter, so we can benefit
- from it in get_pointer_alignment. */
- DECL_ALIGN (decl) = align;
-
+ /* Output the alignment of this data. */
if (align > BITS_PER_UNIT)
- ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
+ ASM_OUTPUT_ALIGN (asm_out_file,
+ floor_log2 (DECL_ALIGN (decl) / BITS_PER_UNIT));
/* Do any machine/system dependent processing of the object. */
#ifdef ASM_DECLARE_OBJECT_NAME
void
assemble_external_libcall (fun)
- rtx fun;
+ rtx fun ATTRIBUTE_UNUSED;
{
#ifdef ASM_OUTPUT_EXTERNAL_LIBCALL
/* Declare library function name external when first used, if nec. */
char name[12];
char *namestring;
rtx x;
- /* Round size up to multiple of BIGGEST_ALIGNMENT bits
- so that each uninitialized object starts on such a boundary. */
- int rounded = ((size + (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1)
- / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
- * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
#if 0
if (flag_shared_data)
#ifdef ASM_OUTPUT_ALIGNED_LOCAL
ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size, BIGGEST_ALIGNMENT);
#else
- ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded);
+ {
+ /* Round size up to multiple of BIGGEST_ALIGNMENT bits
+ so that each uninitialized object starts on such a boundary. */
+ int rounded = ((size + (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1)
+ / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
+ * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
+ ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded);
+ }
#endif
#endif
return x;
else if (! REAL_VALUE_ISNAN (d) && REAL_VALUES_EQUAL (dconst1, d))
return CONST1_RTX (mode);
+ if (sizeof u == sizeof (HOST_WIDE_INT))
+ return immed_double_const (u.i[0], 0, mode);
if (sizeof u == 2 * sizeof (HOST_WIDE_INT))
return immed_double_const (u.i[0], u.i[1], mode);
register tree link;
int length = list_length (CONSTRUCTOR_ELTS (exp));
tree type;
+ int have_purpose = 0;
+
+ for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
+ if (TREE_PURPOSE (link))
+ have_purpose = 1;
if (bcmp ((char *) &length, p, sizeof length))
return 0;
p += sizeof length;
/* For record constructors, insist that the types match.
- For arrays, just verify both constructors are for arrays. */
+ For arrays, just verify both constructors are for arrays.
+ Then insist that either both or none have any TREE_PURPOSE
+ values. */
if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
type = TREE_TYPE (exp);
else
p += sizeof type;
+ if (bcmp ((char *) &have_purpose, p, sizeof have_purpose))
+ return 0;
+
+ p += sizeof have_purpose;
+
/* For arrays, insist that the size in bytes match. */
if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
{
- int size = int_size_in_bytes (TREE_TYPE (exp));
+ HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
+
if (bcmp ((char *) &size, p, sizeof size))
return 0;
p += sizeof zero;
}
+
+ if (TREE_PURPOSE (link)
+ && TREE_CODE (TREE_PURPOSE (link)) == FIELD_DECL)
+ {
+ if (bcmp ((char *) &TREE_PURPOSE (link), p,
+ sizeof TREE_PURPOSE (link)))
+ return 0;
+
+ p += sizeof TREE_PURPOSE (link);
+ }
+ else if (TREE_PURPOSE (link))
+ {
+ if ((p = compare_constant_1 (TREE_PURPOSE (link), p)) == 0)
+ return 0;
+ }
+ else if (have_purpose)
+ {
+ int zero = 0;
+
+ if (bcmp ((char *) &zero, p, sizeof zero))
+ return 0;
+
+ p += sizeof zero;
+ }
}
return p;
case PLUS_EXPR:
case MINUS_EXPR:
+ case RANGE_EXPR:
p = compare_constant_1 (TREE_OPERAND (exp, 0), p);
if (p == 0)
return 0;
register tree link;
int length = list_length (CONSTRUCTOR_ELTS (exp));
tree type;
+ int have_purpose = 0;
+
+ for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
+ if (TREE_PURPOSE (link))
+ have_purpose = 1;
obstack_grow (&permanent_obstack, (char *) &length, sizeof length);
/* For record constructors, insist that the types match.
- For arrays, just verify both constructors are for arrays. */
+ For arrays, just verify both constructors are for arrays.
+ Then insist that either both or none have any TREE_PURPOSE
+ values. */
if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
type = TREE_TYPE (exp);
else
type = 0;
obstack_grow (&permanent_obstack, (char *) &type, sizeof type);
+ obstack_grow (&permanent_obstack, (char *) &have_purpose,
+ sizeof have_purpose);
/* For arrays, insist that the size in bytes match. */
if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
{
- int size = int_size_in_bytes (TREE_TYPE (exp));
+ HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
obstack_grow (&permanent_obstack, (char *) &size, sizeof size);
}
obstack_grow (&permanent_obstack,
(char *) &zero, sizeof zero);
}
+
+ if (TREE_PURPOSE (link)
+ && TREE_CODE (TREE_PURPOSE (link)) == FIELD_DECL)
+ obstack_grow (&permanent_obstack,
+ (char *) &TREE_PURPOSE (link),
+ sizeof TREE_PURPOSE (link));
+ else if (TREE_PURPOSE (link))
+ record_constant_1 (TREE_PURPOSE (link));
+ else if (have_purpose)
+ {
+ int zero = 0;
+
+ obstack_grow (&permanent_obstack,
+ (char *) &zero, sizeof zero);
+ }
}
}
return;
case PLUS_EXPR:
case MINUS_EXPR:
+ case RANGE_EXPR:
record_constant_1 (TREE_OPERAND (exp, 0));
record_constant_1 (TREE_OPERAND (exp, 1));
return;
align = (mode == VOIDmode) ? UNITS_PER_WORD : GET_MODE_SIZE (mode);
if (align > BIGGEST_ALIGNMENT / BITS_PER_UNIT)
align = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
+#ifdef CONSTANT_ALIGNMENT
+ align = CONSTANT_ALIGNMENT (make_tree (type_for_mode (mode, 0), x),
+ align * BITS_PER_UNIT) / BITS_PER_UNIT;
+#endif
pool_offset += align - 1;
pool_offset &= ~ (align - 1);
void
output_constant_pool (fnname, fndecl)
- char *fnname;
- tree fndecl;
+ char *fnname ATTRIBUTE_UNUSED;
+ tree fndecl ATTRIBUTE_UNUSED;
{
struct pool_constant *pool;
rtx x;
assemble_zeros (size - total_bytes);
}
-/* Output asm to handle ``#pragma weak'' */
-
-void
-handle_pragma_weak (what, name, value)
- enum pragma_state what;
- char *name, *value;
-{
-#ifdef HANDLE_PRAGMA_WEAK
- if (what == ps_name || what == ps_value)
- {
- struct weak_syms *weak =
- (struct weak_syms *)permalloc (sizeof (struct weak_syms));
- weak->next = weak_decls;
- weak->name = permalloc (strlen (name) + 1);
- strcpy (weak->name, name);
-
- if (what != ps_value)
- weak->value = NULL_PTR;
-
- else
- {
- weak->value = permalloc (strlen (value) + 1);
- strcpy (weak->value, value);
- }
-
- weak_decls = weak;
- }
- else if (! (what == ps_done || what == ps_start))
- warning ("malformed `#pragma weak'");
-#endif /* HANDLE_PRAGMA_WEAK */
-}
-
/* Declare DECL to be a weak symbol. */
void
/* Emit any pending weak declarations. */
+#ifdef HANDLE_PRAGMA_WEAK
+struct weak_syms * weak_decls;
+#endif
+
void
weak_finish ()
{