#include "expr.h"
#include "hard-reg-set.h"
#include "regs.h"
+#include "defaults.h"
+#include "real.h"
#include "obstack.h"
#ifdef XCOFF_DEBUGGING_INFO
-#include "xcoff.h"
+#include "xcoffout.h"
#endif
#ifndef ASM_STABS_OP
extern struct obstack *saveable_obstack;
extern struct obstack permanent_obstack;
#define obstack_chunk_alloc xmalloc
-extern int xmalloc ();
/* Number for making the label on the next
constant that is stored in memory. */
int output_addressed_constants ();
void output_constant ();
void output_constructor ();
+void text_section ();
+void readonly_data_section ();
+void data_section ();
\f
#ifdef EXTRA_SECTIONS
static enum in_section {no_section, in_text, in_data, EXTRA_SECTIONS} in_section
}
}
-/* Tell assembler to switch to read-only data section. This is normally
- the text section. */
-
-void
-readonly_data_section ()
-{
-#ifdef READONLY_DATA_SECTION
- READONLY_DATA_SECTION ();
-#else
- text_section ();
-#endif
-}
-
/* Tell assembler to switch to data section. */
void
}
}
+/* Tell assembler to switch to read-only data section. This is normally
+ the text section. */
+
+void
+readonly_data_section ()
+{
+#ifdef READONLY_DATA_SECTION
+ READONLY_DATA_SECTION (); /* Note this can call data_section. */
+#else
+ text_section ();
+#endif
+}
+
/* Determine if we're in the text section. */
int
name++;
return name;
}
-
+\f
/* Decode an `asm' spec for a declaration as a register name.
Return the register number, or -1 if nothing specified,
- or -2 if the name is not a register. Accept an exact spelling or
- a decimal number. Prefixes such as % are optional. */
+ or -2 if the ASMSPEC is not `cc' or `memory' and is not recognized,
+ or -3 if ASMSPEC is `cc' and is not recognized,
+ or -4 if ASMSPEC is `memory' and is not recognized.
+ Accept an exact spelling or a decimal number.
+ Prefixes such as % are optional. */
int
decode_reg_name (asmspec)
}
#endif /* ADDITIONAL_REGISTER_NAMES */
+ if (!strcmp (asmspec, "memory"))
+ return -4;
+
+ if (!strcmp (asmspec, "cc"))
+ return -3;
+
return -2;
}
DECL_RTL (decl) = 0;
/* First detect errors in declaring global registers. */
- if (TREE_REGDECL (decl) && reg_number == -1)
+ if (DECL_REGISTER (decl) && reg_number == -1)
error_with_decl (decl,
"register name not specified for `%s'");
- else if (TREE_REGDECL (decl) && reg_number == -2)
+ else if (DECL_REGISTER (decl) && reg_number < 0)
error_with_decl (decl,
"invalid register name for `%s'");
- else if (reg_number >= 0 && ! TREE_REGDECL (decl))
+ else if ((reg_number >= 0 || reg_number == -3) && ! DECL_REGISTER (decl))
error_with_decl (decl,
"register name given for non-register variable `%s'");
- else if (TREE_REGDECL (decl) && TREE_CODE (decl) == FUNCTION_DECL)
+ else if (DECL_REGISTER (decl) && TREE_CODE (decl) == FUNCTION_DECL)
error ("function declared `register'");
- else if (TREE_REGDECL (decl) && TYPE_MODE (TREE_TYPE (decl)) == BLKmode)
+ else if (DECL_REGISTER (decl) && TYPE_MODE (TREE_TYPE (decl)) == BLKmode)
error_with_decl (decl, "data type of `%s' isn't suitable for a register");
/* Now handle properly declared static register variables. */
- else if (TREE_REGDECL (decl))
+ else if (DECL_REGISTER (decl))
{
int nregs;
#if 0 /* yylex should print the warning for this */
/* 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_EXTERNAL (decl) && asmspec == 0)
+ if (!top_level && !DECL_EXTERNAL (decl) && asmspec == 0)
{
char *label;
}
}
}
+
+/* Make the rtl for variable VAR be volatile.
+ Use this only for static variables. */
+
+make_var_volatile (var)
+ tree var;
+{
+ if (GET_CODE (DECL_RTL (var)) != MEM)
+ abort ();
+
+ MEM_VOLATILE_P (DECL_RTL (var)) = 1;
+}
\f
/* Output a string of literal assembler code
for an `asm' keyword used between functions. */
fprintf (asm_out_file, "\t%s\n", TREE_STRING_POINTER (string));
}
-/* Tiemann: please get rid of this conditional and put appropriate
- definitions in each of the files that should have them.
- The type of debugging format is not the right parameter to
- control how some other aspect of assembler output is done. */
-
+#if 0 /* This should no longer be needed, because
+ flag_gnu_linker should be 0 on these systems,
+ which should prevent any output
+ if ASM_OUTPUT_CONSTRUCTOR and ASM_OUTPUT_DESTRUCTOR are absent. */
#if !(defined(DBX_DEBUGGING_INFO) && !defined(FASCIST_ASSEMBLER))
#ifndef ASM_OUTPUT_CONSTRUCTOR
#define ASM_OUTPUT_CONSTRUCTOR(file, name)
#define ASM_OUTPUT_DESTRUCTOR(file, name)
#endif
#endif
+#endif /* 0 */
/* Record an element in the table of global destructors.
How this is done depends on what sort of assembler and linker
if (thissize > maximum)
thissize = maximum;
-#ifdef ASM_OUTPUT_ASCII
ASM_OUTPUT_ASCII (asm_out_file, p, thissize);
-#else
- fprintf (asm_out_file, "\t.ascii \"");
-
- for (i = 0; i < thissize; i++)
- {
- register int c = p[i];
- if (c == '\"' || c == '\\')
- putc ('\\', asm_out_file);
- if (c >= ' ' && c < 0177)
- putc (c, asm_out_file);
- else
- {
- fprintf (asm_out_file, "\\%o", c);
- /* After an octal-escape, if a digit follows,
- terminate one string constant and start another.
- The Vax assembler fails to stop reading the escape
- after three digits, so this is the only way we
- can get it to parse the data properly. */
- if (i < thissize - 1
- && p[i + 1] >= '0' && p[i + 1] <= '9')
- fprintf (asm_out_file, "\"\n\t.ascii \"");
- }
- }
- fprintf (asm_out_file, "\"\n");
-#endif /* no ASM_OUTPUT_ASCII */
pos += thissize;
p += thissize;
/* Normally no need to say anything for external references,
since assembler considers all undefined symbols external. */
- if (TREE_EXTERNAL (decl))
+ if (DECL_EXTERNAL (decl))
return;
/* Output no assembler code for a function declaration.
{
error_with_file_and_line (DECL_SOURCE_FILE (decl),
DECL_SOURCE_LINE (decl),
- "storage size of static var `%s' isn't known",
+ "storage size of `%s' isn't known",
IDENTIFIER_POINTER (DECL_NAME (decl)));
return;
}
declaration. When something like ".stabx "aa:S-2",aa,133,0" is emitted
and `aa' hasn't been output yet, the assembler generates a stab entry with
a value of zero, in addition to creating an unnecessary external entry
- for `aa'. Hence, we must pospone dbxout_symbol to here at the end. */
+ for `aa'. Hence, we must postpone dbxout_symbol to here at the end. */
/* File-scope global variables are output here. */
if (write_symbols == XCOFF_DEBUG && top_level)
{
#ifdef ASM_OUTPUT_EXTERNAL
if (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd'
- && TREE_EXTERNAL (decl) && TREE_PUBLIC (decl))
+ && DECL_EXTERNAL (decl) && TREE_PUBLIC (decl))
{
rtx rtl = DECL_RTL (decl);
abort ();
}
- set_float_handler (0);
+ set_float_handler (NULL_PTR);
}
\f
/* Here we combine duplicate floating constants to make
rtx
immed_double_const (i0, i1, mode)
- int i0, i1;
+ HOST_WIDE_INT i0, i1;
enum machine_mode mode;
{
register rtx r;
sign bit are all one. So we get either a reasonable negative value
or a reasonable unsigned value for this mode. */
int width = GET_MODE_BITSIZE (mode);
- if (width < HOST_BITS_PER_INT
- && ((i0 & ((-1) << (width - 1))) != ((-1) << (width - 1))))
- i0 &= (1 << width) - 1, i1 = 0;
- else if (width == HOST_BITS_PER_INT
+ if (width < HOST_BITS_PER_WIDE_INT
+ && ((i0 & ((HOST_WIDE_INT) (-1) << (width - 1)))
+ != ((HOST_WIDE_INT) (-1) << (width - 1))))
+ i0 &= ((HOST_WIDE_INT) 1 << width) - 1, i1 = 0;
+ else if (width == HOST_BITS_PER_WIDE_INT
&& ! (i1 == ~0 && i0 < 0))
i1 = 0;
- else if (width > 2 * HOST_BITS_PER_INT)
+ else if (width > 2 * HOST_BITS_PER_WIDE_INT)
/* We cannot represent this value as a constant. */
abort ();
- /* If MODE fits within HOST_BITS_PER_INT, always use a CONST_INT.
+ /* If MODE fits within HOST_BITS_PER_WIDE_INT, always use a CONST_INT.
??? Strictly speaking, this is wrong if we create a CONST_INT
for a large unsigned constant with the size of MODE being
- HOST_BITS_PER_INT and later try to interpret that constant in a wider
- mode. In that case we will mis-interpret it as a negative number.
+ HOST_BITS_PER_WIDE_INT and later try to interpret that constant in a
+ wider mode. In that case we will mis-interpret it as a negative
+ number.
Unfortunately, the only alternative is to make a CONST_DOUBLE
for any constant in any mode if it is an unsigned constant larger
We have always been making CONST_INTs in this case, so nothing new
is being broken. */
- if (width <= HOST_BITS_PER_INT)
+ if (width <= HOST_BITS_PER_WIDE_INT)
i1 = (i0 < 0) ? ~0 : 0;
/* If this integer fits in one word, return a CONST_INT. */
if ((i1 == 0 && i0 >= 0)
|| (i1 == ~0 && i0 < 0))
- return gen_rtx (CONST_INT, VOIDmode, i0);
+ return GEN_INT (i0);
/* We use VOIDmode for integers. */
mode = VOIDmode;
/* Detect special cases. */
- if (REAL_VALUES_EQUAL (dconst0, d))
+ /* Avoid REAL_VALUES_EQUAL here in order to distinguish minus zero. */
+ if (!bcmp (&dconst0, &d, sizeof d))
return CONST0_RTX (mode);
else if (REAL_VALUES_EQUAL (dconst1, d))
return CONST1_RTX (mode);
- if (sizeof u == 2 * sizeof (int))
+ if (sizeof u == 2 * sizeof (HOST_WIDE_INT))
return immed_double_const (u.i[0], u.i[1], mode);
/* The rest of this function handles the case where
struct addr_const
{
rtx base;
- int offset;
+ HOST_WIDE_INT offset;
};
static void
/* For record type, include the type in the hashing.
We do not do so for array types
because (1) the sizes of the elements are sufficient
- and (2) distinct array types can have the same constructor. */
+ and (2) distinct array types can have the same constructor.
+ Instead, we include the array size because the constructor could
+ be shorter. */
if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
- hi = ((int) TREE_TYPE (exp) & ((1 << HASHBITS) - 1)) % MAX_HASH_TABLE;
+ hi = ((HOST_WIDE_INT) TREE_TYPE (exp) & ((1 << HASHBITS) - 1))
+ % MAX_HASH_TABLE;
else
- hi = 5;
+ hi = ((5 + int_size_in_bytes (TREE_TYPE (exp)))
+ & ((1 << HASHBITS) - 1)) % MAX_HASH_TABLE;
for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
- hi = (hi * 603 + const_hash (TREE_VALUE (link))) % MAX_HASH_TABLE;
+ if (TREE_VALUE (link))
+ hi = (hi * 603 + const_hash (TREE_VALUE (link))) % MAX_HASH_TABLE;
return hi;
}
return 0;
p += sizeof type;
+ /* 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));
+ if (bcmp (&size, p, sizeof size))
+ return 0;
+ p += sizeof size;
+ }
+
for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
- if ((p = compare_constant_1 (TREE_VALUE (link), p)) == 0)
- return 0;
+ {
+ if (TREE_VALUE (link))
+ {
+ if ((p = compare_constant_1 (TREE_VALUE (link), p)) == 0)
+ return 0;
+ }
+ else
+ {
+ tree zero = 0;
+
+ if (bcmp (&zero, p, sizeof zero))
+ return 0;
+ p += sizeof zero;
+ }
+ }
+
return p;
}
else if (code == ADDR_EXPR)
type = 0;
obstack_grow (&permanent_obstack, (char *) &type, sizeof type);
+ /* 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));
+ obstack_grow (&permanent_obstack, (char *) &size, sizeof size);
+ }
+
for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
- record_constant_1 (TREE_VALUE (link));
+ {
+ if (TREE_VALUE (link))
+ record_constant_1 (TREE_VALUE (link));
+ else
+ {
+ tree zero = 0;
+
+ obstack_grow (&permanent_obstack, (char *) &zero, sizeof zero);
+ }
+ }
+
return;
}
else if (code == ADDR_EXPR)
TREE_CST_RTL (exp)
= gen_rtx (MEM, TYPE_MODE (TREE_TYPE (exp)), def);
RTX_UNCHANGING_P (TREE_CST_RTL (exp)) = 1;
+ if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
+ || TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
+ MEM_IN_STRUCT_P (TREE_CST_RTL (exp)) = 1;
pop_obstacks ();
The argument is XSTR (... , 0) */
#define SYMHASH(LABEL) \
- ((((int) (LABEL)) & ((1 << HASHBITS) - 1)) % MAX_RTX_HASH_TABLE)
+ ((((HOST_WIDE_INT) (LABEL)) & ((1 << HASHBITS) - 1)) % MAX_RTX_HASH_TABLE)
\f
/* Initialize constant pool hashing for next function. */
/* Allow a constructor with no elements for any data type.
This means to fill the space with zeros. */
- if (TREE_CODE (exp) == CONSTRUCTOR
- && TREE_OPERAND (exp, 1) == 0)
+ if (TREE_CODE (exp) == CONSTRUCTOR && CONSTRUCTOR_ELTS (exp) == 0)
{
assemble_zeros (size);
return;
|| TREE_CODE (exp) == NON_LVALUE_EXPR)
exp = TREE_OPERAND (exp, 0);
- if (! assemble_integer (expand_expr (exp, 0, VOIDmode,
+ if (! assemble_integer (expand_expr (exp, NULL_RTX, VOIDmode,
EXPAND_INITIALIZER),
size, 0))
error ("initializer for integer value is too complicated");
int byte_buffer_in_use = 0;
register int byte;
- if (HOST_BITS_PER_INT < BITS_PER_UNIT)
+ if (HOST_BITS_PER_WIDE_INT < BITS_PER_UNIT)
abort ();
if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
field = TREE_PURPOSE (link);
/* Eliminate the marker that makes a cast not be an lvalue. */
- if (val != 0 && TREE_CODE (val) == NON_LVALUE_EXPR)
- val = TREE_OPERAND (val, 0);
+ if (val != 0)
+ STRIP_NOPS (val);
if (field == 0 || !DECL_BIT_FIELD (field))
{
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. */
- if (shift < HOST_BITS_PER_INT
- && shift + this_time > HOST_BITS_PER_INT)
+ if (shift < HOST_BITS_PER_WIDE_INT
+ && shift + this_time > HOST_BITS_PER_WIDE_INT)
{
- this_time -= (HOST_BITS_PER_INT - shift);
- shift = HOST_BITS_PER_INT;
+ this_time -= (HOST_BITS_PER_WIDE_INT - shift);
+ shift = HOST_BITS_PER_WIDE_INT;
}
/* Now get the bits from the appropriate constant word. */
- if (shift < HOST_BITS_PER_INT)
+ if (shift < HOST_BITS_PER_WIDE_INT)
{
value = TREE_INT_CST_LOW (val);
}
- else if (shift < 2 * HOST_BITS_PER_INT)
+ else if (shift < 2 * HOST_BITS_PER_WIDE_INT)
{
value = TREE_INT_CST_HIGH (val);
- shift -= HOST_BITS_PER_INT;
+ shift -= HOST_BITS_PER_WIDE_INT;
}
else
abort ();
- byte |= (((value >> shift) & ((1 << this_time) - 1))
+ byte |= (((value >> shift)
+ & (((HOST_WIDE_INT) 1 << this_time) - 1))
<< (BITS_PER_UNIT - this_time - next_bit));
#else
/* On little-endian machines,
- TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field)));
/* Don't try to take a bunch of bits that cross
the word boundary in the INTEGER_CST. */
- if (shift < HOST_BITS_PER_INT
- && shift + this_time > HOST_BITS_PER_INT)
+ if (shift < HOST_BITS_PER_WIDE_INT
+ && shift + this_time > HOST_BITS_PER_WIDE_INT)
{
- this_time -= (HOST_BITS_PER_INT - shift);
- shift = HOST_BITS_PER_INT;
+ this_time -= (HOST_BITS_PER_WIDE_INT - shift);
+ shift = HOST_BITS_PER_WIDE_INT;
}
/* Now get the bits from the appropriate constant word. */
if (shift < HOST_BITS_PER_INT)
value = TREE_INT_CST_LOW (val);
- else if (shift < 2 * HOST_BITS_PER_INT)
+ else if (shift < 2 * HOST_BITS_PER_WIDE_INT)
{
value = TREE_INT_CST_HIGH (val);
- shift -= HOST_BITS_PER_INT;
+ shift -= HOST_BITS_PER_WIDE_INT;
}
else
abort ();
- byte |= ((value >> shift) & ((1 << this_time) - 1)) << next_bit;
+ byte |= ((value >> shift)
+ & (((HOST_WIDE_INT) 1 << this_time) - 1)) << next_bit;
#endif
next_offset += this_time;
byte_buffer_in_use = 1;