aboutsummaryrefslogtreecommitdiff
path: root/gcc/varasm.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2015-11-08 18:33:42 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2015-11-08 18:33:42 +0000
commitee45a32dae253f7daa966573eb8cb64b2cf7bf52 (patch)
treecf927ff52a6d5ba28290472db09363fe67a835d6 /gcc/varasm.c
parenteb11eb157cf07500e2915da8a72f2f3a501cc5ae (diff)
downloadgcc-ee45a32dae253f7daa966573eb8cb64b2cf7bf52.zip
gcc-ee45a32dae253f7daa966573eb8cb64b2cf7bf52.tar.gz
gcc-ee45a32dae253f7daa966573eb8cb64b2cf7bf52.tar.bz2
Merge of the scalar-storage-order branch.
From-SVN: r229965
Diffstat (limited to 'gcc/varasm.c')
-rw-r--r--gcc/varasm.c121
1 files changed, 84 insertions, 37 deletions
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 9ffe914..ec6aabf 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see
#include "flags.h"
#include "stmt.h"
#include "expr.h"
+#include "expmed.h"
#include "output.h"
#include "langhooks.h"
#include "debug.h"
@@ -106,7 +107,7 @@ static int compare_constant (const tree, const tree);
static void output_constant_def_contents (rtx);
static void output_addressed_constants (tree);
static unsigned HOST_WIDE_INT output_constant (tree, unsigned HOST_WIDE_INT,
- unsigned int);
+ unsigned int, bool);
static void globalize_decl (tree);
static bool decl_readonly_section_1 (enum section_category);
#ifdef BSS_SECTION_ASM_OP
@@ -2054,7 +2055,8 @@ assemble_variable_contents (tree decl, const char *name,
/* Output the actual data. */
output_constant (DECL_INITIAL (decl),
tree_to_uhwi (DECL_SIZE_UNIT (decl)),
- get_variable_align (decl));
+ get_variable_align (decl),
+ false);
else
/* Leave space for it. */
assemble_zeros (tree_to_uhwi (DECL_SIZE_UNIT (decl)));
@@ -2733,12 +2735,17 @@ assemble_integer (rtx x, unsigned int size, unsigned int align, int force)
return false;
}
+/* Assemble the floating-point constant D into an object of size MODE. ALIGN
+ is the alignment of the constant in bits. If REVERSE is true, D is output
+ in reverse storage order. */
+
void
-assemble_real (REAL_VALUE_TYPE d, machine_mode mode, unsigned int align)
+assemble_real (REAL_VALUE_TYPE d, machine_mode mode, unsigned int align,
+ bool reverse)
{
long data[4] = {0, 0, 0, 0};
- int i;
int bitsize, nelts, nunits, units_per;
+ rtx elt;
/* This is hairy. We have a quantity of known size. real_to_target
will put it into an array of *host* longs, 32 bits per element
@@ -2760,15 +2767,24 @@ assemble_real (REAL_VALUE_TYPE d, machine_mode mode, unsigned int align)
real_to_target (data, &d, mode);
/* Put out the first word with the specified alignment. */
- assemble_integer (GEN_INT (data[0]), MIN (nunits, units_per), align, 1);
+ if (reverse)
+ elt = flip_storage_order (SImode, gen_int_mode (data[nelts - 1], SImode));
+ else
+ elt = GEN_INT (data[0]);
+ assemble_integer (elt, MIN (nunits, units_per), align, 1);
nunits -= units_per;
/* Subsequent words need only 32-bit alignment. */
align = min_align (align, 32);
- for (i = 1; i < nelts; i++)
+ for (int i = 1; i < nelts; i++)
{
- assemble_integer (GEN_INT (data[i]), MIN (nunits, units_per), align, 1);
+ if (reverse)
+ elt = flip_storage_order (SImode,
+ gen_int_mode (data[nelts - 1 - i], SImode));
+ else
+ elt = GEN_INT (data[i]);
+ assemble_integer (elt, MIN (nunits, units_per), align, 1);
nunits -= units_per;
}
}
@@ -3070,10 +3086,12 @@ compare_constant (const tree t1, const tree t2)
if (typecode == ARRAY_TYPE)
{
HOST_WIDE_INT size_1 = int_size_in_bytes (TREE_TYPE (t1));
- /* For arrays, check that the sizes all match. */
+ /* For arrays, check that mode, size and storage order match. */
if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2))
|| size_1 == -1
- || size_1 != int_size_in_bytes (TREE_TYPE (t2)))
+ || size_1 != int_size_in_bytes (TREE_TYPE (t2))
+ || TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (t1))
+ != TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (t2)))
return 0;
}
else
@@ -3357,7 +3375,7 @@ assemble_constant_contents (tree exp, const char *label, unsigned int align)
targetm.asm_out.declare_constant_name (asm_out_file, label, exp, size);
/* Output the value of EXP. */
- output_constant (exp, size, align);
+ output_constant (exp, size, align, false);
targetm.asm_out.decl_end ();
}
@@ -3788,7 +3806,7 @@ output_constant_pool_2 (machine_mode mode, rtx x, unsigned int align)
case MODE_DECIMAL_FLOAT:
{
gcc_assert (CONST_DOUBLE_AS_FLOAT_P (x));
- assemble_real (*CONST_DOUBLE_REAL_VALUE (x), mode, align);
+ assemble_real (*CONST_DOUBLE_REAL_VALUE (x), mode, align, false);
break;
}
@@ -4288,7 +4306,11 @@ initializer_constant_valid_p_1 (tree value, tree endtype, tree *cache)
tree reloc;
reloc = initializer_constant_valid_p_1 (elt, TREE_TYPE (elt),
NULL);
- if (!reloc)
+ if (!reloc
+ /* An absolute value is required with reverse SSO. */
+ || (reloc != null_pointer_node
+ && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (value))
+ && !AGGREGATE_TYPE_P (TREE_TYPE (elt))))
{
if (cache)
{
@@ -4528,9 +4550,19 @@ initializer_constant_valid_p_1 (tree value, tree endtype, tree *cache)
therefore, we do not need to check for such things as
arithmetic-combinations of integers. */
tree
-initializer_constant_valid_p (tree value, tree endtype)
+initializer_constant_valid_p (tree value, tree endtype, bool reverse)
{
- return initializer_constant_valid_p_1 (value, endtype, NULL);
+ tree reloc = initializer_constant_valid_p_1 (value, endtype, NULL);
+
+ /* An absolute value is required with reverse storage order. */
+ if (reloc
+ && reloc != null_pointer_node
+ && reverse
+ && !AGGREGATE_TYPE_P (endtype)
+ && !VECTOR_TYPE_P (endtype))
+ reloc = NULL_TREE;
+
+ return reloc;
}
/* Return true if VALUE is a valid constant-valued expression
@@ -4580,8 +4612,8 @@ struct oc_outer_state {
};
static unsigned HOST_WIDE_INT
- output_constructor (tree, unsigned HOST_WIDE_INT, unsigned int,
- oc_outer_state *);
+output_constructor (tree, unsigned HOST_WIDE_INT, unsigned int, bool,
+ oc_outer_state *);
/* Output assembler code for constant EXP, with no label.
This includes the pseudo-op such as ".int" or ".byte", and a newline.
@@ -4603,13 +4635,17 @@ static unsigned HOST_WIDE_INT
for a structure constructor that wants to produce more than SIZE bytes.
But such constructors will never be generated for any possible input.
- ALIGN is the alignment of the data in bits. */
+ ALIGN is the alignment of the data in bits.
+
+ If REVERSE is true, EXP is output in reverse storage order. */
static unsigned HOST_WIDE_INT
-output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
+output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align,
+ bool reverse)
{
enum tree_code code;
unsigned HOST_WIDE_INT thissize;
+ rtx cst;
if (size == 0 || flag_syntax_only)
return size;
@@ -4704,9 +4740,10 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
case FIXED_POINT_TYPE:
case POINTER_BOUNDS_TYPE:
case NULLPTR_TYPE:
- if (! assemble_integer (expand_expr (exp, NULL_RTX, VOIDmode,
- EXPAND_INITIALIZER),
- MIN (size, thissize), align, 0))
+ cst = expand_expr (exp, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
+ if (reverse)
+ cst = flip_storage_order (TYPE_MODE (TREE_TYPE (exp)), cst);
+ if (!assemble_integer (cst, MIN (size, thissize), align, 0))
error ("initializer for integer/fixed-point value is too complicated");
break;
@@ -4714,13 +4751,15 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
if (TREE_CODE (exp) != REAL_CST)
error ("initializer for floating value is not a floating constant");
else
- assemble_real (TREE_REAL_CST (exp), TYPE_MODE (TREE_TYPE (exp)), align);
+ assemble_real (TREE_REAL_CST (exp), TYPE_MODE (TREE_TYPE (exp)),
+ align, reverse);
break;
case COMPLEX_TYPE:
- output_constant (TREE_REALPART (exp), thissize / 2, align);
+ output_constant (TREE_REALPART (exp), thissize / 2, align, reverse);
output_constant (TREE_IMAGPART (exp), thissize / 2,
- min_align (align, BITS_PER_UNIT * (thissize / 2)));
+ min_align (align, BITS_PER_UNIT * (thissize / 2)),
+ reverse);
break;
case ARRAY_TYPE:
@@ -4728,7 +4767,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
switch (TREE_CODE (exp))
{
case CONSTRUCTOR:
- return output_constructor (exp, size, align, NULL);
+ return output_constructor (exp, size, align, reverse, NULL);
case STRING_CST:
thissize
= MIN ((unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp), size);
@@ -4739,11 +4778,13 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
machine_mode inner = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
unsigned int nalign = MIN (align, GET_MODE_ALIGNMENT (inner));
int elt_size = GET_MODE_SIZE (inner);
- output_constant (VECTOR_CST_ELT (exp, 0), elt_size, align);
+ output_constant (VECTOR_CST_ELT (exp, 0), elt_size, align,
+ reverse);
thissize = elt_size;
for (unsigned int i = 1; i < VECTOR_CST_NELTS (exp); i++)
{
- output_constant (VECTOR_CST_ELT (exp, i), elt_size, nalign);
+ output_constant (VECTOR_CST_ELT (exp, i), elt_size, nalign,
+ reverse);
thissize += elt_size;
}
break;
@@ -4756,7 +4797,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
case RECORD_TYPE:
case UNION_TYPE:
gcc_assert (TREE_CODE (exp) == CONSTRUCTOR);
- return output_constructor (exp, size, align, NULL);
+ return output_constructor (exp, size, align, reverse, NULL);
case ERROR_MARK:
return 0;
@@ -4770,7 +4811,6 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
return size;
}
-
/* Subroutine of output_constructor, used for computing the size of
arrays of unspecified length. VAL must be a CONSTRUCTOR of an array
@@ -4832,6 +4872,7 @@ struct oc_local_state {
int last_relative_index; /* Implicit or explicit index of the last
array element output within a bitfield. */
bool byte_buffer_in_use; /* Whether BYTE is in use. */
+ bool reverse; /* Whether reverse storage order is in use. */
/* Current element. */
tree field; /* Current field decl in a record. */
@@ -4864,7 +4905,8 @@ output_constructor_array_range (oc_local_state *local)
if (local->val == NULL_TREE)
assemble_zeros (fieldsize);
else
- fieldsize = output_constant (local->val, fieldsize, align2);
+ fieldsize
+ = output_constant (local->val, fieldsize, align2, local->reverse);
/* Count its size. */
local->total_bytes += fieldsize;
@@ -4950,7 +4992,8 @@ output_constructor_regular_field (oc_local_state *local)
if (local->val == NULL_TREE)
assemble_zeros (fieldsize);
else
- fieldsize = output_constant (local->val, fieldsize, align2);
+ fieldsize
+ = output_constant (local->val, fieldsize, align2, local->reverse);
/* Count its size. */
local->total_bytes += fieldsize;
@@ -5048,7 +5091,7 @@ output_constructor_bitfield (oc_local_state *local, unsigned int bit_offset)
temp_state.bit_offset = next_offset % BITS_PER_UNIT;
temp_state.byte = local->byte;
local->total_bytes
- += output_constructor (local->val, 0, 0, &temp_state);
+ += output_constructor (local->val, 0, 0, local->reverse, &temp_state);
local->byte = temp_state.byte;
return;
}
@@ -5074,9 +5117,9 @@ output_constructor_bitfield (oc_local_state *local, unsigned int bit_offset)
/* Number of bits we can process at once (all part of the same byte). */
this_time = MIN (end_offset - next_offset, BITS_PER_UNIT - next_bit);
- if (BYTES_BIG_ENDIAN)
+ if (local->reverse ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN)
{
- /* On big-endian machine, take the most significant bits (of the
+ /* For big-endian data, take the most significant bits (of the
bits that are significant) first and put them into bytes from
the most significant end. */
shift = end_offset - next_offset - this_time;
@@ -5138,12 +5181,11 @@ output_constructor_bitfield (oc_local_state *local, unsigned int bit_offset)
caller output state of relevance in recursive invocations. */
static unsigned HOST_WIDE_INT
-output_constructor (tree exp, unsigned HOST_WIDE_INT size,
- unsigned int align, oc_outer_state *outer)
+output_constructor (tree exp, unsigned HOST_WIDE_INT size, unsigned int align,
+ bool reverse, oc_outer_state *outer)
{
unsigned HOST_WIDE_INT cnt;
constructor_elt *ce;
-
oc_local_state local;
/* Setup our local state to communicate with helpers. */
@@ -5160,6 +5202,11 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size,
local.byte_buffer_in_use = outer != NULL;
local.byte = outer ? outer->byte : 0;
local.last_relative_index = -1;
+ /* The storage order is specified for every aggregate type. */
+ if (AGGREGATE_TYPE_P (local.type))
+ local.reverse = TYPE_REVERSE_STORAGE_ORDER (local.type);
+ else
+ local.reverse = reverse;
gcc_assert (HOST_BITS_PER_WIDE_INT >= BITS_PER_UNIT);