Merge of the scalar-storage-order branch.

From-SVN: r229965
This commit is contained in:
Eric Botcazou 2015-11-08 18:33:42 +00:00 committed by Eric Botcazou
parent eb11eb157c
commit ee45a32dae
224 changed files with 9968 additions and 523 deletions

View File

@ -1,3 +1,276 @@
2015-11-08 Eric Botcazou <ebotcazou@adacore.com>
* doc/extend.texi (type attributes): Document scalar_storage_order.
(Structure-Packing Pragmas): Rename into...
(Structure-Layout Pragmas): ...this. Document scalar_storage_order.
* doc/invoke.texi (C Dialect Options): Document -fsso-struct
(Warnings): Document -Wno-scalar-storage-order.
* flag-types.h (enum scalar_storage_order_kind): New enumeration.
* calls.c (store_unaligned_arguments_into_pseudos): Adjust calls to
extract_bit_field and store_bit_field.
(initialize_argument_information): Adjust call to store_expr.
(load_register_parameters): Adjust call to extract_bit_field.
* expmed.c (check_reverse_storage_order_support): New function.
(check_reverse_float_storage_order_support): Likewise.
(flip_storage_order): Likewise.
(store_bit_field_1): Add REVERSE parameter. Flip the storage order
of the value if it is true. Pass REVERSE to recursive call after
adjusting the target offset.
Do not use extraction or movstrict instruction if REVERSE is true.
Pass REVERSE to store_fixed_bit_field.
(store_bit_field): Add REVERSE parameter and pass to it to above.
(store_fixed_bit_field): Add REVERSE parameter and pass to it to
store_split_bit_field and store_fixed_bit_field_1.
(store_fixed_bit_field_1): Add REVERSE parameter. Flip the storage
order of the value if it is true and adjust the target offset.
(store_split_bit_field): Add REVERSE parameter and pass it to
store_fixed_bit_field. Adjust the target offset if it is true.
(extract_bit_field_1): Add REVERSE parameter. Flip the storage order
of the value if it is true. Pass REVERSE to recursive call after
adjusting the target offset.
Do not use extraction or subreg instruction if REVERSE is true.
Pass REVERSE to extract_fixed_bit_field.
(extract_bit_field): Add REVERSE parameter and pass to it to above.
(extract_fixed_bit_field): Add REVERSE parameter and pass to it to
extract_split_bit_field and extract_fixed_bit_field_1.
(extract_fixed_bit_field_1): Add REVERSE parameter. Flip the storage
order of the value if it is true and adjust the target offset.
(extract_split_bit_field): Add REVERSE parameter and pass it to
extract_fixed_bit_field. Adjust the target offset if it is true.
* expmed.h (flip_storage_order): Declare.
(store_bit_field): Adjust prototype.
(extract_bit_field): Likewise.
* expr.c (emit_group_load_1): Adjust calls to extract_bit_field.
(emit_group_store): Adjust call to store_bit_field.
(copy_blkmode_from_reg): Likewise.
(copy_blkmode_to_reg): Likewise.
(write_complex_part): Likewise.
(read_complex_part): Likewise.
(optimize_bitfield_assignment_op): Add REVERSE parameter. Assert
that it isn't true if the target is a register.
<PLUS_EXPR>: If it is, do not optimize unless bitsize is equal to 1,
and flip the storage order of the value.
<BIT_IOR_EXPR>: Flip the storage order of the value.
(get_bit_range): Adjust call to get_inner_reference.
(expand_assignment): Adjust calls to get_inner_reference, store_expr,
optimize_bitfield_assignment_op and store_field. Handle MEM_EXPRs
with reverse storage order.
(store_expr_with_bounds): Add REVERSE parameter and pass it to
recursive calls and call to store_bit_field. Force the value into a
register if it is true and then flip the storage order of the value.
(store_expr): Add REVERSE parameter and pass it to above.
(categorize_ctor_elements_1): Adjust call to
initializer_constant_valid_p.
(store_constructor_field): Add REVERSE parameter and pass it to
recursive calls and call to store_field.
(store_constructor): Add REVERSE parameter and pass it to calls to
store_constructor_field and store_expr. Set it to true for an
aggregate type with TYPE_REVERSE_STORAGE_ORDER.
(store_field): Add REVERSE parameter and pass it to recursive calls
and calls to store_expr and store_bit_field. Temporarily flip the
storage order of the value with record type and integral mode and
adjust the shift if it is true.
(get_inner_reference): Add PREVERSEP parameter and set it to true
upon encoutering a reference with reverse storage order.
(expand_expr_addr_expr_1): Adjust call to get_inner_reference.
(expand_constructor): Adjust call to store_constructor.
(expand_expr_real_2) <CASE_CONVERT>: Pass TYPE_REVERSE_STORAGE_ORDER
of the union type to store_expr in the MEM case and assert that it
isn't set in the REG case. Adjust call to store_field.
(expand_expr_real_1) <MEM_REF>: Handle reverse storage order.
<normal_inner_ref>: Add REVERSEP variable and adjust calls to
get_inner_reference and extract_bit_field. Temporarily flip the
storage order of the value with record type and integral mode and
adjust the shift if it is true. Flip the storage order of the value
at the end if it is true.
<VIEW_CONVERT_EXPR>: Add REVERSEP variable and adjust call to
get_inner_reference. Do not fetch an inner reference if it is true.
* expr.h (store_expr_with_bounds): Ajust prototype.
(store_expr): Likewise.
* fold-const.c (make_bit_field_ref): Add REVERSEP parameter and set
REF_REVERSE_STORAGE_ORDER on the reference according to it.
(optimize_bit_field_compare): Deal with reverse storage order.
Adjust calls to get_inner_reference and make_bit_field_ref.
(decode_field_reference): Add PREVERSEP parameter and adjust call to
get_inner_reference.
(fold_truth_andor_1): Deal with reverse storage order. Adjust calls
to decode_field_reference and make_bit_field_ref.
(fold_unary_loc) <CASE_CONVERT>: Adjust call to get_inner_reference.
<VIEW_CONVERT_EXPR>: Propagate the REF_REVERSE_STORAGE_ORDER flag.
(fold_comparison): Adjust call to get_inner_reference.
(split_address_to_core_and_offset): Adjust call to
get_inner_reference.
* gimple-expr.c (useless_type_conversion_p): Return false for array
types with different TYPE_REVERSE_STORAGE_ORDER flag.
* gimplify.c (gimplify_expr) <MEM_REF>: Propagate the
REF_REVERSE_STORAGE_ORDER flag.
* lto-streamer-out.c (hash_tree): Deal with
TYPE_REVERSE_STORAGE_ORDER.
* output.h (assemble_real): Adjust prototype.
* print-tree.c (print_node): Convey TYPE_REVERSE_STORAGE_ORDER.
* stor-layout.c (finish_record_layout): Propagate the
TYPE_REVERSE_STORAGE_ORDER flag to the variants.
* tree-core.h (TYPE_REVERSE_STORAGE_ORDER): Document.
(TYPE_SATURATING): Adjust.
(REF_REVERSE_STORAGE_ORDER): Document.
* tree-dfa.c (get_ref_base_and_extent): Add PREVERSE parameter and
set it to true upon encoutering a reference with reverse storage
order.
* tree-dfa.h (get_ref_base_and_extent): Adjust prototype.
* tree-inline.c (remap_gimple_op_r): Propagate the
REF_REVERSE_STORAGE_ORDER flag.
(copy_tree_body_r): Likewise.
* tree-outof-ssa.c (insert_value_copy_on_edge): Adjust call to
store_expr.
* tree-streamer-in.c (unpack_ts_base_value_fields): Deal with
TYPE_REVERSE_STORAGE_ORDER and REF_REVERSE_STORAGE_ORDER.
* tree-streamer-out.c (pack_ts_base_value_fields): Likewise.
* tree.c (stabilize_reference) <BIT_FIELD_REF>: Propagate the
REF_REVERSE_STORAGE_ORDER flag.
(verify_type_variant): Deal with TYPE_REVERSE_STORAGE_ORDER.
(gimple_canonical_types_compatible_p): Likewise.
* tree.h (TYPE_REVERSE_STORAGE_ORDER): New flag.
(TYPE_SATURATING): Adjust.
(REF_REVERSE_STORAGE_ORDER): New flag.
(reverse_storage_order_for_component_p): New inline predicate.
(storage_order_barrier_p): Likewise.
(get_inner_reference): Adjust prototype.
* varasm.c: Include expmed.h.
(assemble_variable_contents): Adjust call to output_constant.
(assemble_real): Add REVERSE parameter. Flip the storage
order of the value if REVERSE is true.
(compare_constant) <CONSTRUCTOR>: Compare TYPE_REVERSE_STORAGE_ORDER.
(assemble_constant_contents): Adjust call to output_constant.
(output_constant_pool_2): Adjust call to assemble_real.
(initializer_constant_valid_p_1) <CONSTRUCTOR>: Deal with
TYPE_REVERSE_STORAGE_ORDER.
(initializer_constant_valid_p): Add REVERSE parameter.
(output_constant): Add REVERSE parameter.
<INTEGER_TYPE>: Flip the storage order of the value if REVERSE is true.
<REAL_TYPE>: Adjust call to assemble_real.
<COMPLEX_TYPE>: Pass it to recursive calls.
<ARRAY_TYPE>: Likewise. Adjust call to output_constructor.
<RECORD_TYPE>: Likewise. Adjust call to output_constructor.
(struct oc_local_state): Add REVERSE field.
(output_constructor_array_range): Adjust calls to output_constant.
(output_constructor_regular_field): Likewise.
(output_constructor_bitfield): Adjust call to output_constructor.
Flip the storage order of the value if REVERSE is true.
(output_constructor): Add REVERSE parameter. Set it to true for an
aggregate type with TYPE_REVERSE_STORAGE_ORDER. Adjust call to
output_constructor_bitfield.
* varasm.h (initializer_constant_valid_p): Default REVERSE to false.
* asan.c (instrument_derefs): Adjust call to get_inner_reference.
* builtins.c (get_object_alignment_2): Likewise.
* cfgexpand.c (expand_debug_expr): Adjust call to get_inner_reference
and get_ref_base_and_extent.
* dbxout.c (dbxout_expand_expr): Likewise.
* dwarf2out.c (add_var_loc_to_decl): Likewise.
(loc_list_for_address_of_addr_expr_of_indirect_ref): Likewise.
(loc_list_from_tree): Likewise.
(fortran_common): Likewise.
* gimple-fold.c (gimple_fold_builtin_memory_op): Adjust calls to
get_ref_base_and_extent.
(get_base_constructor): Likewise.
(fold_const_aggregate_ref_1): Likewise.
* gimple-laddress.c (pass_laddress::execute): Adjust call to
get_inner_reference.
* gimple-ssa-strength-reduction.c (slsr_process_ref): Adjust call to
get_inner_reference and bail out on reverse storage order.
* ifcvt.c (noce_emit_move_insn): Adjust calls to store_bit_field.
* ipa-cp.c (ipa_get_jf_ancestor_result): Adjust call to
build_ref_for_offset.
* ipa-polymorphic-call.c (set_by_invariant): Adjust call to
get_ref_base_and_extent.
(ipa_polymorphic_call_context): Likewise.
(extr_type_from_vtbl_ptr_store): Likewise.
(check_stmt_for_type_change): Likewise.
(get_dynamic_type): Likewise.
* ipa-prop.c (ipa_load_from_parm_agg_1): Adjust call to
get_ref_base_and_extent.
(compute_complex_assign_jump_func): Likewise.
(get_ancestor_addr_info): Likewise.
(compute_known_type_jump_func): Likewise.
(determine_known_aggregate_parts): Likewise.
(ipa_get_adjustment_candidate): Likewise.
(ipa_modify_call_arguments): Set REF_REVERSE_STORAGE_ORDER on
MEM_REF.
* ipa-prop.h (ipa_parm_adjustment): Add REVERSE field.
(build_ref_for_offset): Adjust prototype.
* simplify-rtx.c (delegitimize_mem_from_attrs): Adjust call to
get_inner_reference.
* tree-affine.c (tree_to_aff_combination): Adjust call to
get_inner_reference.
(get_inner_reference_aff): Likewise.
* tree-data-ref.c (split_constant_offset_1): Likewise.
(dr_analyze_innermost): Likewise. Bail out if reverse storage order.
* tree-scalar-evolution.c (interpret_rhs_expr): Adjust call to
get_inner_reference.
* tree-sra.c (struct access): Add REVERSE and move WRITE around.
(dump_access): Print new fields.
(create_access): Adjust call to get_ref_base_and_extent and set the
REVERSE flag according to the result.
(completely_scalarize_record): Set the REVERSE flag.
(scalarize_elem): Add REVERSE parameter.
(build_access_from_expr_1): Preserve storage order barriers.
(build_accesses_from_assign): Likewise.
(build_ref_for_offset): Add REVERSE parameter and set the
REF_REVERSE_STORAGE_ORDER flag accordingly.
(build_ref_for_model): Adjust call to build_ref_for_offset and clear
the REF_REVERSE_STORAGE_ORDER flag if there are components.
(analyze_access_subtree): Likewise.
(create_artificial_child_access): Set the REVERSE flag.
(get_access_for_expr): Adjust call to get_ref_base_and_extent.
(turn_representatives_into_adjustments): Propagate REVERSE flag.
(ipa_sra_check_caller): Adjust call to get_inner_reference.
* tree-ssa-alias.c (ao_ref_base): Adjust call to
get_ref_base_and_extent.
(aliasing_component_refs_p): Likewise.
(stmt_kills_ref_p_1): Likewise.
* tree-ssa-dce.c (mark_aliased_reaching_defs_necessary_1): Likewise.
* tree-ssa-loop-ivopts.c (may_be_nonaddressable_p) <MEM_REF>: New.
Return true if reverse storage order.
<BIT_FIELD_REF>: Likewise.
<COMPONENT_REF>: Likewise.
<ARRAY_REF>: Likewise.
<ARRAY_RANGE_REF>: Likewise.
(split_address_cost): Likewise. Bail out if reverse storage order.
* tree-ssa-math-opts.c (find_bswap_or_nop_load): Adjust call to
get_inner_reference. Bail out if reverse storage order.
(bswap_replace): Adjust call to get_inner_reference.
* tree-ssa-pre.c (create_component_ref_by_pieces_1) <MEM_REF>: Set
the REF_REVERSE_STORAGE_ORDER flag.
<BIT_FIELD_REF>: Likewise.
* tree-ssa-sccvn.c (vn_reference_eq): Return false on storage order
barriers.
(copy_reference_ops_from_ref) <MEM_REF>: Set REVERSE field according
to the REF_REVERSE_STORAGE_ORDER flag.
<BIT_FIELD_REF>: Likewise.
<VIEW_CONVERT_EXPR>: Set it for storage order barriers.
(contains_storage_order_barrier_p): New predicate.
(vn_reference_lookup_3): Adjust calls to get_ref_base_and_extent.
Punt on storage order barriers if necessary.
* tree-ssa-sccvn.h (struct vn_reference_op_struct): Add REVERSE.
* tree-ssa-structalias.c (get_constraint_for_component_ref): Adjust
call to get_ref_base_and_extent.
(do_structure_copy): Likewise.
* tree-vect-data-refs.c (vect_check_gather): Adjust call to
get_inner_reference.
(vect_analyze_data_refs): Likewise. Bail out if reverse storage
order.
* tsan.c (instrument_expr): Adjust call to get_inner_reference.
* ubsan.c (instrument_bool_enum_load): Likewise.
(instrument_object_size): Likewise.
* var-tracking.c (track_expr_p): Adjust call to
get_ref_base_and_extent
* config/mips/mips.c (r10k_safe_mem_expr_p): Adjust call to
get_inner_reference.
* config/s390/s390.c (s390_expand_atomic): Adjust call to
store_bit_field.
* config/tilegx/tilegx.c (tilegx_expand_unaligned_load): Adjust call to
extract_bit_field.
* config/tilepro/tilepro.c (tilepro_expand_unaligned_load): Likewise.
2015-11-07 Eric Botcazou <ebotcazou@adacore.com>
* config/sparc/sparc.opt (mfix-at697f): Add final period.

View File

@ -1,3 +1,28 @@
2015-11-08 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/gigi.h (set_reverse_storage_order_on_pad_type):
Declare.
* gcc-interface/decl.c (gnat_to_gnu_entity) <discrete_type>: Set the
storage order on the enclosing record for a packed array type.
<E_Array_Type>: Set the storage order.
<E_Array_Subtype>: Likewise.
<E_Record_Type>: Likewise.
<E_Record_Subtype>: Likewise.
(gnat_to_gnu_component_type): Set the reverse storage order on a
padded type built for a non-bit-packed array.
(gnat_to_gnu_field): Likewise.
(components_to_record): Deal with TYPE_REVERSE_STORAGE_ORDER.
* gcc-interface/utils.c (make_packable_type): Likewise.
(pad_type_hasher::equal): Likewise.
(gnat_types_compatible_p): Likewise.
(unchecked_convert): Likewise.
(set_reverse_storage_order_on_pad_type): New public function.
* gcc-interface/trans.c (Attribute_to_gnu): Adjust call to
get_inner_reference.
* gcc-interface/utils2.c (build_unary_op): Likewise.
(gnat_build_constructor): Deal with TYPE_REVERSE_STORAGE_ORDER.
(gnat_rewrite_reference): Propagate REF_REVERSE_STORAGE_ORDER.
2015-11-07 Richard Sandiford <richard.sandiford@arm.com>
* gcc-interface/utils.c: Don't undef DEF_BUILTIN.

View File

@ -1805,6 +1805,12 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
TYPE_ALIGN (gnu_type)
= align > 0 ? align : TYPE_ALIGN (gnu_field_type);
/* Propagate the reverse storage order flag to the record type so
that the required byte swapping is performed when retrieving the
enclosed modular value. */
TYPE_REVERSE_STORAGE_ORDER (gnu_type)
= Reverse_Storage_Order (Original_Array_Type (gnat_entity));
relate_alias_sets (gnu_type, gnu_field_type, ALIAS_SET_COPY);
/* Don't declare the field as addressable since we won't be taking
@ -2152,8 +2158,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
for (index = ndim - 1; index >= 0; index--)
{
tem = build_nonshared_array_type (tem, gnu_index_types[index]);
if (Reverse_Storage_Order (gnat_entity) && !GNAT_Mode)
sorry ("non-default Scalar_Storage_Order");
if (index == ndim - 1)
TYPE_REVERSE_STORAGE_ORDER (tem)
= Reverse_Storage_Order (gnat_entity);
TYPE_MULTI_ARRAY_P (tem) = (index > 0);
if (array_type_has_nonaliased_component (tem, gnat_entity))
TYPE_NONALIASED_COMPONENT (tem) = 1;
@ -2516,6 +2523,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
{
gnu_type = build_nonshared_array_type (gnu_type,
gnu_index_types[index]);
if (index == ndim - 1)
TYPE_REVERSE_STORAGE_ORDER (gnu_type)
= Reverse_Storage_Order (gnat_entity);
TYPE_MULTI_ARRAY_P (gnu_type) = (index > 0);
if (array_type_has_nonaliased_component (gnu_type, gnat_entity))
TYPE_NONALIASED_COMPONENT (gnu_type) = 1;
@ -2876,8 +2886,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
gnu_type = make_node (tree_code_for_record_type (gnat_entity));
TYPE_NAME (gnu_type) = gnu_entity_name;
TYPE_PACKED (gnu_type) = (packed != 0) || has_rep;
if (Reverse_Storage_Order (gnat_entity) && !GNAT_Mode)
sorry ("non-default Scalar_Storage_Order");
TYPE_REVERSE_STORAGE_ORDER (gnu_type)
= Reverse_Storage_Order (gnat_entity);
process_attributes (&gnu_type, &attr_list, true, gnat_entity);
if (!definition)
@ -3287,6 +3297,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
gnu_type = make_node (RECORD_TYPE);
TYPE_NAME (gnu_type) = gnu_entity_name;
TYPE_PACKED (gnu_type) = TYPE_PACKED (gnu_base_type);
TYPE_REVERSE_STORAGE_ORDER (gnu_type)
= Reverse_Storage_Order (gnat_entity);
process_attributes (&gnu_type, &attr_list, true, gnat_entity);
/* Set the size, alignment and alias set of the new type to
@ -3341,6 +3353,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
TYPE_NAME (new_variant)
= concat_name (TYPE_NAME (gnu_type),
IDENTIFIER_POINTER (suffix));
TYPE_REVERSE_STORAGE_ORDER (new_variant)
= TYPE_REVERSE_STORAGE_ORDER (gnu_type);
copy_and_substitute_in_size (new_variant, old_variant,
gnu_subst_list);
v->new_type = new_variant;
@ -5548,6 +5562,16 @@ gnat_to_gnu_component_type (Entity_Id gnat_array, bool definition,
gnat_array);
}
/* If the component type is a padded type made for a non-bit-packed array
of scalars with reverse storage order, we need to propagate the reverse
storage order to the padding type since it is the innermost enclosing
aggregate type around the scalar. */
if (TYPE_IS_PADDING_P (gnu_type)
&& Reverse_Storage_Order (gnat_array)
&& !Is_Bit_Packed_Array (gnat_array)
&& Is_Scalar_Type (gnat_type))
gnu_type = set_reverse_storage_order_on_pad_type (gnu_type);
if (Has_Volatile_Components (gnat_array))
{
const int quals
@ -6718,6 +6742,15 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
else
gnu_pos = NULL_TREE;
/* If the field's type is a padded type made for a scalar field of a record
type with reverse storage order, we need to propagate the reverse storage
order to the padding type since it is the innermost enclosing aggregate
type around the scalar. */
if (TYPE_IS_PADDING_P (gnu_field_type)
&& TYPE_REVERSE_STORAGE_ORDER (gnu_record_type)
&& Is_Scalar_Type (gnat_field_type))
gnu_field_type = set_reverse_storage_order_on_pad_type (gnu_field_type);
gcc_assert (TREE_CODE (gnu_field_type) != RECORD_TYPE
|| !TYPE_CONTAINS_TEMPLATE_P (gnu_field_type));
@ -7034,6 +7067,8 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
TYPE_NAME (gnu_union_type) = gnu_union_name;
TYPE_ALIGN (gnu_union_type) = 0;
TYPE_PACKED (gnu_union_type) = TYPE_PACKED (gnu_record_type);
TYPE_REVERSE_STORAGE_ORDER (gnu_union_type)
= TYPE_REVERSE_STORAGE_ORDER (gnu_record_type);
}
/* If all the fields down to this level have a rep clause, find out
@ -7085,6 +7120,8 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
record actually gets only the alignment required. */
TYPE_ALIGN (gnu_variant_type) = TYPE_ALIGN (gnu_record_type);
TYPE_PACKED (gnu_variant_type) = TYPE_PACKED (gnu_record_type);
TYPE_REVERSE_STORAGE_ORDER (gnu_variant_type)
= TYPE_REVERSE_STORAGE_ORDER (gnu_record_type);
/* Similarly, if the outer record has a size specified and all
the fields have a rep clause, we can propagate the size. */
@ -7177,6 +7214,8 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
position at this level. */
tree gnu_rep_type = make_node (RECORD_TYPE);
tree gnu_rep_part;
TYPE_REVERSE_STORAGE_ORDER (gnu_rep_type)
= TYPE_REVERSE_STORAGE_ORDER (gnu_variant_type);
finish_record_type (gnu_rep_type, NULL_TREE, 0, debug_info);
gnu_rep_part
= create_rep_part (gnu_rep_type, gnu_variant_type,
@ -7384,6 +7423,8 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
gnu_field_list = gnu_rep_list;
else
{
TYPE_REVERSE_STORAGE_ORDER (gnu_rep_type)
= TYPE_REVERSE_STORAGE_ORDER (gnu_record_type);
finish_record_type (gnu_rep_type, gnu_rep_list, 1, debug_info);
/* If FIRST_FREE_POS is nonzero, we need to ensure that the fields

View File

@ -154,6 +154,9 @@ extern tree maybe_pad_type (tree type, tree size, unsigned int align,
bool is_user_type, bool definition,
bool set_rm_size);
/* Return a copy of the padded TYPE but with reverse storage order. */
extern tree set_reverse_storage_order_on_pad_type (tree type);
enum alias_set_op
{
ALIAS_SET_COPY,

View File

@ -2172,7 +2172,7 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
tree gnu_field_offset;
tree gnu_inner;
machine_mode mode;
int unsignedp, volatilep;
int unsignedp, reversep, volatilep;
gnu_result_type = get_unpadded_type (Etype (gnat_node));
gnu_prefix = remove_conversions (gnu_prefix, true);
@ -2194,7 +2194,7 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
&& TREE_CODE (gnu_prefix) == FIELD_DECL));
get_inner_reference (gnu_prefix, &bitsize, &bitpos, &gnu_offset,
&mode, &unsignedp, &volatilep, false);
&mode, &unsignedp, &reversep, &volatilep, false);
if (TREE_CODE (gnu_prefix) == COMPONENT_REF)
{

View File

@ -957,6 +957,7 @@ make_packable_type (tree type, bool in_record)
TYPE_NAME (new_type) = TYPE_NAME (type);
TYPE_JUSTIFIED_MODULAR_P (new_type) = TYPE_JUSTIFIED_MODULAR_P (type);
TYPE_CONTAINS_TEMPLATE_P (new_type) = TYPE_CONTAINS_TEMPLATE_P (type);
TYPE_REVERSE_STORAGE_ORDER (new_type) = TYPE_REVERSE_STORAGE_ORDER (type);
if (TREE_CODE (type) == RECORD_TYPE)
TYPE_PADDING_P (new_type) = TYPE_PADDING_P (type);
@ -1175,14 +1176,15 @@ pad_type_hasher::equal (pad_type_hash *t1, pad_type_hash *t2)
type1 = t1->type;
type2 = t2->type;
/* We consider that the padded types are equivalent if they pad the same
type and have the same size, alignment and RM size. Taking the mode
into account is redundant since it is determined by the others. */
/* We consider that the padded types are equivalent if they pad the same type
and have the same size, alignment, RM size and storage order. Taking the
mode into account is redundant since it is determined by the others. */
return
TREE_TYPE (TYPE_FIELDS (type1)) == TREE_TYPE (TYPE_FIELDS (type2))
&& TYPE_SIZE (type1) == TYPE_SIZE (type2)
&& TYPE_ALIGN (type1) == TYPE_ALIGN (type2)
&& TYPE_ADA_SIZE (type1) == TYPE_ADA_SIZE (type2);
&& TYPE_ADA_SIZE (type1) == TYPE_ADA_SIZE (type2)
&& TYPE_REVERSE_STORAGE_ORDER (type1) == TYPE_REVERSE_STORAGE_ORDER (type2);
}
/* Look up the padded TYPE in the hash table and return its canonical version
@ -1452,6 +1454,31 @@ built:
return record;
}
/* Return a copy of the padded TYPE but with reverse storage order. */
tree
set_reverse_storage_order_on_pad_type (tree type)
{
tree field, canonical_pad_type;
#ifdef ENABLE_CHECKING
/* If the inner type is not scalar then the function does nothing. */
tree inner_type = TREE_TYPE (TYPE_FIELDS (type));
gcc_assert (!AGGREGATE_TYPE_P (inner_type) && !VECTOR_TYPE_P (inner_type));
#endif
/* This is required for the canonicalization. */
gcc_assert (TREE_CONSTANT (TYPE_SIZE (type)));
field = copy_node (TYPE_FIELDS (type));
type = copy_type (type);
DECL_CONTEXT (field) = type;
TYPE_FIELDS (type) = field;
TYPE_REVERSE_STORAGE_ORDER (type) = 1;
canonical_pad_type = lookup_and_insert_pad_type (type);
return canonical_pad_type ? canonical_pad_type : type;
}
/* Relate the alias sets of GNU_NEW_TYPE and GNU_OLD_TYPE according to OP.
If this is a multi-dimensional array type, do this recursively.
@ -3357,7 +3384,7 @@ gnat_types_compatible_p (tree t1, tree t2)
return 1;
/* Array types are also compatible if they are constrained and have the same
domain(s) and the same component type. */
domain(s), the same component type and the same scalar storage order. */
if (code == ARRAY_TYPE
&& (TYPE_DOMAIN (t1) == TYPE_DOMAIN (t2)
|| (TYPE_DOMAIN (t1)
@ -3368,7 +3395,8 @@ gnat_types_compatible_p (tree t1, tree t2)
TYPE_MAX_VALUE (TYPE_DOMAIN (t2)))))
&& (TREE_TYPE (t1) == TREE_TYPE (t2)
|| (TREE_CODE (TREE_TYPE (t1)) == ARRAY_TYPE
&& gnat_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))))
&& gnat_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2))))
&& TYPE_REVERSE_STORAGE_ORDER (t1) == TYPE_REVERSE_STORAGE_ORDER (t2))
return 1;
return 0;
@ -4849,17 +4877,38 @@ unchecked_convert (tree type, tree expr, bool notrunc_p)
}
/* If we are converting to an integral type whose precision is not equal
to its size, first unchecked convert to a record type that contains an
field of the given precision. Then extract the field. */
to its size, first unchecked convert to a record type that contains a
field of the given precision. Then extract the result from the field.
There is a subtlety if the source type is an aggregate type with reverse
storage order because its representation is not contiguous in the native
storage order, i.e. a direct unchecked conversion to an integral type
with N bits of precision cannot read the first N bits of the aggregate
type. To overcome it, we do an unchecked conversion to an integral type
with reverse storage order and return the resulting value. This also
ensures that the result of the unchecked conversion doesn't depend on
the endianness of the target machine, but only on the storage order of
the aggregate type.
Finally, for the sake of consistency, we do the unchecked conversion
to an integral type with reverse storage order as soon as the source
type is an aggregate type with reverse storage order, even if there
are no considerations of precision or size involved. */
else if (INTEGRAL_TYPE_P (type)
&& TYPE_RM_SIZE (type)
&& 0 != compare_tree_int (TYPE_RM_SIZE (type),
GET_MODE_BITSIZE (TYPE_MODE (type))))
&& (0 != compare_tree_int (TYPE_RM_SIZE (type),
GET_MODE_BITSIZE (TYPE_MODE (type)))
|| (AGGREGATE_TYPE_P (etype)
&& TYPE_REVERSE_STORAGE_ORDER (etype))))
{
tree rec_type = make_node (RECORD_TYPE);
unsigned HOST_WIDE_INT prec = TREE_INT_CST_LOW (TYPE_RM_SIZE (type));
tree field_type, field;
if (AGGREGATE_TYPE_P (etype))
TYPE_REVERSE_STORAGE_ORDER (rec_type)
= TYPE_REVERSE_STORAGE_ORDER (etype);
if (TYPE_UNSIGNED (type))
field_type = make_unsigned_type (prec);
else
@ -4878,11 +4927,16 @@ unchecked_convert (tree type, tree expr, bool notrunc_p)
/* Similarly if we are converting from an integral type whose precision is
not equal to its size, first copy into a field of the given precision
and unchecked convert the record type. */
and unchecked convert the record type.
The same considerations as above apply if the target type is an aggregate
type with reverse storage order and we also proceed similarly. */
else if (INTEGRAL_TYPE_P (etype)
&& TYPE_RM_SIZE (etype)
&& 0 != compare_tree_int (TYPE_RM_SIZE (etype),
GET_MODE_BITSIZE (TYPE_MODE (etype))))
&& (0 != compare_tree_int (TYPE_RM_SIZE (etype),
GET_MODE_BITSIZE (TYPE_MODE (etype)))
|| (AGGREGATE_TYPE_P (type)
&& TYPE_REVERSE_STORAGE_ORDER (type))))
{
tree rec_type = make_node (RECORD_TYPE);
unsigned HOST_WIDE_INT prec = TREE_INT_CST_LOW (TYPE_RM_SIZE (etype));
@ -4890,6 +4944,10 @@ unchecked_convert (tree type, tree expr, bool notrunc_p)
vec_alloc (v, 1);
tree field_type, field;
if (AGGREGATE_TYPE_P (type))
TYPE_REVERSE_STORAGE_ORDER (rec_type)
= TYPE_REVERSE_STORAGE_ORDER (type);
if (TYPE_UNSIGNED (etype))
field_type = make_unsigned_type (prec);
else

View File

@ -1408,11 +1408,11 @@ build_unary_op (enum tree_code op_code, tree result_type, tree operand)
HOST_WIDE_INT bitpos;
tree offset, inner;
machine_mode mode;
int unsignedp, volatilep;
int unsignedp, reversep, volatilep;
inner = get_inner_reference (operand, &bitsize, &bitpos, &offset,
&mode, &unsignedp, &volatilep,
false);
&mode, &unsignedp, &reversep,
&volatilep, false);
/* If INNER is a padding type whose field has a self-referential
size, convert to that inner type. We know the offset is zero
@ -1916,7 +1916,9 @@ gnat_build_constructor (tree type, vec<constructor_elt, va_gc> *v)
|| (TREE_CODE (type) == RECORD_TYPE
&& CONSTRUCTOR_BITFIELD_P (obj)
&& !initializer_constant_valid_for_bitfield_p (val))
|| !initializer_constant_valid_p (val, TREE_TYPE (val)))
|| !initializer_constant_valid_p (val,
TREE_TYPE (val),
TYPE_REVERSE_STORAGE_ORDER (type)))
allconstant = false;
if (!TREE_READONLY (val))
@ -2749,6 +2751,7 @@ gnat_rewrite_reference (tree ref, rewrite_fn func, void *data, tree *init)
gnat_rewrite_reference (TREE_OPERAND (ref, 0), func,
data, init),
TREE_OPERAND (ref, 1), TREE_OPERAND (ref, 2));
REF_REVERSE_STORAGE_ORDER (result) = REF_REVERSE_STORAGE_ORDER (ref);
break;
case ARRAY_REF:

View File

@ -1779,9 +1779,9 @@ instrument_derefs (gimple_stmt_iterator *iter, tree t,
HOST_WIDE_INT bitsize, bitpos;
tree offset;
machine_mode mode;
int volatilep = 0, unsignedp = 0;
tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset,
&mode, &unsignedp, &volatilep, false);
int unsignedp, reversep, volatilep = 0;
tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
&unsignedp, &reversep, &volatilep, false);
if (TREE_CODE (t) == COMPONENT_REF
&& DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)) != NULL_TREE)

View File

@ -252,14 +252,14 @@ get_object_alignment_2 (tree exp, unsigned int *alignp,
HOST_WIDE_INT bitsize, bitpos;
tree offset;
machine_mode mode;
int unsignedp, volatilep;
int unsignedp, reversep, volatilep;
unsigned int align = BITS_PER_UNIT;
bool known_alignment = false;
/* Get the innermost object and the constant (bitpos) and possibly
variable (offset) offset of the access. */
exp = get_inner_reference (exp, &bitsize, &bitpos, &offset,
&mode, &unsignedp, &volatilep, true);
exp = get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode,
&unsignedp, &reversep, &volatilep, true);
/* Extract alignment information from the innermost object and
possibly adjust bitpos and offset. */

View File

@ -1,3 +1,15 @@
2015-11-08 Eric Botcazou <ebotcazou@adacore.com>
* c-common.c (c_common_attributes): Add scalar_storage_order.
(handle_scalar_storage_order_attribute): New function.
* c-pragma.c (global_sso): New variable.
(maybe_apply_pragma_scalar_storage_order): New function.
(handle_pragma_scalar_storage_order): Likewise.
(init_pragma): Register scalar_storage_order.
* c-pragma.h (maybe_apply_pragma_scalar_storage_order): Declare.
* c.opt (Wscalar-storage-order): New warning.
(fsso-struct=): New option.
2015-11-08 Martin Sebor <msebor@redhat.com>
* c.opt (Wplacement-new): Add a period to the end of a sentence.

View File

@ -339,6 +339,8 @@ static tree handle_no_reorder_attribute (tree *, tree, tree, int,
static tree handle_const_attribute (tree *, tree, tree, int, bool *);
static tree handle_transparent_union_attribute (tree *, tree, tree,
int, bool *);
static tree handle_scalar_storage_order_attribute (tree *, tree, tree,
int, bool *);
static tree handle_constructor_attribute (tree *, tree, tree, int, bool *);
static tree handle_destructor_attribute (tree *, tree, tree, int, bool *);
static tree handle_mode_attribute (tree *, tree, tree, int, bool *);
@ -693,6 +695,8 @@ const struct attribute_spec c_common_attribute_table[] =
/* The same comments as for noreturn attributes apply to const ones. */
{ "const", 0, 0, true, false, false,
handle_const_attribute, false },
{ "scalar_storage_order", 1, 1, false, false, false,
handle_scalar_storage_order_attribute, false },
{ "transparent_union", 0, 0, false, false, false,
handle_transparent_union_attribute, false },
{ "constructor", 0, 1, true, false, false,
@ -7668,6 +7672,62 @@ handle_const_attribute (tree *node, tree name, tree ARG_UNUSED (args),
return NULL_TREE;
}
/* Handle a "scalar_storage_order" attribute; arguments as in
struct attribute_spec.handler. */
static tree
handle_scalar_storage_order_attribute (tree *node, tree name, tree args,
int flags, bool *no_add_attrs)
{
tree id = TREE_VALUE (args);
tree type;
if (TREE_CODE (*node) == TYPE_DECL
&& ! (flags & ATTR_FLAG_CXX11))
node = &TREE_TYPE (*node);
type = *node;
if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
{
error ("scalar_storage_order is not supported because endianness "
"is not uniform");
return NULL_TREE;
}
if (RECORD_OR_UNION_TYPE_P (type) && !c_dialect_cxx ())
{
bool reverse = false;
if (TREE_CODE (id) == STRING_CST
&& strcmp (TREE_STRING_POINTER (id), "big-endian") == 0)
reverse = !BYTES_BIG_ENDIAN;
else if (TREE_CODE (id) == STRING_CST
&& strcmp (TREE_STRING_POINTER (id), "little-endian") == 0)
reverse = BYTES_BIG_ENDIAN;
else
{
error ("scalar_storage_order argument must be one of \"big-endian\""
" or \"little-endian\"");
return NULL_TREE;
}
if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
{
if (reverse)
/* A type variant isn't good enough, since we don't want a cast
to such a type to be removed as a no-op. */
*node = type = build_duplicate_type (type);
}
TYPE_REVERSE_STORAGE_ORDER (type) = reverse;
return NULL_TREE;
}
warning (OPT_Wattributes, "%qE attribute ignored", name);
*no_add_attrs = true;
return NULL_TREE;
}
/* Handle a "transparent_union" attribute; arguments as in
struct attribute_spec.handler. */
@ -7680,7 +7740,6 @@ handle_transparent_union_attribute (tree *node, tree name,
*no_add_attrs = true;
if (TREE_CODE (*node) == TYPE_DECL
&& ! (flags & ATTR_FLAG_CXX11))
node = &TREE_TYPE (*node);
@ -7711,8 +7770,8 @@ handle_transparent_union_attribute (tree *node, tree name,
if (c_dialect_cxx ())
goto ignored;
/* A type variant isn't good enough, since we don't a cast
to such a type removed as a no-op. */
/* A type variant isn't good enough, since we don't want a cast
to such a type to be removed as a no-op. */
*node = type = build_duplicate_type (type);
}

View File

@ -388,6 +388,51 @@ handle_pragma_weak (cpp_reader * ARG_UNUSED (dummy))
}
}
static enum scalar_storage_order_kind global_sso;
void
maybe_apply_pragma_scalar_storage_order (tree type)
{
if (global_sso == SSO_NATIVE)
return;
gcc_assert (RECORD_OR_UNION_TYPE_P (type));
if (lookup_attribute ("scalar_storage_order", TYPE_ATTRIBUTES (type)))
return;
if (global_sso == SSO_BIG_ENDIAN)
TYPE_REVERSE_STORAGE_ORDER (type) = !BYTES_BIG_ENDIAN;
else if (global_sso == SSO_LITTLE_ENDIAN)
TYPE_REVERSE_STORAGE_ORDER (type) = BYTES_BIG_ENDIAN;
else
gcc_unreachable ();
}
static void
handle_pragma_scalar_storage_order (cpp_reader *ARG_UNUSED(dummy))
{
const char *kind_string;
enum cpp_ttype token;
tree x;
if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
error ("scalar_storage_order is not supported");
token = pragma_lex (&x);
if (token != CPP_NAME)
GCC_BAD ("missing [big-endian|little-endian|default] after %<#pragma scalar_storage_order%>");
kind_string = IDENTIFIER_POINTER (x);
if (strcmp (kind_string, "default") == 0)
global_sso = default_sso;
else if (strcmp (kind_string, "big") == 0)
global_sso = SSO_BIG_ENDIAN;
else if (strcmp (kind_string, "little") == 0)
global_sso = SSO_LITTLE_ENDIAN;
else
GCC_BAD ("expected [big-endian|little-endian|default] after %<#pragma scalar_storage_order%>");
}
/* GCC supports two #pragma directives for renaming the external
symbol associated with a declaration (DECL_ASSEMBLER_NAME), for
compatibility with the Solaris and VMS system headers. GCC also
@ -1481,6 +1526,7 @@ init_pragma (void)
c_register_pragma (0, "pack", handle_pragma_pack);
#endif
c_register_pragma (0, "weak", handle_pragma_weak);
c_register_pragma ("GCC", "visibility", handle_pragma_visibility);
c_register_pragma ("GCC", "diagnostic", handle_pragma_diagnostic);
@ -1502,6 +1548,10 @@ init_pragma (void)
REGISTER_TARGET_PRAGMAS ();
#endif
global_sso = default_sso;
c_register_pragma (0, "scalar_storage_order",
handle_pragma_scalar_storage_order);
/* Allow plugins to register their own pragmas. */
invoke_plugin_callbacks (PLUGIN_PRAGMAS, NULL);
}

View File

@ -227,6 +227,7 @@ extern void c_invoke_pragma_handler (unsigned int);
extern void maybe_apply_pragma_weak (tree);
extern void maybe_apply_pending_pragma_weaks (void);
extern tree maybe_apply_renaming_pragma (tree, tree);
extern void maybe_apply_pragma_scalar_storage_order (tree);
extern void add_to_renaming_pragma_list (tree, tree);
extern enum cpp_ttype pragma_lex (tree *, location_t *loc = NULL);

View File

@ -792,6 +792,10 @@ Wreturn-type
C ObjC C++ ObjC++ Var(warn_return_type) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
Warn whenever a function's return type defaults to \"int\" (C), or about inconsistent return types (C++).
Wscalar-storage-order
C ObjC C++ ObjC++ Init(1) Warning
Warn on suspicious constructs involving reverse scalar storage order.
Wselector
ObjC ObjC++ Var(warn_selector) Warning
Warn if a selector has multiple methods.
@ -1454,6 +1458,19 @@ Enable C++14 sized deallocation support.
fsquangle
C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
fsso-struct=
C ObjC Joined Enum(sso_struct) Var(default_sso) Init(SSO_NATIVE)
-fsso-struct=[big-endian|little-endian] Set the default scalar storage order.
Enum
Name(sso_struct) Type(enum scalar_storage_order_kind) UnknownError(unrecognized scalar storage order value %qs)
EnumValue
Enum(sso_struct) String(big-endian) Value(SSO_BIG_ENDIAN)
EnumValue
Enum(sso_struct) String(little-endian) Value(SSO_LITTLE_ENDIAN)
fstats
C++ ObjC++ Var(flag_detailed_statistics)
Display statistics accumulated during compilation.

View File

@ -1,3 +1,14 @@
2015-11-08 Eric Botcazou <ebotcazou@adacore.com>
* c-decl.c (finish_struct): If the structure has reverse storage
order, rewrite the type of array fields with scalar component. Call
maybe_apply_pragma_scalar_storage_order on entry.
* c-typeck.c (build_unary_op) <ADDR_EXPR>: Remove left-overs. Issue
errors on bit-fields and reverse SSO here and not...
(c_mark_addressable): ...here.
(output_init_element): Adjust call to initializer_constant_valid_p.
(c_build_qualified_type): Propagate TYPE_REVERSE_STORAGE_ORDER.
2015-11-06 David Malcolm <dmalcolm@redhat.com>
* c-decl.c (warn_defaults_to): Update for change in signature

View File

@ -7724,6 +7724,8 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
TYPE_FIELDS (t) = fieldlist;
maybe_apply_pragma_scalar_storage_order (t);
layout_type (t);
if (TYPE_SIZE_UNIT (t)
@ -7732,27 +7734,45 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
&& !valid_constant_size_p (TYPE_SIZE_UNIT (t)))
error ("type %qT is too large", t);
/* Give bit-fields their proper types. */
{
tree *fieldlistp = &fieldlist;
while (*fieldlistp)
if (TREE_CODE (*fieldlistp) == FIELD_DECL && DECL_INITIAL (*fieldlistp)
&& TREE_TYPE (*fieldlistp) != error_mark_node)
/* Give bit-fields their proper types and rewrite the type of array fields
with scalar component if the enclosing type has reverse storage order. */
for (tree field = fieldlist; field; field = DECL_CHAIN (field))
{
if (TREE_CODE (field) == FIELD_DECL
&& DECL_INITIAL (field)
&& TREE_TYPE (field) != error_mark_node)
{
unsigned HOST_WIDE_INT width
= tree_to_uhwi (DECL_INITIAL (*fieldlistp));
tree type = TREE_TYPE (*fieldlistp);
= tree_to_uhwi (DECL_INITIAL (field));
tree type = TREE_TYPE (field);
if (width != TYPE_PRECISION (type))
{
TREE_TYPE (*fieldlistp)
TREE_TYPE (field)
= c_build_bitfield_integer_type (width, TYPE_UNSIGNED (type));
DECL_MODE (*fieldlistp) = TYPE_MODE (TREE_TYPE (*fieldlistp));
DECL_MODE (field) = TYPE_MODE (TREE_TYPE (field));
}
DECL_INITIAL (*fieldlistp) = 0;
DECL_INITIAL (field) = 0;
}
else
fieldlistp = &DECL_CHAIN (*fieldlistp);
}
else if (TYPE_REVERSE_STORAGE_ORDER (t)
&& TREE_CODE (field) == FIELD_DECL
&& TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE)
{
tree ftype = TREE_TYPE (field);
tree ctype = strip_array_types (ftype);
if (!RECORD_OR_UNION_TYPE_P (ctype) && TYPE_MODE (ctype) != QImode)
{
tree fmain_type = TYPE_MAIN_VARIANT (ftype);
tree *typep = &fmain_type;
do {
*typep = build_distinct_type_copy (*typep);
TYPE_REVERSE_STORAGE_ORDER (*typep) = 1;
typep = &TREE_TYPE (*typep);
} while (TREE_CODE (*typep) == ARRAY_TYPE);
TREE_TYPE (field)
= c_build_qualified_type (fmain_type, TYPE_QUALS (ftype));
}
}
}
/* Now we have the truly final field list.
Store it in this type and in the variants. */

View File

@ -4169,18 +4169,10 @@ build_unary_op (location_t location,
goto return_build_unary_op;
}
/* For &x[y], return x+y */
if (TREE_CODE (arg) == ARRAY_REF)
{
tree op0 = TREE_OPERAND (arg, 0);
if (!c_mark_addressable (op0))
return error_mark_node;
}
/* Anything not already handled and not a true memory reference
or a non-lvalue array is an error. */
else if (typecode != FUNCTION_TYPE && !flag
&& !lvalue_or_else (location, arg, lv_addressof))
if (typecode != FUNCTION_TYPE && !flag
&& !lvalue_or_else (location, arg, lv_addressof))
return error_mark_node;
/* Move address operations inside C_MAYBE_CONST_EXPR to simplify
@ -4218,6 +4210,39 @@ build_unary_op (location_t location,
argtype = c_build_qualified_type (argtype, quals);
}
switch (TREE_CODE (arg))
{
case COMPONENT_REF:
if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)))
{
error ("cannot take address of bit-field %qD",
TREE_OPERAND (arg, 1));
return error_mark_node;
}
/* ... fall through ... */
case ARRAY_REF:
if (TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (TREE_OPERAND (arg, 0))))
{
if (!AGGREGATE_TYPE_P (TREE_TYPE (arg))
&& !VECTOR_TYPE_P (TREE_TYPE (arg)))
{
error ("cannot take address of scalar with reverse storage "
"order");
return error_mark_node;
}
if (TREE_CODE (TREE_TYPE (arg)) == ARRAY_TYPE
&& TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (arg)))
warning (OPT_Wscalar_storage_order, "address of array with "
"reverse scalar storage order requested");
}
default:
break;
}
if (!c_mark_addressable (arg))
return error_mark_node;
@ -4360,15 +4385,6 @@ c_mark_addressable (tree exp)
switch (TREE_CODE (x))
{
case COMPONENT_REF:
if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1)))
{
error
("cannot take address of bit-field %qD", TREE_OPERAND (x, 1));
return false;
}
/* ... fall through ... */
case ADDR_EXPR:
case ARRAY_REF:
case REALPART_EXPR:
@ -8444,7 +8460,11 @@ output_init_element (location_t loc, tree value, tree origtype,
constructor_erroneous = 1;
else if (!TREE_CONSTANT (value))
constructor_constant = 0;
else if (!initializer_constant_valid_p (value, TREE_TYPE (value))
else if (!initializer_constant_valid_p (value,
TREE_TYPE (value),
AGGREGATE_TYPE_P (constructor_type)
&& TYPE_REVERSE_STORAGE_ORDER
(constructor_type))
|| ((TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
&& DECL_C_BIT_FIELD (field)
@ -13238,6 +13258,12 @@ c_build_qualified_type (tree type, int type_quals)
= build_array_type (TYPE_CANONICAL (element_type),
domain? TYPE_CANONICAL (domain)
: NULL_TREE);
if (TYPE_REVERSE_STORAGE_ORDER (type))
{
unqualified_canon
= build_distinct_type_copy (unqualified_canon);
TYPE_REVERSE_STORAGE_ORDER (unqualified_canon) = 1;
}
TYPE_CANONICAL (t)
= c_build_qualified_type (unqualified_canon, type_quals);
}

View File

@ -1065,7 +1065,7 @@ store_unaligned_arguments_into_pseudos (struct arg_data *args, int num_actuals)
args[i].aligned_regs[j] = reg;
word = extract_bit_field (word, bitsize, 0, 1, NULL_RTX,
word_mode, word_mode);
word_mode, word_mode, false);
/* There is no need to restrict this code to loading items
in TYPE_ALIGN sized hunks. The bitfield instructions can
@ -1082,7 +1082,7 @@ store_unaligned_arguments_into_pseudos (struct arg_data *args, int num_actuals)
bytes -= bitsize / BITS_PER_UNIT;
store_bit_field (reg, bitsize, endian_correction, 0, 0,
word_mode, word);
word_mode, word, false);
}
}
}
@ -1363,7 +1363,7 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
else
copy = assign_temp (type, 1, 0);
store_expr (args[i].tree_value, copy, 0, false);
store_expr (args[i].tree_value, copy, 0, false, false);
/* Just change the const function to pure and then let
the next test clear the pure based on
@ -2084,8 +2084,8 @@ load_register_parameters (struct arg_data *args, int num_actuals,
rtx dest = gen_rtx_REG (word_mode, REGNO (reg) + nregs - 1);
unsigned int bitoff = (nregs - 1) * BITS_PER_WORD;
unsigned int bitsize = size * BITS_PER_UNIT - bitoff;
rtx x = extract_bit_field (mem, bitsize, bitoff, 1,
dest, word_mode, word_mode);
rtx x = extract_bit_field (mem, bitsize, bitoff, 1, dest,
word_mode, word_mode, false);
if (BYTES_BIG_ENDIAN)
x = expand_shift (LSHIFT_EXPR, word_mode, x,
BITS_PER_WORD - bitsize, dest, 1);

View File

@ -4374,9 +4374,10 @@ expand_debug_expr (tree exp)
machine_mode mode1;
HOST_WIDE_INT bitsize, bitpos;
tree offset;
int volatilep = 0;
tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset,
&mode1, &unsignedp, &volatilep, false);
int reversep, volatilep = 0;
tree tem
= get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode1,
&unsignedp, &reversep, &volatilep, false);
rtx orig_op0;
if (bitsize == 0)
@ -4799,9 +4800,10 @@ expand_debug_expr (tree exp)
if (handled_component_p (TREE_OPERAND (exp, 0)))
{
HOST_WIDE_INT bitoffset, bitsize, maxsize;
bool reverse;
tree decl
= get_ref_base_and_extent (TREE_OPERAND (exp, 0),
&bitoffset, &bitsize, &maxsize);
= get_ref_base_and_extent (TREE_OPERAND (exp, 0), &bitoffset,
&bitsize, &maxsize, &reverse);
if ((TREE_CODE (decl) == VAR_DECL
|| TREE_CODE (decl) == PARM_DECL
|| TREE_CODE (decl) == RESULT_DECL)

View File

@ -15705,10 +15705,10 @@ r10k_safe_mem_expr_p (tree expr, unsigned HOST_WIDE_INT offset)
HOST_WIDE_INT bitoffset, bitsize;
tree inner, var_offset;
machine_mode mode;
int unsigned_p, volatile_p;
int unsigned_p, reverse_p, volatile_p;
inner = get_inner_reference (expr, &bitsize, &bitoffset, &var_offset, &mode,
&unsigned_p, &volatile_p, false);
&unsigned_p, &reverse_p, &volatile_p, false);
if (!DECL_P (inner) || !DECL_SIZE_UNIT (inner) || var_offset)
return false;

View File

@ -6426,7 +6426,7 @@ s390_expand_atomic (machine_mode mode, enum rtx_code code,
case SET:
if (ac.aligned && MEM_P (val))
store_bit_field (new_rtx, GET_MODE_BITSIZE (mode), 0,
0, 0, SImode, val);
0, 0, SImode, val, false);
else
{
new_rtx = expand_simple_binop (SImode, AND, new_rtx, ac.modemaski,

View File

@ -1962,7 +1962,7 @@ tilegx_expand_unaligned_load (rtx dest_reg, rtx mem, HOST_WIDE_INT bitsize,
extract_bit_field (gen_lowpart (DImode, wide_result),
bitsize, bit_offset % BITS_PER_UNIT,
!sign, gen_lowpart (DImode, dest_reg),
DImode, DImode);
DImode, DImode, false);
if (extracted != dest_reg)
emit_move_insn (dest_reg, gen_lowpart (DImode, extracted));

View File

@ -1692,7 +1692,7 @@ tilepro_expand_unaligned_load (rtx dest_reg, rtx mem, HOST_WIDE_INT bitsize,
extract_bit_field (gen_lowpart (SImode, wide_result),
bitsize, bit_offset % BITS_PER_UNIT,
!sign, gen_lowpart (SImode, dest_reg),
SImode, SImode);
SImode, SImode, false);
if (extracted != dest_reg)
emit_move_insn (dest_reg, gen_lowpart (SImode, extracted));

View File

@ -2479,11 +2479,11 @@ dbxout_expand_expr (tree expr)
machine_mode mode;
HOST_WIDE_INT bitsize, bitpos;
tree offset, tem;
int volatilep = 0, unsignedp = 0;
int unsignedp, reversep, volatilep = 0;
rtx x;
tem = get_inner_reference (expr, &bitsize, &bitpos, &offset,
&mode, &unsignedp, &volatilep, true);
tem = get_inner_reference (expr, &bitsize, &bitpos, &offset, &mode,
&unsignedp, &reversep, &volatilep, true);
x = dbxout_expand_expr (tem);
if (x == NULL || !MEM_P (x))

View File

@ -6395,6 +6395,42 @@ of the structure or union is placed to minimize the memory required. When
attached to an @code{enum} definition, it indicates that the smallest
integral type should be used.
@item scalar_storage_order ("@var{endianness}")
@cindex @code{scalar_storage_order} type attribute
When attached to a @code{union} or a @code{struct}, this attribute sets
the storage order, aka endianness, of the scalar fields of the type, as
well as the array fields whose component is scalar. The supported
endianness are @code{big-endian} and @code{little-endian}. The attribute
has no effects on fields which are themselves a @code{union}, a @code{struct}
or an array whose component is a @code{union} or a @code{struct}, and it is
possible to have fields with a different scalar storage order than the
enclosing type.
This attribute is supported only for targets that use a uniform default
scalar storage order (fortunately, most of them), i.e. targets that store
the scalars either all in big-endian or all in little-endian.
Additional restrictions are enforced for types with the reverse scalar
storage order with regard to the scalar storage order of the target:
@itemize
@item Taking the address of a scalar field of a @code{union} or a
@code{struct} with reverse scalar storage order is not permitted and will
yield an error.
@item Taking the address of an array field, whose component is scalar, of
a @code{union} or a @code{struct} with reverse scalar storage order is
permitted but will yield a warning, unless @option{-Wno-scalar-storage-order}
is specified.
@item Taking the address of a @code{union} or a @code{struct} with reverse
scalar storage order is permitted.
@end itemize
These restrictions exist because the storage order attribute is lost when
the address of a scalar or the address of an array with scalar component
is taken, so storing indirectly through this address will generally not work.
The second case is nevertheless allowed to be able to perform a block copy
from or to the array.
@item transparent_union
@cindex @code{transparent_union} type attribute
@ -18432,7 +18468,7 @@ for further explanation.
* Darwin Pragmas::
* Solaris Pragmas::
* Symbol-Renaming Pragmas::
* Structure-Packing Pragmas::
* Structure-Layout Pragmas::
* Weak Pragmas::
* Diagnostic Pragmas::
* Visibility Pragmas::
@ -18708,8 +18744,8 @@ the name does not change.
always the C-language name.
@end enumerate
@node Structure-Packing Pragmas
@subsection Structure-Packing Pragmas
@node Structure-Layout Pragmas
@subsection Structure-Layout Pragmas
For compatibility with Microsoft Windows compilers, GCC supports a
set of @code{#pragma} directives that change the maximum alignment of
@ -18732,17 +18768,30 @@ multiple @code{#pragma pack(@var{n})} instances and finalized by a single
@code{#pragma pack(pop)}.
@end enumerate
Some targets, e.g.@: x86 and PowerPC, support the @code{ms_struct}
@code{#pragma} which lays out a structure as the documented
@code{__attribute__ ((ms_struct))}.
Some targets, e.g.@: x86 and PowerPC, support the @code{#pragma ms_struct}
directive which lays out structures and unions subsequently defined as the
documented @code{__attribute__ ((ms_struct))}.
@enumerate
@item @code{#pragma ms_struct on} turns on the layout for structures
declared.
@item @code{#pragma ms_struct off} turns off the layout for structures
declared.
@item @code{#pragma ms_struct on} turns on the Microsoft layout.
@item @code{#pragma ms_struct off} turns off the Microsoft layout.
@item @code{#pragma ms_struct reset} goes back to the default layout.
@end enumerate
Most targets also support the @code{#pragma scalar_storage_order} directive
which lays out structures and unions subsequently defined as the documented
@code{__attribute__ ((scalar_storage_order))}.
@enumerate
@item @code{#pragma scalar_storage_order big-endian} sets the storage order
of the scalar fields to big-endian.
@item @code{#pragma scalar_storage_order little-endian} sets the storage order
of the scalar fields to little-endian.
@item @code{#pragma scalar_storage_order default} goes back to the endianness
that was in effect when compilation started (see also command-line option
@option{-fsso-struct=@var{endianness}} @pxref{C Dialect Options}).
@end enumerate
@node Weak Pragmas
@subsection Weak Pragmas

View File

@ -169,10 +169,11 @@ in the following sections.
-aux-info @var{filename} -fallow-parameterless-variadic-functions @gol
-fno-asm -fno-builtin -fno-builtin-@var{function} @gol
-fhosted -ffreestanding -fopenacc -fopenmp -fopenmp-simd @gol
-fms-extensions -fplan9-extensions -trigraphs -traditional -traditional-cpp @gol
-fms-extensions -fplan9-extensions -fsso-struct=@var{endianness}
-fallow-single-precision -fcond-mismatch -flax-vector-conversions @gol
-fsigned-bitfields -fsigned-char @gol
-funsigned-bitfields -funsigned-char}
-funsigned-bitfields -funsigned-char @gol
-trigraphs -traditional -traditional-cpp}
@item C++ Language Options
@xref{C++ Dialect Options,,Options Controlling C++ Dialect}.
@ -278,6 +279,7 @@ Objective-C and Objective-C++ Dialects}.
-Wshift-overflow -Wshift-overflow=@var{n} @gol
-Wshift-count-negative -Wshift-count-overflow -Wshift-negative-value @gol
-Wsign-compare -Wsign-conversion -Wfloat-conversion @gol
-Wno-scalar-storage-order @gol
-Wsizeof-pointer-memaccess -Wsizeof-array-argument @gol
-Wstack-protector -Wstack-usage=@var{len} -Wstrict-aliasing @gol
-Wstrict-aliasing=n @gol -Wstrict-overflow -Wstrict-overflow=@var{n} @gol
@ -2076,6 +2078,17 @@ These options control whether a bit-field is signed or unsigned, when the
declaration does not use either @code{signed} or @code{unsigned}. By
default, such a bit-field is signed, because this is consistent: the
basic integer types such as @code{int} are signed types.
@item -fsso-struct=@var{endianness}
@opindex fsso-struct
Set the default scalar storage order of structures and unions to the
specified endianness. The accepted values are @samp{big-endian} and
@samp{little-endian}. If the option is not passed, the compiler uses
the native endianness of the target. This option is not supported for C++.
@strong{Warning:} the @option{-fsso-struct} switch causes GCC to generate
code that is not binary compatible with code generated without it if the
specified endianness is not the native endianness of the target.
@end table
@node C++ Dialect Options
@ -5113,6 +5126,11 @@ This includes conversions from real to integer, and from higher precision
real to lower precision real values. This option is also enabled by
@option{-Wconversion}.
@item -Wno-scalar-storage-order
@opindex -Wno-scalar-storage-order
@opindex -Wscalar-storage-order
Do not warn on suspicious constructs involving reverse scalar storage order.
@item -Wsized-deallocation @r{(C++ and Objective-C++ only)}
@opindex Wsized-deallocation
@opindex Wno-sized-deallocation

View File

@ -5273,9 +5273,10 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
&& TREE_CODE (TREE_OPERAND (realdecl, 0)) == ADDR_EXPR))
{
HOST_WIDE_INT maxsize;
tree innerdecl;
innerdecl
= get_ref_base_and_extent (realdecl, &bitpos, &bitsize, &maxsize);
bool reverse;
tree innerdecl
= get_ref_base_and_extent (realdecl, &bitpos, &bitsize, &maxsize,
&reverse);
if (!DECL_P (innerdecl)
|| DECL_IGNORED_P (innerdecl)
|| TREE_STATIC (innerdecl)
@ -14463,12 +14464,12 @@ loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev,
tree obj, offset;
HOST_WIDE_INT bitsize, bitpos, bytepos;
machine_mode mode;
int unsignedp, volatilep = 0;
int unsignedp, reversep, volatilep = 0;
dw_loc_list_ref list_ret = NULL, list_ret1 = NULL;
obj = get_inner_reference (TREE_OPERAND (loc, 0),
&bitsize, &bitpos, &offset, &mode,
&unsignedp, &volatilep, false);
&unsignedp, &reversep, &volatilep, false);
STRIP_NOPS (obj);
if (bitpos % BITS_PER_UNIT)
{
@ -14797,10 +14798,10 @@ loc_list_from_tree (tree loc, int want_address,
tree obj, offset;
HOST_WIDE_INT bitsize, bitpos, bytepos;
machine_mode mode;
int unsignedp, volatilep = 0;
int unsignedp, reversep, volatilep = 0;
obj = get_inner_reference (loc, &bitsize, &bitpos, &offset, &mode,
&unsignedp, &volatilep, false);
&unsignedp, &reversep, &volatilep, false);
gcc_assert (obj != loc);
@ -16102,7 +16103,7 @@ fortran_common (tree decl, HOST_WIDE_INT *value)
machine_mode mode;
HOST_WIDE_INT bitsize, bitpos;
tree offset;
int unsignedp, volatilep = 0;
int unsignedp, reversep, volatilep = 0;
/* If the decl isn't a VAR_DECL, or if it isn't static, or if
it does not have a value (the offset into the common area), or if it
@ -16118,8 +16119,8 @@ fortran_common (tree decl, HOST_WIDE_INT *value)
if (TREE_CODE (val_expr) != COMPONENT_REF)
return NULL_TREE;
cvar = get_inner_reference (val_expr, &bitsize, &bitpos, &offset,
&mode, &unsignedp, &volatilep, true);
cvar = get_inner_reference (val_expr, &bitsize, &bitpos, &offset, &mode,
&unsignedp, &reversep, &volatilep, true);
if (cvar == NULL_TREE
|| TREE_CODE (cvar) != VAR_DECL

View File

@ -48,24 +48,24 @@ static void store_fixed_bit_field (rtx, unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
rtx);
rtx, bool);
static void store_fixed_bit_field_1 (rtx, unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
rtx);
rtx, bool);
static void store_split_bit_field (rtx, unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
rtx);
rtx, bool);
static rtx extract_fixed_bit_field (machine_mode, rtx,
unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT, rtx, int);
unsigned HOST_WIDE_INT, rtx, int, bool);
static rtx extract_fixed_bit_field_1 (machine_mode, rtx,
unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT, rtx, int);
unsigned HOST_WIDE_INT, rtx, int, bool);
static rtx lshift_value (machine_mode, unsigned HOST_WIDE_INT, int);
static rtx extract_split_bit_field (rtx, unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT, int);
unsigned HOST_WIDE_INT, int, bool);
static void do_cmp_and_jump (rtx, rtx, enum rtx_code, machine_mode, rtx_code_label *);
static rtx expand_smod_pow2 (machine_mode, rtx, HOST_WIDE_INT);
static rtx expand_sdiv_pow2 (machine_mode, rtx, HOST_WIDE_INT);
@ -323,6 +323,94 @@ negate_rtx (machine_mode mode, rtx x)
return result;
}
/* Whether reverse storage order is supported on the target. */
static int reverse_storage_order_supported = -1;
/* Check whether reverse storage order is supported on the target. */
static void
check_reverse_storage_order_support (void)
{
if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
{
reverse_storage_order_supported = 0;
sorry ("reverse scalar storage order");
}
else
reverse_storage_order_supported = 1;
}
/* Whether reverse FP storage order is supported on the target. */
static int reverse_float_storage_order_supported = -1;
/* Check whether reverse FP storage order is supported on the target. */
static void
check_reverse_float_storage_order_support (void)
{
if (FLOAT_WORDS_BIG_ENDIAN != WORDS_BIG_ENDIAN)
{
reverse_float_storage_order_supported = 0;
sorry ("reverse floating-point scalar storage order");
}
else
reverse_float_storage_order_supported = 1;
}
/* Return an rtx representing value of X with reverse storage order.
MODE is the intended mode of the result,
useful if X is a CONST_INT. */
rtx
flip_storage_order (enum machine_mode mode, rtx x)
{
enum machine_mode int_mode;
rtx result;
if (mode == QImode)
return x;
if (COMPLEX_MODE_P (mode))
{
rtx real = read_complex_part (x, false);
rtx imag = read_complex_part (x, true);
real = flip_storage_order (GET_MODE_INNER (mode), real);
imag = flip_storage_order (GET_MODE_INNER (mode), imag);
return gen_rtx_CONCAT (mode, real, imag);
}
if (__builtin_expect (reverse_storage_order_supported < 0, 0))
check_reverse_storage_order_support ();
if (SCALAR_INT_MODE_P (mode))
int_mode = mode;
else
{
if (FLOAT_MODE_P (mode)
&& __builtin_expect (reverse_float_storage_order_supported < 0, 0))
check_reverse_float_storage_order_support ();
int_mode = mode_for_size (GET_MODE_PRECISION (mode), MODE_INT, 0);
if (int_mode == BLKmode)
{
sorry ("reverse storage order for %smode", GET_MODE_NAME (mode));
return x;
}
x = gen_lowpart (int_mode, x);
}
result = simplify_unary_operation (BSWAP, int_mode, x, int_mode);
if (result == 0)
result = expand_unop (int_mode, bswap_optab, x, NULL_RTX, 1);
if (int_mode != mode)
result = gen_lowpart (mode, result);
return result;
}
/* Adjust bitfield memory MEM so that it points to the first unit of mode
MODE that contains a bitfield of size BITSIZE at bit position BITNUM.
If MODE is BLKmode, return a reference to every byte in the bitfield.
@ -626,7 +714,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
unsigned HOST_WIDE_INT bitregion_start,
unsigned HOST_WIDE_INT bitregion_end,
machine_mode fieldmode,
rtx value, bool fallback_p)
rtx value, bool reverse, bool fallback_p)
{
rtx op0 = str_rtx;
rtx orig_value;
@ -642,7 +730,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
int outer_mode_size = GET_MODE_SIZE (GET_MODE (op0));
int byte_offset = 0;
/* Paradoxical subregs need special handling on big endian machines. */
/* Paradoxical subregs need special handling on big-endian machines. */
if (SUBREG_BYTE (op0) == 0 && inner_mode_size < outer_mode_size)
{
int difference = inner_mode_size - outer_mode_size;
@ -704,6 +792,8 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
sub = simplify_gen_subreg (GET_MODE (op0), value, fieldmode, 0);
if (sub)
{
if (reverse)
sub = flip_storage_order (GET_MODE (op0), sub);
emit_move_insn (op0, sub);
return true;
}
@ -714,6 +804,8 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
bitnum / BITS_PER_UNIT);
if (sub)
{
if (reverse)
value = flip_storage_order (fieldmode, value);
emit_move_insn (sub, value);
return true;
}
@ -726,6 +818,8 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
if (simple_mem_bitfield_p (op0, bitsize, bitnum, fieldmode))
{
op0 = adjust_bitfield_address (op0, fieldmode, bitnum / BITS_PER_UNIT);
if (reverse)
value = flip_storage_order (fieldmode, value);
emit_move_insn (op0, value);
return true;
}
@ -752,6 +846,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
can be done with a movstrict instruction. */
if (!MEM_P (op0)
&& !reverse
&& lowpart_bit_field_p (bitnum, bitsize, GET_MODE (op0))
&& bitsize == GET_MODE_BITSIZE (fieldmode)
&& optab_handler (movstrict_optab, fieldmode) != CODE_FOR_nothing)
@ -795,7 +890,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
be less than full.
However, only do that if the value is not BLKmode. */
unsigned int backwards = WORDS_BIG_ENDIAN && fieldmode != BLKmode;
const bool backwards = WORDS_BIG_ENDIAN && fieldmode != BLKmode;
unsigned int nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD;
unsigned int i;
rtx_insn *last;
@ -818,7 +913,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
? GET_MODE_SIZE (fieldmode) / UNITS_PER_WORD
- i - 1
: i);
unsigned int bit_offset = (backwards
unsigned int bit_offset = (backwards ^ reverse
? MAX ((int) bitsize - ((int) i + 1)
* BITS_PER_WORD,
0)
@ -828,7 +923,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
MIN (BITS_PER_WORD, bitsize - i * BITS_PER_WORD);
/* If the remaining chunk doesn't have full wordsize we have
to make sure that for big endian machines the higher order
to make sure that for big-endian machines the higher order
bits are used. */
if (new_bitsize < BITS_PER_WORD && BYTES_BIG_ENDIAN && !backwards)
value_word = simplify_expand_binop (word_mode, lshr_optab,
@ -842,7 +937,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
bitnum + bit_offset,
bitregion_start, bitregion_end,
word_mode,
value_word, fallback_p))
value_word, reverse, fallback_p))
{
delete_insns_since (last);
return false;
@ -878,7 +973,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
return false;
store_split_bit_field (op0, bitsize, bitnum, bitregion_start,
bitregion_end, value);
bitregion_end, value, reverse);
return true;
}
}
@ -889,6 +984,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
extraction_insn insv;
if (!MEM_P (op0)
&& !reverse
&& get_best_reg_extraction_insn (&insv, EP_insv,
GET_MODE_BITSIZE (GET_MODE (op0)),
fieldmode)
@ -897,7 +993,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
/* If OP0 is a memory, try copying it to a register and seeing if a
cheap register alternative is available. */
if (MEM_P (op0))
if (MEM_P (op0) && !reverse)
{
if (get_best_mem_extraction_insn (&insv, EP_insv, bitsize, bitnum,
fieldmode)
@ -917,7 +1013,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
rtx tempreg = copy_to_reg (xop0);
if (store_bit_field_1 (tempreg, bitsize, bitpos,
bitregion_start, bitregion_end,
fieldmode, orig_value, false))
fieldmode, orig_value, reverse, false))
{
emit_move_insn (xop0, tempreg);
return true;
@ -930,7 +1026,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
return false;
store_fixed_bit_field (op0, bitsize, bitnum, bitregion_start,
bitregion_end, value);
bitregion_end, value, reverse);
return true;
}
@ -943,7 +1039,9 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
These two fields are 0, if the C++ memory model does not apply,
or we are not interested in keeping track of bitfield regions.
FIELDMODE is the machine-mode of the FIELD_DECL node for this field. */
FIELDMODE is the machine-mode of the FIELD_DECL node for this field.
If REVERSE is true, the store is to be done in reverse order. */
void
store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
@ -951,7 +1049,7 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
unsigned HOST_WIDE_INT bitregion_start,
unsigned HOST_WIDE_INT bitregion_end,
machine_mode fieldmode,
rtx value)
rtx value, bool reverse)
{
/* Handle -fstrict-volatile-bitfields in the cases where it applies. */
if (strict_volatile_bitfield_p (str_rtx, bitsize, bitnum, fieldmode,
@ -965,6 +1063,8 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
{
str_rtx = adjust_bitfield_address (str_rtx, fieldmode,
bitnum / BITS_PER_UNIT);
if (reverse)
value = flip_storage_order (fieldmode, value);
gcc_assert (bitnum % BITS_PER_UNIT == 0);
emit_move_insn (str_rtx, value);
}
@ -977,7 +1077,7 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
gcc_assert (bitnum + bitsize <= GET_MODE_BITSIZE (fieldmode));
temp = copy_to_reg (str_rtx);
if (!store_bit_field_1 (temp, bitsize, bitnum, 0, 0,
fieldmode, value, true))
fieldmode, value, reverse, true))
gcc_unreachable ();
emit_move_insn (str_rtx, temp);
@ -1010,19 +1110,21 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
if (!store_bit_field_1 (str_rtx, bitsize, bitnum,
bitregion_start, bitregion_end,
fieldmode, value, true))
fieldmode, value, reverse, true))
gcc_unreachable ();
}
/* Use shifts and boolean operations to store VALUE into a bit field of
width BITSIZE in OP0, starting at bit BITNUM. */
width BITSIZE in OP0, starting at bit BITNUM.
If REVERSE is true, the store is to be done in reverse order. */
static void
store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
unsigned HOST_WIDE_INT bitnum,
unsigned HOST_WIDE_INT bitregion_start,
unsigned HOST_WIDE_INT bitregion_end,
rtx value)
rtx value, bool reverse)
{
/* There is a case not handled here:
a structure with a known alignment of just a halfword
@ -1045,14 +1147,14 @@ store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
/* The only way this should occur is if the field spans word
boundaries. */
store_split_bit_field (op0, bitsize, bitnum, bitregion_start,
bitregion_end, value);
bitregion_end, value, reverse);
return;
}
op0 = narrow_bit_field_mem (op0, mode, bitsize, bitnum, &bitnum);
}
store_fixed_bit_field_1 (op0, bitsize, bitnum, value);
store_fixed_bit_field_1 (op0, bitsize, bitnum, value, reverse);
}
/* Helper function for store_fixed_bit_field, stores
@ -1061,7 +1163,7 @@ store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
static void
store_fixed_bit_field_1 (rtx op0, unsigned HOST_WIDE_INT bitsize,
unsigned HOST_WIDE_INT bitnum,
rtx value)
rtx value, bool reverse)
{
machine_mode mode;
rtx temp;
@ -1074,7 +1176,7 @@ store_fixed_bit_field_1 (rtx op0, unsigned HOST_WIDE_INT bitsize,
/* Note that bitsize + bitnum can be greater than GET_MODE_BITSIZE (mode)
for invalid input, such as f5 from gcc.dg/pr48335-2.c. */
if (BYTES_BIG_ENDIAN)
if (reverse ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN)
/* BITNUM is the distance between our msb
and that of the containing datum.
Convert it to the distance from the lsb. */
@ -1120,6 +1222,9 @@ store_fixed_bit_field_1 (rtx op0, unsigned HOST_WIDE_INT bitsize,
bitnum, NULL_RTX, 1);
}
if (reverse)
value = flip_storage_order (mode, value);
/* Now clear the chosen bits in OP0,
except that if VALUE is -1 we need not bother. */
/* We keep the intermediates in registers to allow CSE to combine
@ -1129,8 +1234,10 @@ store_fixed_bit_field_1 (rtx op0, unsigned HOST_WIDE_INT bitsize,
if (! all_one)
{
temp = expand_binop (mode, and_optab, temp,
mask_rtx (mode, bitnum, bitsize, 1),
rtx mask = mask_rtx (mode, bitnum, bitsize, 1);
if (reverse)
mask = flip_storage_order (mode, mask);
temp = expand_binop (mode, and_optab, temp, mask,
NULL_RTX, 1, OPTAB_LIB_WIDEN);
temp = force_reg (mode, temp);
}
@ -1158,6 +1265,8 @@ store_fixed_bit_field_1 (rtx op0, unsigned HOST_WIDE_INT bitsize,
(within the word).
VALUE is the value to store.
If REVERSE is true, the store is to be done in reverse order.
This does not yet handle fields wider than BITS_PER_WORD. */
static void
@ -1165,10 +1274,9 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
unsigned HOST_WIDE_INT bitpos,
unsigned HOST_WIDE_INT bitregion_start,
unsigned HOST_WIDE_INT bitregion_end,
rtx value)
rtx value, bool reverse)
{
unsigned int unit;
unsigned int bitsdone = 0;
unsigned int unit, total_bits, bitsdone = 0;
/* Make sure UNIT isn't larger than BITS_PER_WORD, we can only handle that
much at a time. */
@ -1199,12 +1307,14 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
: word_mode, value));
}
total_bits = GET_MODE_BITSIZE (GET_MODE (value));
while (bitsdone < bitsize)
{
unsigned HOST_WIDE_INT thissize;
rtx part, word;
unsigned HOST_WIDE_INT thispos;
unsigned HOST_WIDE_INT offset;
rtx part, word;
offset = (bitpos + bitsdone) / unit;
thispos = (bitpos + bitsdone) % unit;
@ -1229,13 +1339,18 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
thissize = MIN (bitsize - bitsdone, BITS_PER_WORD);
thissize = MIN (thissize, unit - thispos);
if (BYTES_BIG_ENDIAN)
if (reverse ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN)
{
/* Fetch successively less significant portions. */
if (CONST_INT_P (value))
part = GEN_INT (((unsigned HOST_WIDE_INT) (INTVAL (value))
>> (bitsize - bitsdone - thissize))
& (((HOST_WIDE_INT) 1 << thissize) - 1));
/* Likewise, but the source is little-endian. */
else if (reverse)
part = extract_fixed_bit_field (word_mode, value, thissize,
bitsize - bitsdone - thissize,
NULL_RTX, 1, false);
else
{
int total_bits = GET_MODE_BITSIZE (GET_MODE (value));
@ -1244,7 +1359,7 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
endianness compensation) to fetch the piece we want. */
part = extract_fixed_bit_field (word_mode, value, thissize,
total_bits - bitsize + bitsdone,
NULL_RTX, 1);
NULL_RTX, 1, false);
}
}
else
@ -1254,9 +1369,14 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
part = GEN_INT (((unsigned HOST_WIDE_INT) (INTVAL (value))
>> bitsdone)
& (((HOST_WIDE_INT) 1 << thissize) - 1));
/* Likewise, but the source is big-endian. */
else if (reverse)
part = extract_fixed_bit_field (word_mode, value, thissize,
total_bits - bitsdone - thissize,
NULL_RTX, 1, false);
else
part = extract_fixed_bit_field (word_mode, value, thissize,
bitsdone, NULL_RTX, 1);
bitsdone, NULL_RTX, 1, false);
}
/* If OP0 is a register, then handle OFFSET here.
@ -1294,7 +1414,8 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
it is just an out-of-bounds access. Ignore it. */
if (word != const0_rtx)
store_fixed_bit_field (word, thissize, offset * unit + thispos,
bitregion_start, bitregion_end, part);
bitregion_start, bitregion_end, part,
reverse);
bitsdone += thissize;
}
}
@ -1419,7 +1540,7 @@ static rtx
extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
unsigned HOST_WIDE_INT bitnum, int unsignedp, rtx target,
machine_mode mode, machine_mode tmode,
bool fallback_p)
bool reverse, bool fallback_p)
{
rtx op0 = str_rtx;
machine_mode int_mode;
@ -1445,6 +1566,8 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
&& bitnum == 0
&& bitsize == GET_MODE_BITSIZE (GET_MODE (op0)))
{
if (reverse)
op0 = flip_storage_order (mode, op0);
/* We're trying to extract a full register from itself. */
return op0;
}
@ -1561,6 +1684,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
as the least significant bit of the value is the least significant
bit of either OP0 or a word of OP0. */
if (!MEM_P (op0)
&& !reverse
&& lowpart_bit_field_p (bitnum, bitsize, GET_MODE (op0))
&& bitsize == GET_MODE_BITSIZE (mode1)
&& TRULY_NOOP_TRUNCATION_MODES_P (mode1, GET_MODE (op0)))
@ -1576,6 +1700,8 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
if (simple_mem_bitfield_p (op0, bitsize, bitnum, mode1))
{
op0 = adjust_bitfield_address (op0, mode1, bitnum / BITS_PER_UNIT);
if (reverse)
op0 = flip_storage_order (mode1, op0);
return convert_extracted_bit_field (op0, mode, tmode, unsignedp);
}
@ -1588,7 +1714,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
This is because the most significant word is the one which may
be less than full. */
unsigned int backwards = WORDS_BIG_ENDIAN;
const bool backwards = WORDS_BIG_ENDIAN;
unsigned int nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD;
unsigned int i;
rtx_insn *last;
@ -1615,7 +1741,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
? GET_MODE_SIZE (GET_MODE (target)) / UNITS_PER_WORD - i - 1
: i);
/* Offset from start of field in OP0. */
unsigned int bit_offset = (backwards
unsigned int bit_offset = (backwards ^ reverse
? MAX ((int) bitsize - ((int) i + 1)
* BITS_PER_WORD,
0)
@ -1625,7 +1751,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
= extract_bit_field_1 (op0, MIN (BITS_PER_WORD,
bitsize - i * BITS_PER_WORD),
bitnum + bit_offset, 1, target_part,
mode, word_mode, fallback_p);
mode, word_mode, reverse, fallback_p);
gcc_assert (target_part);
if (!result_part)
@ -1675,7 +1801,8 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
{
if (!fallback_p)
return NULL_RTX;
target = extract_split_bit_field (op0, bitsize, bitnum, unsignedp);
target = extract_split_bit_field (op0, bitsize, bitnum, unsignedp,
reverse);
return convert_extracted_bit_field (target, mode, tmode, unsignedp);
}
}
@ -1685,6 +1812,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
enum extraction_pattern pattern = unsignedp ? EP_extzv : EP_extv;
extraction_insn extv;
if (!MEM_P (op0)
&& !reverse
/* ??? We could limit the structure size to the part of OP0 that
contains the field, with appropriate checks for endianness
and TRULY_NOOP_TRUNCATION. */
@ -1701,7 +1829,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
/* If OP0 is a memory, try copying it to a register and seeing if a
cheap register alternative is available. */
if (MEM_P (op0))
if (MEM_P (op0) & !reverse)
{
if (get_best_mem_extraction_insn (&extv, pattern, bitsize, bitnum,
tmode))
@ -1726,7 +1854,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
xop0 = copy_to_reg (xop0);
rtx result = extract_bit_field_1 (xop0, bitsize, bitpos,
unsignedp, target,
mode, tmode, false);
mode, tmode, reverse, false);
if (result)
return result;
delete_insns_since (last);
@ -1744,9 +1872,21 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
/* Should probably push op0 out to memory and then do a load. */
gcc_assert (int_mode != BLKmode);
target = extract_fixed_bit_field (int_mode, op0, bitsize, bitnum,
target, unsignedp);
return convert_extracted_bit_field (target, mode, tmode, unsignedp);
target = extract_fixed_bit_field (int_mode, op0, bitsize, bitnum, target,
unsignedp, reverse);
/* Complex values must be reversed piecewise, so we need to undo the global
reversal, convert to the complex mode and reverse again. */
if (reverse && COMPLEX_MODE_P (tmode))
{
target = flip_storage_order (int_mode, target);
target = convert_extracted_bit_field (target, mode, tmode, unsignedp);
target = flip_storage_order (tmode, target);
}
else
target = convert_extracted_bit_field (target, mode, tmode, unsignedp);
return target;
}
/* Generate code to extract a byte-field from STR_RTX
@ -1760,6 +1900,8 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
TMODE is the mode the caller would like the value to have;
but the value may be returned with type MODE instead.
If REVERSE is true, the extraction is to be done in reverse order.
If a TARGET is specified and we can store in it at no extra cost,
we do so, and return TARGET.
Otherwise, we return a REG of mode TMODE or MODE, with TMODE preferred
@ -1768,7 +1910,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
rtx
extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
unsigned HOST_WIDE_INT bitnum, int unsignedp, rtx target,
machine_mode mode, machine_mode tmode)
machine_mode mode, machine_mode tmode, bool reverse)
{
machine_mode mode1;
@ -1790,6 +1932,8 @@ extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
{
rtx result = adjust_bitfield_address (str_rtx, mode1,
bitnum / BITS_PER_UNIT);
if (reverse)
result = flip_storage_order (mode1, result);
gcc_assert (bitnum % BITS_PER_UNIT == 0);
return convert_extracted_bit_field (result, mode, tmode, unsignedp);
}
@ -1801,13 +1945,15 @@ extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
}
return extract_bit_field_1 (str_rtx, bitsize, bitnum, unsignedp,
target, mode, tmode, true);
target, mode, tmode, reverse, true);
}
/* Use shifts and boolean operations to extract a field of BITSIZE bits
from bit BITNUM of OP0.
UNSIGNEDP is nonzero for an unsigned bit field (don't sign-extend value).
If REVERSE is true, the extraction is to be done in reverse order.
If TARGET is nonzero, attempts to store the value there
and return TARGET, but this is not guaranteed.
If TARGET is not used, create a pseudo-reg of mode TMODE for the value. */
@ -1816,7 +1962,7 @@ static rtx
extract_fixed_bit_field (machine_mode tmode, rtx op0,
unsigned HOST_WIDE_INT bitsize,
unsigned HOST_WIDE_INT bitnum, rtx target,
int unsignedp)
int unsignedp, bool reverse)
{
if (MEM_P (op0))
{
@ -1827,13 +1973,14 @@ extract_fixed_bit_field (machine_mode tmode, rtx op0,
if (mode == VOIDmode)
/* The only way this should occur is if the field spans word
boundaries. */
return extract_split_bit_field (op0, bitsize, bitnum, unsignedp);
return extract_split_bit_field (op0, bitsize, bitnum, unsignedp,
reverse);
op0 = narrow_bit_field_mem (op0, mode, bitsize, bitnum, &bitnum);
}
return extract_fixed_bit_field_1 (tmode, op0, bitsize, bitnum,
target, unsignedp);
target, unsignedp, reverse);
}
/* Helper function for extract_fixed_bit_field, extracts
@ -1843,7 +1990,7 @@ static rtx
extract_fixed_bit_field_1 (machine_mode tmode, rtx op0,
unsigned HOST_WIDE_INT bitsize,
unsigned HOST_WIDE_INT bitnum, rtx target,
int unsignedp)
int unsignedp, bool reverse)
{
machine_mode mode = GET_MODE (op0);
gcc_assert (SCALAR_INT_MODE_P (mode));
@ -1852,13 +1999,15 @@ extract_fixed_bit_field_1 (machine_mode tmode, rtx op0,
for invalid input, such as extract equivalent of f5 from
gcc.dg/pr48335-2.c. */
if (BYTES_BIG_ENDIAN)
if (reverse ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN)
/* BITNUM is the distance between our msb and that of OP0.
Convert it to the distance from the lsb. */
bitnum = GET_MODE_BITSIZE (mode) - bitsize - bitnum;
/* Now BITNUM is always the distance between the field's lsb and that of OP0.
We have reduced the big-endian case to the little-endian case. */
if (reverse)
op0 = flip_storage_order (mode, op0);
if (unsignedp)
{
@ -1930,11 +2079,14 @@ lshift_value (machine_mode mode, unsigned HOST_WIDE_INT value,
OP0 is the REG, SUBREG or MEM rtx for the first of the two words.
BITSIZE is the field width; BITPOS, position of its first bit, in the word.
UNSIGNEDP is 1 if should zero-extend the contents; else sign-extend. */
UNSIGNEDP is 1 if should zero-extend the contents; else sign-extend.
If REVERSE is true, the extraction is to be done in reverse order. */
static rtx
extract_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
unsigned HOST_WIDE_INT bitpos, int unsignedp)
unsigned HOST_WIDE_INT bitpos, int unsignedp,
bool reverse)
{
unsigned int unit;
unsigned int bitsdone = 0;
@ -1989,11 +2141,11 @@ extract_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
whose meaning is determined by BYTES_PER_UNIT.
OFFSET is in UNITs, and UNIT is in bits. */
part = extract_fixed_bit_field (word_mode, word, thissize,
offset * unit + thispos, 0, 1);
offset * unit + thispos, 0, 1, reverse);
bitsdone += thissize;
/* Shift this part into place for the result. */
if (BYTES_BIG_ENDIAN)
if (reverse ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN)
{
if (bitsize != bitsdone)
part = expand_shift (LSHIFT_EXPR, word_mode, part,

View File

@ -676,6 +676,10 @@ extern rtx emit_cstore (rtx target, enum insn_code icode, enum rtx_code code,
May emit insns. */
extern rtx negate_rtx (machine_mode, rtx);
/* Arguments MODE, RTX: return an rtx for the flipping of that value.
May emit insns. */
extern rtx flip_storage_order (enum machine_mode, rtx);
/* Expand a logical AND operation. */
extern rtx expand_and (machine_mode, rtx, rtx, rtx);
@ -707,10 +711,10 @@ extern void store_bit_field (rtx, unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
machine_mode, rtx);
machine_mode, rtx, bool);
extern rtx extract_bit_field (rtx, unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT, int, rtx,
machine_mode, machine_mode);
machine_mode, machine_mode, bool);
extern rtx extract_low_bits (machine_mode, machine_mode, rtx);
extern rtx expand_mult (machine_mode, rtx, rtx, rtx, int);
extern rtx expand_mult_highpart_adjust (machine_mode, rtx, rtx, rtx, rtx, int);

View File

@ -121,11 +121,11 @@ static rtx_insn *compress_float_constant (rtx, rtx);
static rtx get_subtarget (rtx);
static void store_constructor_field (rtx, unsigned HOST_WIDE_INT,
HOST_WIDE_INT, machine_mode,
tree, int, alias_set_type);
static void store_constructor (tree, rtx, int, HOST_WIDE_INT);
tree, int, alias_set_type, bool);
static void store_constructor (tree, rtx, int, HOST_WIDE_INT, bool);
static rtx store_field (rtx, HOST_WIDE_INT, HOST_WIDE_INT,
unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
machine_mode, tree, alias_set_type, bool);
machine_mode, tree, alias_set_type, bool, bool);
static unsigned HOST_WIDE_INT highest_pow2_factor_for_target (const_tree, const_tree);
@ -1678,7 +1678,7 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, int ssize)
&& (!REG_P (tmps[i]) || GET_MODE (tmps[i]) != mode))
tmps[i] = extract_bit_field (tmps[i], bytelen * BITS_PER_UNIT,
(bytepos % slen0) * BITS_PER_UNIT,
1, NULL_RTX, mode, mode);
1, NULL_RTX, mode, mode, false);
}
else
{
@ -1688,7 +1688,7 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, int ssize)
mem = assign_stack_temp (GET_MODE (src), slen);
emit_move_insn (mem, src);
tmps[i] = extract_bit_field (mem, bytelen * BITS_PER_UNIT,
0, 1, NULL_RTX, mode, mode);
0, 1, NULL_RTX, mode, mode, false);
}
}
/* FIXME: A SIMD parallel will eventually lead to a subreg of a
@ -1731,7 +1731,7 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, int ssize)
else
tmps[i] = extract_bit_field (src, bytelen * BITS_PER_UNIT,
bytepos * BITS_PER_UNIT, 1, NULL_RTX,
mode, mode);
mode, mode, false);
if (shift)
tmps[i] = expand_shift (LSHIFT_EXPR, mode, tmps[i],
@ -2039,7 +2039,7 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
store_bit_field (dest,
adj_bytelen * BITS_PER_UNIT, bytepos * BITS_PER_UNIT,
bytepos * BITS_PER_UNIT, ssize * BITS_PER_UNIT - 1,
VOIDmode, tmps[i]);
VOIDmode, tmps[i], false);
}
/* Optimize the access just a bit. */
@ -2052,7 +2052,7 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
else
store_bit_field (dest, bytelen * BITS_PER_UNIT, bytepos * BITS_PER_UNIT,
0, 0, mode, tmps[i]);
0, 0, mode, tmps[i], false);
}
/* Copy from the pseudo into the (probable) hard reg. */
@ -2182,7 +2182,9 @@ copy_blkmode_from_reg (rtx target, rtx srcreg, tree type)
store_bit_field (dst, bitsize, bitpos % BITS_PER_WORD, 0, 0, copy_mode,
extract_bit_field (src, bitsize,
xbitpos % BITS_PER_WORD, 1,
NULL_RTX, copy_mode, copy_mode));
NULL_RTX, copy_mode, copy_mode,
false),
false);
}
}
@ -2259,7 +2261,9 @@ copy_blkmode_to_reg (machine_mode mode, tree src)
0, 0, word_mode,
extract_bit_field (src_word, bitsize,
bitpos % BITS_PER_WORD, 1,
NULL_RTX, word_mode, word_mode));
NULL_RTX, word_mode, word_mode,
false),
false);
}
if (mode == BLKmode)
@ -3004,7 +3008,8 @@ write_complex_part (rtx cplx, rtx val, bool imag_p)
gcc_assert (MEM_P (cplx) && ibitsize < BITS_PER_WORD);
}
store_bit_field (cplx, ibitsize, imag_p ? ibitsize : 0, 0, 0, imode, val);
store_bit_field (cplx, ibitsize, imag_p ? ibitsize : 0, 0, 0, imode, val,
false);
}
/* Extract one of the components of the complex value CPLX. Extract the
@ -3067,7 +3072,7 @@ read_complex_part (rtx cplx, bool imag_p)
}
return extract_bit_field (cplx, ibitsize, imag_p ? ibitsize : 0,
true, NULL_RTX, imode, imode);
true, NULL_RTX, imode, imode, false);
}
/* A subroutine of emit_move_insn_1. Yet another lowpart generator.
@ -4457,7 +4462,7 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
unsigned HOST_WIDE_INT bitregion_start,
unsigned HOST_WIDE_INT bitregion_end,
machine_mode mode1, rtx str_rtx,
tree to, tree src)
tree to, tree src, bool reverse)
{
machine_mode str_mode = GET_MODE (str_rtx);
unsigned int str_bitsize = GET_MODE_BITSIZE (str_mode);
@ -4530,6 +4535,8 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
}
else if (!REG_P (str_rtx) && GET_CODE (str_rtx) != SUBREG)
return false;
else
gcc_assert (!reverse);
/* If the bit field covers the whole REG/MEM, store_field
will likely generate better code. */
@ -4540,7 +4547,7 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
if (bitpos + bitsize > str_bitsize)
return false;
if (BYTES_BIG_ENDIAN)
if (reverse ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN)
bitpos = str_bitsize - bitpos - bitsize;
switch (code)
@ -4553,7 +4560,7 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
We might win by one instruction for the other bitfields
too if insv/extv instructions aren't used, so that
can be added later. */
if (bitpos + bitsize != str_bitsize
if ((reverse || bitpos + bitsize != str_bitsize)
&& (bitsize != 1 || TREE_CODE (op1) != INTEGER_CST))
break;
@ -4571,13 +4578,17 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
set_mem_expr (str_rtx, 0);
}
binop = code == PLUS_EXPR ? add_optab : sub_optab;
if (bitsize == 1 && bitpos + bitsize != str_bitsize)
if (bitsize == 1 && (reverse || bitpos + bitsize != str_bitsize))
{
value = expand_and (str_mode, value, const1_rtx, NULL);
binop = xor_optab;
}
else
binop = code == PLUS_EXPR ? add_optab : sub_optab;
value = expand_shift (LSHIFT_EXPR, str_mode, value, bitpos, NULL_RTX, 1);
if (reverse)
value = flip_storage_order (str_mode, value);
result = expand_binop (str_mode, binop, str_rtx,
value, str_rtx, 1, OPTAB_WIDEN);
if (result != str_rtx)
@ -4610,6 +4621,8 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
value = expand_and (str_mode, value, mask, NULL_RTX);
}
value = expand_shift (LSHIFT_EXPR, str_mode, value, bitpos, NULL_RTX, 1);
if (reverse)
value = flip_storage_order (str_mode, value);
result = expand_binop (str_mode, binop, str_rtx,
value, str_rtx, 1, OPTAB_WIDEN);
if (result != str_rtx)
@ -4664,10 +4677,10 @@ get_bit_range (unsigned HOST_WIDE_INT *bitstart,
machine_mode rmode;
HOST_WIDE_INT rbitsize, rbitpos;
tree roffset;
int unsignedp;
int volatilep = 0;
int unsignedp, reversep, volatilep = 0;
get_inner_reference (TREE_OPERAND (exp, 0), &rbitsize, &rbitpos,
&roffset, &rmode, &unsignedp, &volatilep, false);
&roffset, &rmode, &unsignedp, &reversep,
&volatilep, false);
if ((rbitpos % BITS_PER_UNIT) != 0)
{
*bitstart = *bitend = 0;
@ -4783,6 +4796,8 @@ expand_assignment (tree to, tree from, bool nontemporal)
reg = expand_expr (from, NULL_RTX, VOIDmode, EXPAND_NORMAL);
reg = force_not_mem (reg);
mem = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_WRITE);
if (TREE_CODE (to) == MEM_REF && REF_REVERSE_STORAGE_ORDER (to))
reg = flip_storage_order (mode, reg);
if (icode != CODE_FOR_nothing)
{
@ -4795,7 +4810,8 @@ expand_assignment (tree to, tree from, bool nontemporal)
expand_insn (icode, 2, ops);
}
else
store_bit_field (mem, GET_MODE_BITSIZE (mode), 0, 0, 0, mode, reg);
store_bit_field (mem, GET_MODE_BITSIZE (mode), 0, 0, 0, mode, reg,
false);
return;
}
@ -4806,7 +4822,8 @@ expand_assignment (tree to, tree from, bool nontemporal)
problem. Same for (partially) storing into a non-memory object. */
if (handled_component_p (to)
|| (TREE_CODE (to) == MEM_REF
&& mem_ref_refers_to_non_mem_p (to))
&& (REF_REVERSE_STORAGE_ORDER (to)
|| mem_ref_refers_to_non_mem_p (to)))
|| TREE_CODE (TREE_TYPE (to)) == ARRAY_TYPE)
{
machine_mode mode1;
@ -4814,13 +4831,12 @@ expand_assignment (tree to, tree from, bool nontemporal)
unsigned HOST_WIDE_INT bitregion_start = 0;
unsigned HOST_WIDE_INT bitregion_end = 0;
tree offset;
int unsignedp;
int volatilep = 0;
int unsignedp, reversep, volatilep = 0;
tree tem;
push_temp_slots ();
tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1,
&unsignedp, &volatilep, true);
&unsignedp, &reversep, &volatilep, true);
/* Make sure bitpos is not negative, it can wreak havoc later. */
if (bitpos < 0)
@ -4939,22 +4955,22 @@ expand_assignment (tree to, tree from, bool nontemporal)
if (COMPLEX_MODE_P (TYPE_MODE (TREE_TYPE (from)))
&& bitpos == 0
&& bitsize == mode_bitsize)
result = store_expr (from, to_rtx, false, nontemporal);
result = store_expr (from, to_rtx, false, nontemporal, reversep);
else if (bitsize == mode_bitsize / 2
&& (bitpos == 0 || bitpos == mode_bitsize / 2))
result = store_expr (from, XEXP (to_rtx, bitpos != 0), false,
nontemporal);
nontemporal, reversep);
else if (bitpos + bitsize <= mode_bitsize / 2)
result = store_field (XEXP (to_rtx, 0), bitsize, bitpos,
bitregion_start, bitregion_end,
mode1, from,
get_alias_set (to), nontemporal);
mode1, from, get_alias_set (to),
nontemporal, reversep);
else if (bitpos >= mode_bitsize / 2)
result = store_field (XEXP (to_rtx, 1), bitsize,
bitpos - mode_bitsize / 2,
bitregion_start, bitregion_end,
mode1, from,
get_alias_set (to), nontemporal);
mode1, from, get_alias_set (to),
nontemporal, reversep);
else if (bitpos == 0 && bitsize == mode_bitsize)
{
rtx from_rtx;
@ -4974,8 +4990,8 @@ expand_assignment (tree to, tree from, bool nontemporal)
write_complex_part (temp, XEXP (to_rtx, 1), true);
result = store_field (temp, bitsize, bitpos,
bitregion_start, bitregion_end,
mode1, from,
get_alias_set (to), nontemporal);
mode1, from, get_alias_set (to),
nontemporal, reversep);
emit_move_insn (XEXP (to_rtx, 0), read_complex_part (temp, false));
emit_move_insn (XEXP (to_rtx, 1), read_complex_part (temp, true));
}
@ -4994,14 +5010,14 @@ expand_assignment (tree to, tree from, bool nontemporal)
if (optimize_bitfield_assignment_op (bitsize, bitpos,
bitregion_start, bitregion_end,
mode1,
to_rtx, to, from))
mode1, to_rtx, to, from,
reversep))
result = NULL;
else
result = store_field (to_rtx, bitsize, bitpos,
bitregion_start, bitregion_end,
mode1, from,
get_alias_set (to), nontemporal);
mode1, from, get_alias_set (to),
nontemporal, reversep);
}
if (result)
@ -5155,7 +5171,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
/* Compute FROM and store the value in the rtx we got. */
push_temp_slots ();
result = store_expr_with_bounds (from, to_rtx, 0, nontemporal, to);
result = store_expr_with_bounds (from, to_rtx, 0, nontemporal, false, to);
preserve_temp_slots (result);
pop_temp_slots ();
return;
@ -5194,12 +5210,14 @@ emit_storent_insn (rtx to, rtx from)
If NONTEMPORAL is true, try using a nontemporal store instruction.
If REVERSE is true, the store is to be done in reverse order.
If BTARGET is not NULL then computed bounds of EXP are
associated with BTARGET. */
rtx
store_expr_with_bounds (tree exp, rtx target, int call_param_p,
bool nontemporal, tree btarget)
bool nontemporal, bool reverse, tree btarget)
{
rtx temp;
rtx alt_rtl = NULL_RTX;
@ -5221,7 +5239,8 @@ store_expr_with_bounds (tree exp, rtx target, int call_param_p,
expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
call_param_p ? EXPAND_STACK_PARM : EXPAND_NORMAL);
return store_expr_with_bounds (TREE_OPERAND (exp, 1), target,
call_param_p, nontemporal, btarget);
call_param_p, nontemporal, reverse,
btarget);
}
else if (TREE_CODE (exp) == COND_EXPR && GET_MODE (target) == BLKmode)
{
@ -5236,12 +5255,12 @@ store_expr_with_bounds (tree exp, rtx target, int call_param_p,
NO_DEFER_POP;
jumpifnot (TREE_OPERAND (exp, 0), lab1, -1);
store_expr_with_bounds (TREE_OPERAND (exp, 1), target, call_param_p,
nontemporal, btarget);
nontemporal, reverse, btarget);
emit_jump_insn (targetm.gen_jump (lab2));
emit_barrier ();
emit_label (lab1);
store_expr_with_bounds (TREE_OPERAND (exp, 2), target, call_param_p,
nontemporal, btarget);
nontemporal, reverse, btarget);
emit_label (lab2);
OK_DEFER_POP;
@ -5380,9 +5399,9 @@ store_expr_with_bounds (tree exp, rtx target, int call_param_p,
rtx tmp_target;
normal_expr:
/* If we want to use a nontemporal store, force the value to
register first. */
tmp_target = nontemporal ? NULL_RTX : target;
/* If we want to use a nontemporal or a reverse order store, force the
value into a register first. */
tmp_target = nontemporal || reverse ? NULL_RTX : target;
temp = expand_expr_real (exp, tmp_target, GET_MODE (target),
(call_param_p
? EXPAND_STACK_PARM : EXPAND_NORMAL),
@ -5457,7 +5476,7 @@ store_expr_with_bounds (tree exp, rtx target, int call_param_p,
else
store_bit_field (target,
INTVAL (expr_size (exp)) * BITS_PER_UNIT,
0, 0, 0, GET_MODE (temp), temp);
0, 0, 0, GET_MODE (temp), temp, reverse);
}
else
convert_move (target, temp, TYPE_UNSIGNED (TREE_TYPE (exp)));
@ -5556,6 +5575,8 @@ store_expr_with_bounds (tree exp, rtx target, int call_param_p,
;
else
{
if (reverse)
temp = flip_storage_order (GET_MODE (target), temp);
temp = force_operand (temp, target);
if (temp != target)
emit_move_insn (target, temp);
@ -5567,9 +5588,11 @@ store_expr_with_bounds (tree exp, rtx target, int call_param_p,
/* Same as store_expr_with_bounds but ignoring bounds of EXP. */
rtx
store_expr (tree exp, rtx target, int call_param_p, bool nontemporal)
store_expr (tree exp, rtx target, int call_param_p, bool nontemporal,
bool reverse)
{
return store_expr_with_bounds (exp, target, call_param_p, nontemporal, NULL);
return store_expr_with_bounds (exp, target, call_param_p, nontemporal,
reverse, NULL);
}
/* Return true if field F of structure TYPE is a flexible array. */
@ -5789,8 +5812,12 @@ categorize_ctor_elements_1 (const_tree ctor, HOST_WIDE_INT *p_nz_elts,
init_elts += mult * tc;
if (const_from_elts_p && const_p)
const_p = initializer_constant_valid_p (value, elt_type)
!= NULL_TREE;
const_p
= initializer_constant_valid_p (value,
elt_type,
TYPE_REVERSE_STORAGE_ORDER
(TREE_TYPE (ctor)))
!= NULL_TREE;
}
break;
}
@ -5895,6 +5922,7 @@ all_zeros_p (const_tree exp)
TARGET, BITSIZE, BITPOS, MODE, EXP are as for store_field.
CLEARED is as for store_constructor.
ALIAS_SET is the alias set to use for any stores.
If REVERSE is true, the store is to be done in reverse order.
This provides a recursive shortcut back to store_constructor when it isn't
necessary to go through store_field. This is so that we can pass through
@ -5904,7 +5932,8 @@ all_zeros_p (const_tree exp)
static void
store_constructor_field (rtx target, unsigned HOST_WIDE_INT bitsize,
HOST_WIDE_INT bitpos, machine_mode mode,
tree exp, int cleared, alias_set_type alias_set)
tree exp, int cleared,
alias_set_type alias_set, bool reverse)
{
if (TREE_CODE (exp) == CONSTRUCTOR
/* We can only call store_constructor recursively if the size and
@ -5933,10 +5962,12 @@ store_constructor_field (rtx target, unsigned HOST_WIDE_INT bitsize,
set_mem_alias_set (target, alias_set);
}
store_constructor (exp, target, cleared, bitsize / BITS_PER_UNIT);
store_constructor (exp, target, cleared, bitsize / BITS_PER_UNIT,
reverse);
}
else
store_field (target, bitsize, bitpos, 0, 0, mode, exp, alias_set, false);
store_field (target, bitsize, bitpos, 0, 0, mode, exp, alias_set, false,
reverse);
}
@ -5962,10 +5993,12 @@ fields_length (const_tree type)
CLEARED is true if TARGET is known to have been zero'd.
SIZE is the number of bytes of TARGET we are allowed to modify: this
may not be the same as the size of EXP if we are assigning to a field
which has been packed to exclude padding bits. */
which has been packed to exclude padding bits.
If REVERSE is true, the store is to be done in reverse order. */
static void
store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size,
bool reverse)
{
tree type = TREE_TYPE (exp);
HOST_WIDE_INT exp_size = int_size_in_bytes (type);
@ -5979,6 +6012,9 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
unsigned HOST_WIDE_INT idx;
tree field, value;
/* The storage order is specified for every aggregate type. */
reverse = TYPE_REVERSE_STORAGE_ORDER (type);
/* If size is zero or the target is already cleared, do nothing. */
if (size == 0 || cleared)
cleared = 1;
@ -6122,7 +6158,8 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
store_constructor_field (to_rtx, bitsize, bitpos, mode,
value, cleared,
get_alias_set (TREE_TYPE (field)));
get_alias_set (TREE_TYPE (field)),
reverse);
}
break;
}
@ -6137,6 +6174,9 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
HOST_WIDE_INT minelt = 0;
HOST_WIDE_INT maxelt = 0;
/* The storage order is specified for every aggregate type. */
reverse = TYPE_REVERSE_STORAGE_ORDER (type);
domain = TYPE_DOMAIN (type);
const_bounds_p = (TYPE_MIN_VALUE (domain)
&& TYPE_MAX_VALUE (domain)
@ -6277,7 +6317,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
store_constructor_field
(target, bitsize, bitpos, mode, value, cleared,
get_alias_set (elttype));
get_alias_set (elttype), reverse);
}
}
else
@ -6292,7 +6332,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
VAR_DECL, NULL_TREE, domain);
index_r = gen_reg_rtx (promote_decl_mode (index, NULL));
SET_DECL_RTL (index, index_r);
store_expr (lo_index, index_r, 0, false);
store_expr (lo_index, index_r, 0, false, reverse);
/* Build the head of the loop. */
do_pending_stack_adjust ();
@ -6317,9 +6357,9 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
xtarget = adjust_address (xtarget, mode, 0);
if (TREE_CODE (value) == CONSTRUCTOR)
store_constructor (value, xtarget, cleared,
bitsize / BITS_PER_UNIT);
bitsize / BITS_PER_UNIT, reverse);
else
store_expr (value, xtarget, 0, false);
store_expr (value, xtarget, 0, false, reverse);
/* Generate a conditional jump to exit the loop. */
exit_cond = build2 (LT_EXPR, integer_type_node,
@ -6362,7 +6402,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
expand_normal (position),
highest_pow2_factor (position));
xtarget = adjust_address (xtarget, mode, 0);
store_expr (value, xtarget, 0, false);
store_expr (value, xtarget, 0, false, reverse);
}
else
{
@ -6380,7 +6420,8 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
MEM_KEEP_ALIAS_SET_P (target) = 1;
}
store_constructor_field (target, bitsize, bitpos, mode, value,
cleared, get_alias_set (elttype));
cleared, get_alias_set (elttype),
reverse);
}
}
break;
@ -6513,7 +6554,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
: eltmode;
bitpos = eltpos * elt_size;
store_constructor_field (target, bitsize, bitpos, value_mode,
value, cleared, alias);
value, cleared, alias, reverse);
}
}
@ -6546,14 +6587,16 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
(in general) be different from that for TARGET, since TARGET is a
reference to the containing structure.
If NONTEMPORAL is true, try generating a nontemporal store. */
If NONTEMPORAL is true, try generating a nontemporal store.
If REVERSE is true, the store is to be done in reverse order. */
static rtx
store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
unsigned HOST_WIDE_INT bitregion_start,
unsigned HOST_WIDE_INT bitregion_end,
machine_mode mode, tree exp,
alias_set_type alias_set, bool nontemporal)
alias_set_type alias_set, bool nontemporal, bool reverse)
{
if (TREE_CODE (exp) == ERROR_MARK)
return const0_rtx;
@ -6568,7 +6611,7 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
/* We're storing into a struct containing a single __complex. */
gcc_assert (!bitpos);
return store_expr (exp, target, 0, nontemporal);
return store_expr (exp, target, 0, nontemporal, reverse);
}
/* If the structure is in a register or if the component
@ -6637,16 +6680,27 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
temp = expand_normal (exp);
/* If BITSIZE is narrower than the size of the type of EXP
we will be narrowing TEMP. Normally, what's wanted are the
low-order bits. However, if EXP's type is a record and this is
big-endian machine, we want the upper BITSIZE bits. */
if (BYTES_BIG_ENDIAN && GET_MODE_CLASS (GET_MODE (temp)) == MODE_INT
&& bitsize < (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (temp))
&& TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
temp = expand_shift (RSHIFT_EXPR, GET_MODE (temp), temp,
GET_MODE_BITSIZE (GET_MODE (temp)) - bitsize,
NULL_RTX, 1);
/* If the value has a record type and an integral mode then, if BITSIZE
is narrower than this mode and this is for big-endian data, we must
first put the value into the low-order bits. Moreover, the field may
be not aligned on a byte boundary; in this case, if it has reverse
storage order, it needs to be accessed as a scalar field with reverse
storage order and we must first put the value into target order. */
if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
&& GET_MODE_CLASS (GET_MODE (temp)) == MODE_INT)
{
HOST_WIDE_INT size = GET_MODE_BITSIZE (GET_MODE (temp));
reverse = TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (exp));
if (reverse)
temp = flip_storage_order (GET_MODE (temp), temp);
if (bitsize < size
&& reverse ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN)
temp = expand_shift (RSHIFT_EXPR, GET_MODE (temp), temp,
size - bitsize, NULL_RTX, 1);
}
/* Unless MODE is VOIDmode or BLKmode, convert TEMP to MODE. */
if (mode != VOIDmode && mode != BLKmode
@ -6706,7 +6760,7 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
temp_target = gen_reg_rtx (mode);
temp_target
= extract_bit_field (temp, size * BITS_PER_UNIT, 0, 1,
temp_target, mode, mode);
temp_target, mode, mode, false);
temp = temp_target;
}
}
@ -6714,7 +6768,7 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
/* Store the value in the bitfield. */
store_bit_field (target, bitsize, bitpos,
bitregion_start, bitregion_end,
mode, temp);
mode, temp, reverse);
return const0_rtx;
}
@ -6734,11 +6788,11 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
if (TREE_CODE (exp) == CONSTRUCTOR && bitsize >= 0)
{
gcc_assert (bitsize % BITS_PER_UNIT == 0);
store_constructor (exp, to_rtx, 0, bitsize/BITS_PER_UNIT);
store_constructor (exp, to_rtx, 0, bitsize / BITS_PER_UNIT, reverse);
return to_rtx;
}
return store_expr (exp, to_rtx, 0, nontemporal);
return store_expr (exp, to_rtx, 0, nontemporal, reverse);
}
}
@ -6747,7 +6801,8 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
codes and find the ultimate containing object, which we return.
We set *PBITSIZE to the size in bits that we want, *PBITPOS to the
bit position, and *PUNSIGNEDP to the signedness of the field.
bit position, *PUNSIGNEDP to the signedness and *PREVERSEP to the
storage order of the field.
If the position of the field is variable, we store a tree
giving the variable offset (in units) in *POFFSET.
This offset is in addition to the bit position.
@ -6781,7 +6836,7 @@ tree
get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
HOST_WIDE_INT *pbitpos, tree *poffset,
machine_mode *pmode, int *punsignedp,
int *pvolatilep, bool keep_aligning)
int *preversep, int *pvolatilep, bool keep_aligning)
{
tree size_tree = 0;
machine_mode mode = VOIDmode;
@ -6789,8 +6844,8 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
tree offset = size_zero_node;
offset_int bit_offset = 0;
/* First get the mode, signedness, and size. We do this from just the
outermost expression. */
/* First get the mode, signedness, storage order and size. We do this from
just the outermost expression. */
*pbitsize = -1;
if (TREE_CODE (exp) == COMPONENT_REF)
{
@ -6843,6 +6898,8 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
*pbitsize = tree_to_uhwi (size_tree);
}
*preversep = reverse_storage_order_for_component_p (exp);
/* Compute cumulative bit-offset for nested component-refs and array-refs,
and find the ultimate containing object. */
while (1)
@ -7519,7 +7576,7 @@ expand_expr_addr_expr_1 (tree exp, rtx target, machine_mode tmode,
rtx result, subtarget;
tree inner, offset;
HOST_WIDE_INT bitsize, bitpos;
int volatilep, unsignedp;
int unsignedp, reversep, volatilep = 0;
machine_mode mode1;
/* If we are taking the address of a constant and are at the top level,
@ -7626,8 +7683,8 @@ expand_expr_addr_expr_1 (tree exp, rtx target, machine_mode tmode,
handle "aligning nodes" here: we can just bypass them because
they won't change the final object whose address will be returned
(they actually exist only for that purpose). */
inner = get_inner_reference (exp, &bitsize, &bitpos, &offset,
&mode1, &unsignedp, &volatilep, false);
inner = get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode1,
&unsignedp, &reversep, &volatilep, false);
break;
}
@ -7811,7 +7868,7 @@ expand_constructor (tree exp, rtx target, enum expand_modifier modifier,
target = assign_temp (type, TREE_ADDRESSABLE (exp), 1);
}
store_constructor (exp, target, 0, int_expr_size (exp));
store_constructor (exp, target, 0, int_expr_size (exp), false);
return target;
}
@ -8084,11 +8141,12 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
store_expr (treeop0,
adjust_address (target, TYPE_MODE (valtype), 0),
modifier == EXPAND_STACK_PARM,
false);
false, TYPE_REVERSE_STORAGE_ORDER (type));
else
{
gcc_assert (REG_P (target));
gcc_assert (REG_P (target)
&& !TYPE_REVERSE_STORAGE_ORDER (type));
/* Store this field into a union of the proper type. */
store_field (target,
@ -8096,7 +8154,8 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
(treeop0))
* BITS_PER_UNIT),
(HOST_WIDE_INT) GET_MODE_BITSIZE (mode)),
0, 0, 0, TYPE_MODE (valtype), treeop0, 0, false);
0, 0, 0, TYPE_MODE (valtype), treeop0, 0,
false, false);
}
/* Return the entire union. */
@ -9131,7 +9190,7 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
int index = BYTES_BIG_ENDIAN ? GET_MODE_NUNITS (vec_mode) - 1 : 0;
int bitsize = GET_MODE_UNIT_BITSIZE (vec_mode);
temp = extract_bit_field (temp, bitsize, bitsize * index, unsignedp,
target, mode, mode);
target, mode, mode, false);
gcc_assert (temp);
return temp;
}
@ -9287,14 +9346,14 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
jumpifnot (treeop0, lab0, -1);
store_expr (treeop1, temp,
modifier == EXPAND_STACK_PARM,
false);
false, false);
emit_jump_insn (targetm.gen_jump (lab1));
emit_barrier ();
emit_label (lab0);
store_expr (treeop2, temp,
modifier == EXPAND_STACK_PARM,
false);
false, false);
emit_label (lab1);
OK_DEFER_POP;
@ -9847,6 +9906,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
case MEM_REF:
{
const bool reverse = REF_REVERSE_STORAGE_ORDER (exp);
addr_space_t as
= TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0))));
machine_mode address_mode;
@ -9861,6 +9921,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
HOST_WIDE_INT offset = mem_ref_offset (exp).to_short_addr ();
base = TREE_OPERAND (base, 0);
if (offset == 0
&& !reverse
&& tree_fits_uhwi_p (TYPE_SIZE (type))
&& (GET_MODE_BITSIZE (DECL_MODE (base))
== tree_to_uhwi (TYPE_SIZE (type))))
@ -9870,13 +9931,14 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
{
temp = assign_stack_temp (DECL_MODE (base),
GET_MODE_SIZE (DECL_MODE (base)));
store_expr (base, temp, 0, false);
store_expr (base, temp, 0, false, false);
temp = adjust_address (temp, BLKmode, offset);
set_mem_size (temp, int_size_in_bytes (type));
return temp;
}
exp = build3 (BIT_FIELD_REF, type, base, TYPE_SIZE (type),
bitsize_int (offset * BITS_PER_UNIT));
REF_REVERSE_STORAGE_ORDER (exp) = reverse;
return expand_expr (exp, target, tmode, modifier);
}
address_mode = targetm.addr_space.address_mode (as);
@ -9926,8 +9988,12 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
0, TYPE_UNSIGNED (TREE_TYPE (exp)),
(modifier == EXPAND_STACK_PARM
? NULL_RTX : target),
mode, mode);
mode, mode, false);
}
if (reverse
&& modifier != EXPAND_MEMORY
&& modifier != EXPAND_WRITE)
temp = flip_storage_order (mode, temp);
return temp;
}
@ -10133,9 +10199,10 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
machine_mode mode1, mode2;
HOST_WIDE_INT bitsize, bitpos;
tree offset;
int volatilep = 0, must_force_mem;
tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset,
&mode1, &unsignedp, &volatilep, true);
int reversep, volatilep = 0, must_force_mem;
tree tem
= get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode1,
&unsignedp, &reversep, &volatilep, true);
rtx orig_op0, memloc;
bool clear_mem_expr = false;
@ -10190,7 +10257,11 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
{
if (bitpos == 0
&& bitsize == GET_MODE_BITSIZE (GET_MODE (op0)))
return op0;
{
if (reversep)
op0 = flip_storage_order (GET_MODE (op0), op0);
return op0;
}
if (bitpos == 0
&& bitsize == GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 0)))
&& bitsize)
@ -10376,20 +10447,38 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
if (MEM_P (op0) && REG_P (XEXP (op0, 0)))
mark_reg_pointer (XEXP (op0, 0), MEM_ALIGN (op0));
/* If the result has a record type and the extraction is done in
an integral mode, then the field may be not aligned on a byte
boundary; in this case, if it has reverse storage order, it
needs to be extracted as a scalar field with reverse storage
order and put back into memory order afterwards. */
if (TREE_CODE (type) == RECORD_TYPE
&& GET_MODE_CLASS (ext_mode) == MODE_INT)
reversep = TYPE_REVERSE_STORAGE_ORDER (type);
op0 = extract_bit_field (op0, bitsize, bitpos, unsignedp,
(modifier == EXPAND_STACK_PARM
? NULL_RTX : target),
ext_mode, ext_mode);
ext_mode, ext_mode, reversep);
/* If the result is a record type and BITSIZE is narrower than
the mode of OP0, an integral mode, and this is a big endian
machine, we must put the field into the high-order bits. */
if (TREE_CODE (type) == RECORD_TYPE && BYTES_BIG_ENDIAN
&& GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
&& bitsize < (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (op0)))
op0 = expand_shift (LSHIFT_EXPR, GET_MODE (op0), op0,
GET_MODE_BITSIZE (GET_MODE (op0))
- bitsize, op0, 1);
/* If the result has a record type and the mode of OP0 is an
integral mode then, if BITSIZE is narrower than this mode
and this is for big-endian data, we must put the field
into the high-order bits. And we must also put it back
into memory order if it has been previously reversed. */
if (TREE_CODE (type) == RECORD_TYPE
&& GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT)
{
HOST_WIDE_INT size = GET_MODE_BITSIZE (GET_MODE (op0));
if (bitsize < size
&& reversep ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN)
op0 = expand_shift (LSHIFT_EXPR, GET_MODE (op0), op0,
size - bitsize, op0, 1);
if (reversep)
op0 = flip_storage_order (GET_MODE (op0), op0);
}
/* If the result type is BLKmode, store the data into a temporary
of the appropriate type, but with the mode corresponding to the
@ -10435,6 +10524,12 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
set_mem_expr (op0, NULL_TREE);
MEM_VOLATILE_P (op0) |= volatilep;
if (reversep
&& modifier != EXPAND_MEMORY
&& modifier != EXPAND_WRITE)
op0 = flip_storage_order (mode1, op0);
if (mode == mode1 || mode1 == BLKmode || mode1 == tmode
|| modifier == EXPAND_CONST_ADDRESS
|| modifier == EXPAND_INITIALIZER)
@ -10498,17 +10593,16 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
machine_mode mode1;
HOST_WIDE_INT bitsize, bitpos;
tree offset;
int unsignedp;
int volatilep = 0;
int unsignedp, reversep, volatilep = 0;
tree tem
= get_inner_reference (treeop0, &bitsize, &bitpos,
&offset, &mode1, &unsignedp, &volatilep,
true);
= get_inner_reference (treeop0, &bitsize, &bitpos, &offset, &mode1,
&unsignedp, &reversep, &volatilep, true);
rtx orig_op0;
/* ??? We should work harder and deal with non-zero offsets. */
if (!offset
&& (bitpos % BITS_PER_UNIT) == 0
&& !reversep
&& bitsize >= 0
&& compare_tree_int (TYPE_SIZE (type), bitsize) == 0)
{
@ -10582,7 +10676,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
else if (reduce_bit_field)
return extract_bit_field (op0, TYPE_PRECISION (type), 0,
TYPE_UNSIGNED (type), NULL_RTX,
mode, mode);
mode, mode, false);
/* As a last resort, spill op0 to memory, and reload it in a
different mode. */
else if (!MEM_P (op0))

View File

@ -212,6 +212,7 @@ extern rtx_insn *emit_move_complex_push (machine_mode, rtx, rtx);
extern rtx_insn *emit_move_complex_parts (rtx, rtx);
extern rtx read_complex_part (rtx, bool);
extern void write_complex_part (rtx, rtx, bool);
extern rtx read_complex_part (rtx, bool);
extern rtx emit_move_resolve_push (machine_mode, rtx);
/* Push a block of length SIZE (perhaps variable)
@ -229,8 +230,8 @@ extern void expand_assignment (tree, tree, bool);
and storing the value into TARGET.
If SUGGEST_REG is nonzero, copy the value through a register
and return that register, if that is possible. */
extern rtx store_expr_with_bounds (tree, rtx, int, bool, tree);
extern rtx store_expr (tree, rtx, int, bool);
extern rtx store_expr_with_bounds (tree, rtx, int, bool, bool, tree);
extern rtx store_expr (tree, rtx, int, bool, bool);
/* Given an rtx that may include add and multiply operations,
generate them as insns and return a pseudo-reg containing the value.

View File

@ -165,7 +165,6 @@ enum stack_check_type
/* Names for the different levels of -Wstrict-overflow=N. The numeric
values here correspond to N. */
enum warn_strict_overflow_code
{
/* Overflow warning that should be issued with -Wall: a questionable
@ -195,6 +194,13 @@ enum fp_contract_mode {
FP_CONTRACT_FAST = 2
};
/* Scalar storage order kind. */
enum scalar_storage_order_kind {
SSO_NATIVE = 0,
SSO_BIG_ENDIAN,
SSO_LITTLE_ENDIAN
};
/* Vectorizer cost-model. */
enum vect_cost_model {
VECT_COST_MODEL_UNLIMITED = 0,
@ -203,7 +209,6 @@ enum vect_cost_model {
VECT_COST_MODEL_DEFAULT = 3
};
/* Different instrumentation modes. */
enum sanitize_code {
/* AddressSanitizer. */

View File

@ -114,12 +114,12 @@ static int operand_equal_for_comparison_p (tree, tree, tree);
static int twoval_comparison_p (tree, tree *, tree *, int *);
static tree eval_subst (location_t, tree, tree, tree, tree, tree);
static tree make_bit_field_ref (location_t, tree, tree,
HOST_WIDE_INT, HOST_WIDE_INT, int);
HOST_WIDE_INT, HOST_WIDE_INT, int, int);
static tree optimize_bit_field_compare (location_t, enum tree_code,
tree, tree, tree);
static tree decode_field_reference (location_t, tree, HOST_WIDE_INT *,
HOST_WIDE_INT *,
machine_mode *, int *, int *,
machine_mode *, int *, int *, int *,
tree *, tree *);
static int simple_operand_p (const_tree);
static bool simple_operand_p_2 (tree);
@ -3688,15 +3688,17 @@ distribute_real_division (location_t loc, enum tree_code code, tree type,
}
/* Return a BIT_FIELD_REF of type TYPE to refer to BITSIZE bits of INNER
starting at BITPOS. The field is unsigned if UNSIGNEDP is nonzero. */
starting at BITPOS. The field is unsigned if UNSIGNEDP is nonzero
and uses reverse storage order if REVERSEP is nonzero. */
static tree
make_bit_field_ref (location_t loc, tree inner, tree type,
HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos, int unsignedp)
HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
int unsignedp, int reversep)
{
tree result, bftype;
if (bitpos == 0)
if (bitpos == 0 && !reversep)
{
tree size = TYPE_SIZE (TREE_TYPE (inner));
if ((INTEGRAL_TYPE_P (TREE_TYPE (inner))
@ -3713,6 +3715,7 @@ make_bit_field_ref (location_t loc, tree inner, tree type,
result = build3_loc (loc, BIT_FIELD_REF, bftype, inner,
size_int (bitsize), bitsize_int (bitpos));
REF_REVERSE_STORAGE_ORDER (result) = reversep;
if (bftype != type)
result = fold_convert_loc (loc, type, result);
@ -3750,6 +3753,7 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
int const_p = TREE_CODE (rhs) == INTEGER_CST;
machine_mode lmode, rmode, nmode;
int lunsignedp, runsignedp;
int lreversep, rreversep;
int lvolatilep = 0, rvolatilep = 0;
tree linner, rinner = NULL_TREE;
tree mask;
@ -3761,20 +3765,23 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
do anything if the inner expression is a PLACEHOLDER_EXPR since we
then will no longer be able to replace it. */
linner = get_inner_reference (lhs, &lbitsize, &lbitpos, &offset, &lmode,
&lunsignedp, &lvolatilep, false);
&lunsignedp, &lreversep, &lvolatilep, false);
if (linner == lhs || lbitsize == GET_MODE_BITSIZE (lmode) || lbitsize < 0
|| offset != 0 || TREE_CODE (linner) == PLACEHOLDER_EXPR || lvolatilep)
return 0;
if (!const_p)
if (const_p)
rreversep = lreversep;
else
{
/* If this is not a constant, we can only do something if bit positions,
sizes, and signedness are the same. */
rinner = get_inner_reference (rhs, &rbitsize, &rbitpos, &offset, &rmode,
&runsignedp, &rvolatilep, false);
sizes, signedness and storage order are the same. */
rinner
= get_inner_reference (rhs, &rbitsize, &rbitpos, &offset, &rmode,
&runsignedp, &rreversep, &rvolatilep, false);
if (rinner == rhs || lbitpos != rbitpos || lbitsize != rbitsize
|| lunsignedp != runsignedp || offset != 0
|| lunsignedp != runsignedp || lreversep != rreversep || offset != 0
|| TREE_CODE (rinner) == PLACEHOLDER_EXPR || rvolatilep)
return 0;
}
@ -3802,7 +3809,7 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
if (nbitsize == lbitsize)
return 0;
if (BYTES_BIG_ENDIAN)
if (lreversep ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN)
lbitpos = nbitsize - lbitsize - lbitpos;
/* Make the mask to be used against the extracted field. */
@ -3819,17 +3826,17 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
make_bit_field_ref (loc, linner,
unsigned_type,
nbitsize, nbitpos,
1),
1, lreversep),
mask),
fold_build2_loc (loc, BIT_AND_EXPR, unsigned_type,
make_bit_field_ref (loc, rinner,
unsigned_type,
nbitsize, nbitpos,
1),
1, rreversep),
mask));
/* Otherwise, we are handling the constant case. See if the constant is too
big for the field. Warn and return a tree of for 0 (false) if so. We do
/* Otherwise, we are handling the constant case. See if the constant is too
big for the field. Warn and return a tree for 0 (false) if so. We do
this not only for its own sake, but to avoid having to test for this
error case below. If we didn't, we might generate wrong code.
@ -3867,7 +3874,8 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
/* Make a new bitfield reference, shift the constant over the
appropriate number of bits and mask it with the computed mask
(in case this was a signed field). If we changed it, make a new one. */
lhs = make_bit_field_ref (loc, linner, unsigned_type, nbitsize, nbitpos, 1);
lhs = make_bit_field_ref (loc, linner, unsigned_type, nbitsize, nbitpos, 1,
lreversep);
rhs = const_binop (BIT_AND_EXPR,
const_binop (LSHIFT_EXPR,
@ -3895,6 +3903,8 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
*PUNSIGNEDP is set to the signedness of the field.
*PREVERSEP is set to the storage order of the field.
*PMASK is set to the mask used. This is either contained in a
BIT_AND_EXPR or derived from the width of the field.
@ -3906,7 +3916,7 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
static tree
decode_field_reference (location_t loc, tree exp, HOST_WIDE_INT *pbitsize,
HOST_WIDE_INT *pbitpos, machine_mode *pmode,
int *punsignedp, int *pvolatilep,
int *punsignedp, int *preversep, int *pvolatilep,
tree *pmask, tree *pand_mask)
{
tree outer_type = 0;
@ -3939,7 +3949,7 @@ decode_field_reference (location_t loc, tree exp, HOST_WIDE_INT *pbitsize,
}
inner = get_inner_reference (exp, pbitsize, pbitpos, &offset, pmode,
punsignedp, pvolatilep, false);
punsignedp, preversep, pvolatilep, false);
if ((inner == exp && and_mask == 0)
|| *pbitsize < 0 || offset != 0
|| TREE_CODE (inner) == PLACEHOLDER_EXPR)
@ -5441,6 +5451,7 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type,
HOST_WIDE_INT xll_bitpos, xlr_bitpos, xrl_bitpos, xrr_bitpos;
HOST_WIDE_INT lnbitsize, lnbitpos, rnbitsize, rnbitpos;
int ll_unsignedp, lr_unsignedp, rl_unsignedp, rr_unsignedp;
int ll_reversep, lr_reversep, rl_reversep, rr_reversep;
machine_mode ll_mode, lr_mode, rl_mode, rr_mode;
machine_mode lnmode, rnmode;
tree ll_mask, lr_mask, rl_mask, rr_mask;
@ -5553,33 +5564,39 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type,
volatilep = 0;
ll_inner = decode_field_reference (loc, ll_arg,
&ll_bitsize, &ll_bitpos, &ll_mode,
&ll_unsignedp, &volatilep, &ll_mask,
&ll_and_mask);
&ll_unsignedp, &ll_reversep, &volatilep,
&ll_mask, &ll_and_mask);
lr_inner = decode_field_reference (loc, lr_arg,
&lr_bitsize, &lr_bitpos, &lr_mode,
&lr_unsignedp, &volatilep, &lr_mask,
&lr_and_mask);
&lr_unsignedp, &lr_reversep, &volatilep,
&lr_mask, &lr_and_mask);
rl_inner = decode_field_reference (loc, rl_arg,
&rl_bitsize, &rl_bitpos, &rl_mode,
&rl_unsignedp, &volatilep, &rl_mask,
&rl_and_mask);
&rl_unsignedp, &rl_reversep, &volatilep,
&rl_mask, &rl_and_mask);
rr_inner = decode_field_reference (loc, rr_arg,
&rr_bitsize, &rr_bitpos, &rr_mode,
&rr_unsignedp, &volatilep, &rr_mask,
&rr_and_mask);
&rr_unsignedp, &rr_reversep, &volatilep,
&rr_mask, &rr_and_mask);
/* It must be true that the inner operation on the lhs of each
comparison must be the same if we are to be able to do anything.
Then see if we have constants. If not, the same must be true for
the rhs's. */
if (volatilep || ll_inner == 0 || rl_inner == 0
if (volatilep
|| ll_reversep != rl_reversep
|| ll_inner == 0 || rl_inner == 0
|| ! operand_equal_p (ll_inner, rl_inner, 0))
return 0;
if (TREE_CODE (lr_arg) == INTEGER_CST
&& TREE_CODE (rr_arg) == INTEGER_CST)
l_const = lr_arg, r_const = rr_arg;
else if (lr_inner == 0 || rr_inner == 0
{
l_const = lr_arg, r_const = rr_arg;
lr_reversep = ll_reversep;
}
else if (lr_reversep != rr_reversep
|| lr_inner == 0 || rr_inner == 0
|| ! operand_equal_p (lr_inner, rr_inner, 0))
return 0;
else
@ -5632,7 +5649,7 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type,
lntype = lang_hooks.types.type_for_size (lnbitsize, 1);
xll_bitpos = ll_bitpos - lnbitpos, xrl_bitpos = rl_bitpos - lnbitpos;
if (BYTES_BIG_ENDIAN)
if (ll_reversep ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN)
{
xll_bitpos = lnbitsize - xll_bitpos - ll_bitsize;
xrl_bitpos = lnbitsize - xrl_bitpos - rl_bitsize;
@ -5697,7 +5714,7 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type,
rntype = lang_hooks.types.type_for_size (rnbitsize, 1);
xlr_bitpos = lr_bitpos - rnbitpos, xrr_bitpos = rr_bitpos - rnbitpos;
if (BYTES_BIG_ENDIAN)
if (lr_reversep ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN)
{
xlr_bitpos = rnbitsize - xlr_bitpos - lr_bitsize;
xrr_bitpos = rnbitsize - xrr_bitpos - rr_bitsize;
@ -5720,12 +5737,12 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type,
if (lnbitsize == rnbitsize && xll_bitpos == xlr_bitpos)
{
lhs = make_bit_field_ref (loc, ll_inner, lntype, lnbitsize, lnbitpos,
ll_unsignedp || rl_unsignedp);
ll_unsignedp || rl_unsignedp, ll_reversep);
if (! all_ones_mask_p (ll_mask, lnbitsize))
lhs = build2 (BIT_AND_EXPR, lntype, lhs, ll_mask);
rhs = make_bit_field_ref (loc, lr_inner, rntype, rnbitsize, rnbitpos,
lr_unsignedp || rr_unsignedp);
lr_unsignedp || rr_unsignedp, lr_reversep);
if (! all_ones_mask_p (lr_mask, rnbitsize))
rhs = build2 (BIT_AND_EXPR, rntype, rhs, lr_mask);
@ -5748,10 +5765,12 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type,
lhs = make_bit_field_ref (loc, ll_inner, lntype,
ll_bitsize + rl_bitsize,
MIN (ll_bitpos, rl_bitpos), ll_unsignedp);
MIN (ll_bitpos, rl_bitpos),
ll_unsignedp, ll_reversep);
rhs = make_bit_field_ref (loc, lr_inner, rntype,
lr_bitsize + rr_bitsize,
MIN (lr_bitpos, rr_bitpos), lr_unsignedp);
MIN (lr_bitpos, rr_bitpos),
lr_unsignedp, lr_reversep);
ll_mask = const_binop (RSHIFT_EXPR, ll_mask,
size_int (MIN (xll_bitpos, xrl_bitpos)));
@ -5814,7 +5833,7 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type,
that field, perform the mask operation. Then compare with the
merged constant. */
result = make_bit_field_ref (loc, ll_inner, lntype, lnbitsize, lnbitpos,
ll_unsignedp || rl_unsignedp);
ll_unsignedp || rl_unsignedp, ll_reversep);
ll_mask = const_binop (BIT_IOR_EXPR, ll_mask, rl_mask);
if (! all_ones_mask_p (ll_mask, lnbitsize))
@ -7678,10 +7697,11 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
HOST_WIDE_INT bitsize, bitpos;
tree offset;
machine_mode mode;
int unsignedp, volatilep;
tree base = TREE_OPERAND (op0, 0);
base = get_inner_reference (base, &bitsize, &bitpos, &offset,
&mode, &unsignedp, &volatilep, false);
int unsignedp, reversep, volatilep;
tree base
= get_inner_reference (TREE_OPERAND (op0, 0), &bitsize, &bitpos,
&offset, &mode, &unsignedp, &reversep,
&volatilep, false);
/* If the reference was to a (constant) zero offset, we can use
the address of the base if it has the same base type
as the result type and the pointer type is unqualified. */
@ -7817,8 +7837,12 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
case VIEW_CONVERT_EXPR:
if (TREE_CODE (op0) == MEM_REF)
return fold_build2_loc (loc, MEM_REF, type,
TREE_OPERAND (op0, 0), TREE_OPERAND (op0, 1));
{
tem = fold_build2_loc (loc, MEM_REF, type,
TREE_OPERAND (op0, 0), TREE_OPERAND (op0, 1));
REF_REVERSE_STORAGE_ORDER (tem) = REF_REVERSE_STORAGE_ORDER (op0);
return tem;
}
return NULL_TREE;
@ -8335,7 +8359,7 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
tree base0, base1, offset0 = NULL_TREE, offset1 = NULL_TREE;
HOST_WIDE_INT bitsize, bitpos0 = 0, bitpos1 = 0;
machine_mode mode;
int volatilep, unsignedp;
int volatilep, reversep, unsignedp;
bool indirect_base0 = false, indirect_base1 = false;
/* Get base and offset for the access. Strip ADDR_EXPR for
@ -8345,9 +8369,10 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
base0 = arg0;
if (TREE_CODE (arg0) == ADDR_EXPR)
{
base0 = get_inner_reference (TREE_OPERAND (arg0, 0),
&bitsize, &bitpos0, &offset0, &mode,
&unsignedp, &volatilep, false);
base0
= get_inner_reference (TREE_OPERAND (arg0, 0),
&bitsize, &bitpos0, &offset0, &mode,
&unsignedp, &reversep, &volatilep, false);
if (TREE_CODE (base0) == INDIRECT_REF)
base0 = TREE_OPERAND (base0, 0);
else
@ -8379,9 +8404,10 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
base1 = arg1;
if (TREE_CODE (arg1) == ADDR_EXPR)
{
base1 = get_inner_reference (TREE_OPERAND (arg1, 0),
&bitsize, &bitpos1, &offset1, &mode,
&unsignedp, &volatilep, false);
base1
= get_inner_reference (TREE_OPERAND (arg1, 0),
&bitsize, &bitpos1, &offset1, &mode,
&unsignedp, &reversep, &volatilep, false);
if (TREE_CODE (base1) == INDIRECT_REF)
base1 = TREE_OPERAND (base1, 0);
else
@ -14311,15 +14337,15 @@ split_address_to_core_and_offset (tree exp,
{
tree core;
machine_mode mode;
int unsignedp, volatilep;
int unsignedp, reversep, volatilep;
HOST_WIDE_INT bitsize;
location_t loc = EXPR_LOCATION (exp);
if (TREE_CODE (exp) == ADDR_EXPR)
{
core = get_inner_reference (TREE_OPERAND (exp, 0), &bitsize, pbitpos,
poffset, &mode, &unsignedp, &volatilep,
false);
poffset, &mode, &unsignedp, &reversep,
&volatilep, false);
core = build_fold_addr_expr_loc (loc, core);
}
else

View File

@ -152,14 +152,16 @@ useless_type_conversion_p (tree outer_type, tree inner_type)
else if (TREE_CODE (inner_type) == ARRAY_TYPE
&& TREE_CODE (outer_type) == ARRAY_TYPE)
{
/* Preserve string attributes. */
/* Preserve various attributes. */
if (TYPE_REVERSE_STORAGE_ORDER (inner_type)
!= TYPE_REVERSE_STORAGE_ORDER (outer_type))
return false;
if (TYPE_STRING_FLAG (inner_type) != TYPE_STRING_FLAG (outer_type))
return false;
/* Conversions from array types with unknown extent to
array types with known extent are not useless. */
if (!TYPE_DOMAIN (inner_type)
&& TYPE_DOMAIN (outer_type))
if (!TYPE_DOMAIN (inner_type) && TYPE_DOMAIN (outer_type))
return false;
/* Nor are conversions from array types with non-constant size to

View File

@ -782,13 +782,14 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
HOST_WIDE_INT src_offset = 0, dest_offset = 0;
HOST_WIDE_INT size = -1;
HOST_WIDE_INT maxsize = -1;
bool reverse;
srcvar = TREE_OPERAND (src, 0);
src_base = get_ref_base_and_extent (srcvar, &src_offset,
&size, &maxsize);
&size, &maxsize, &reverse);
destvar = TREE_OPERAND (dest, 0);
dest_base = get_ref_base_and_extent (destvar, &dest_offset,
&size, &maxsize);
&size, &maxsize, &reverse);
if (tree_fits_uhwi_p (len))
maxsize = tree_to_uhwi (len);
else
@ -5264,6 +5265,8 @@ get_base_constructor (tree base, HOST_WIDE_INT *bit_offset,
tree (*valueize)(tree))
{
HOST_WIDE_INT bit_offset2, size, max_size;
bool reverse;
if (TREE_CODE (base) == MEM_REF)
{
if (!integer_zerop (TREE_OPERAND (base, 1)))
@ -5304,7 +5307,8 @@ get_base_constructor (tree base, HOST_WIDE_INT *bit_offset,
case ARRAY_REF:
case COMPONENT_REF:
base = get_ref_base_and_extent (base, &bit_offset2, &size, &max_size);
base = get_ref_base_and_extent (base, &bit_offset2, &size, &max_size,
&reverse);
if (max_size == -1 || size != max_size)
return NULL_TREE;
*bit_offset += bit_offset2;
@ -5507,6 +5511,7 @@ fold_const_aggregate_ref_1 (tree t, tree (*valueize) (tree))
tree ctor, idx, base;
HOST_WIDE_INT offset, size, max_size;
tree tem;
bool reverse;
if (TREE_THIS_VOLATILE (t))
return NULL_TREE;
@ -5577,7 +5582,7 @@ fold_const_aggregate_ref_1 (tree t, tree (*valueize) (tree))
case BIT_FIELD_REF:
case TARGET_MEM_REF:
case MEM_REF:
base = get_ref_base_and_extent (t, &offset, &size, &max_size);
base = get_ref_base_and_extent (t, &offset, &size, &max_size, &reverse);
ctor = get_base_constructor (base, &offset, valueize);
/* Empty constructor. Always fold to 0. */

View File

@ -102,10 +102,10 @@ pass_laddress::execute (function *fun)
HOST_WIDE_INT bitsize, bitpos;
tree base, offset;
machine_mode mode;
int volatilep = 0, unsignedp = 0;
int volatilep = 0, reversep, unsignedp = 0;
base = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize,
&bitpos, &offset, &mode, &unsignedp,
&volatilep, false);
&reversep, &volatilep, false);
gcc_assert (base != NULL_TREE && (bitpos % BITS_PER_UNIT) == 0);
if (offset != NULL_TREE)
{

View File

@ -972,7 +972,7 @@ slsr_process_ref (gimple *gs)
tree ref_expr, base, offset, type;
HOST_WIDE_INT bitsize, bitpos;
machine_mode mode;
int unsignedp, volatilep;
int unsignedp, reversep, volatilep;
slsr_cand_t c;
if (gimple_vdef (gs))
@ -987,7 +987,9 @@ slsr_process_ref (gimple *gs)
return;
base = get_inner_reference (ref_expr, &bitsize, &bitpos, &offset, &mode,
&unsignedp, &volatilep, false);
&unsignedp, &reversep, &volatilep, false);
if (reversep)
return;
widest_int index = bitpos;
if (!restructure_reference (&base, &offset, &index, &type))

View File

@ -6613,14 +6613,14 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
tree offset;
HOST_WIDE_INT bitsize, bitpos;
machine_mode mode;
int unsignedp, volatilep = 0;
int unsignedp, reversep, volatilep = 0;
tree base = OMP_CLAUSE_DECL (c);
while (TREE_CODE (base) == ARRAY_REF)
base = TREE_OPERAND (base, 0);
if (TREE_CODE (base) == INDIRECT_REF)
base = TREE_OPERAND (base, 0);
base = get_inner_reference (base, &bitsize, &bitpos, &offset,
&mode, &unsignedp,
&mode, &unsignedp, &reversep,
&volatilep, false);
gcc_assert (base == decl
&& (offset == NULL_TREE
@ -6730,7 +6730,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
base = get_inner_reference (base, &bitsize2,
&bitpos2, &offset2,
&mode, &unsignedp,
&volatilep, false);
&reversep, &volatilep,
false);
if (base != decl)
break;
if (scp)
@ -9734,6 +9735,8 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
TREE_OPERAND (*expr_p, 1));
if (tmp)
{
REF_REVERSE_STORAGE_ORDER (tmp)
= REF_REVERSE_STORAGE_ORDER (*expr_p);
*expr_p = tmp;
recalculate_side_effects (*expr_p);
ret = GS_OK;

View File

@ -942,7 +942,7 @@ noce_emit_move_insn (rtx x, rtx y)
}
gcc_assert (start < (MEM_P (op) ? BITS_PER_UNIT : BITS_PER_WORD));
store_bit_field (op, size, start, 0, 0, GET_MODE (x), y);
store_bit_field (op, size, start, 0, 0, GET_MODE (x), y, false);
return;
}
@ -997,7 +997,7 @@ noce_emit_move_insn (rtx x, rtx y)
outmode = GET_MODE (outer);
bitpos = SUBREG_BYTE (outer) * BITS_PER_UNIT;
store_bit_field (inner, GET_MODE_BITSIZE (outmode), bitpos,
0, 0, outmode, y);
0, 0, outmode, y, false);
}
/* Return the CC reg if it is used in COND. */

View File

@ -1055,7 +1055,7 @@ ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input)
{
tree t = TREE_OPERAND (input, 0);
t = build_ref_for_offset (EXPR_LOCATION (t), t,
ipa_get_jf_ancestor_offset (jfunc),
ipa_get_jf_ancestor_offset (jfunc), false,
ptr_type_node, NULL, false);
return build_fold_addr_expr (t);
}

View File

@ -749,6 +749,7 @@ ipa_polymorphic_call_context::set_by_invariant (tree cst,
HOST_WIDE_INT off)
{
HOST_WIDE_INT offset2, size, max_size;
bool reverse;
tree base;
invalid = false;
@ -759,7 +760,7 @@ ipa_polymorphic_call_context::set_by_invariant (tree cst,
return false;
cst = TREE_OPERAND (cst, 0);
base = get_ref_base_and_extent (cst, &offset2, &size, &max_size);
base = get_ref_base_and_extent (cst, &offset2, &size, &max_size, &reverse);
if (!DECL_P (base) || max_size == -1 || max_size != size)
return false;
@ -889,8 +890,10 @@ ipa_polymorphic_call_context::ipa_polymorphic_call_context (tree fndecl,
{
HOST_WIDE_INT size, max_size;
HOST_WIDE_INT offset2;
tree base = get_ref_base_and_extent (TREE_OPERAND (base_pointer, 0),
&offset2, &size, &max_size);
bool reverse;
tree base
= get_ref_base_and_extent (TREE_OPERAND (base_pointer, 0),
&offset2, &size, &max_size, &reverse);
if (max_size != -1 && max_size == size)
combine_speculation_with (TYPE_MAIN_VARIANT (TREE_TYPE (base)),
@ -1158,6 +1161,7 @@ extr_type_from_vtbl_ptr_store (gimple *stmt, struct type_change_info *tci,
{
HOST_WIDE_INT offset, size, max_size;
tree lhs, rhs, base;
bool reverse;
if (!gimple_assign_single_p (stmt))
return NULL_TREE;
@ -1176,7 +1180,7 @@ extr_type_from_vtbl_ptr_store (gimple *stmt, struct type_change_info *tci,
;
else
{
base = get_ref_base_and_extent (lhs, &offset, &size, &max_size);
base = get_ref_base_and_extent (lhs, &offset, &size, &max_size, &reverse);
if (DECL_P (tci->instance))
{
if (base != tci->instance)
@ -1365,6 +1369,7 @@ check_stmt_for_type_change (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef, void *data)
tree op = walk_ssa_copies (gimple_call_arg (stmt, 0));
tree type = TYPE_METHOD_BASETYPE (TREE_TYPE (fn));
HOST_WIDE_INT offset = 0, size, max_size;
bool reverse;
if (dump_file)
{
@ -1375,8 +1380,8 @@ check_stmt_for_type_change (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef, void *data)
/* See if THIS parameter seems like instance pointer. */
if (TREE_CODE (op) == ADDR_EXPR)
{
op = get_ref_base_and_extent (TREE_OPERAND (op, 0),
&offset, &size, &max_size);
op = get_ref_base_and_extent (TREE_OPERAND (op, 0), &offset,
&size, &max_size, &reverse);
if (size != max_size || max_size == -1)
{
tci->speculative = true;
@ -1534,6 +1539,7 @@ ipa_polymorphic_call_context::get_dynamic_type (tree instance,
{
tree ref = gimple_call_fn (call);
HOST_WIDE_INT offset2, size, max_size;
bool reverse;
if (TREE_CODE (ref) == OBJ_TYPE_REF)
{
@ -1563,8 +1569,9 @@ ipa_polymorphic_call_context::get_dynamic_type (tree instance,
&& gimple_assign_load_p (SSA_NAME_DEF_STMT (ref)))
{
tree ref_exp = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (ref));
tree base_ref = get_ref_base_and_extent
(ref_exp, &offset2, &size, &max_size);
tree base_ref
= get_ref_base_and_extent (ref_exp, &offset2, &size,
&max_size, &reverse);
/* Finally verify that what we found looks like read from
OTR_OBJECT or from INSTANCE with offset OFFSET. */

View File

@ -952,7 +952,9 @@ ipa_load_from_parm_agg (struct ipa_func_body_info *fbi,
{
int index;
HOST_WIDE_INT size, max_size;
tree base = get_ref_base_and_extent (op, offset_p, &size, &max_size);
bool reverse;
tree base
= get_ref_base_and_extent (op, offset_p, &size, &max_size, &reverse);
if (max_size == -1 || max_size != size || *offset_p < 0)
return false;
@ -1077,6 +1079,7 @@ compute_complex_assign_jump_func (struct ipa_func_body_info *fbi,
{
HOST_WIDE_INT offset, size, max_size;
tree op1, tc_ssa, base, ssa;
bool reverse;
int index;
op1 = gimple_assign_rhs1 (stmt);
@ -1124,7 +1127,7 @@ compute_complex_assign_jump_func (struct ipa_func_body_info *fbi,
op1 = TREE_OPERAND (op1, 0);
if (TREE_CODE (TREE_TYPE (op1)) != RECORD_TYPE)
return;
base = get_ref_base_and_extent (op1, &offset, &size, &max_size);
base = get_ref_base_and_extent (op1, &offset, &size, &max_size, &reverse);
if (TREE_CODE (base) != MEM_REF
/* If this is a varying address, punt. */
|| max_size == -1
@ -1160,6 +1163,7 @@ get_ancestor_addr_info (gimple *assign, tree *obj_p, HOST_WIDE_INT *offset)
{
HOST_WIDE_INT size, max_size;
tree expr, parm, obj;
bool reverse;
if (!gimple_assign_single_p (assign))
return NULL_TREE;
@ -1169,7 +1173,7 @@ get_ancestor_addr_info (gimple *assign, tree *obj_p, HOST_WIDE_INT *offset)
return NULL_TREE;
expr = TREE_OPERAND (expr, 0);
obj = expr;
expr = get_ref_base_and_extent (expr, offset, &size, &max_size);
expr = get_ref_base_and_extent (expr, offset, &size, &max_size, &reverse);
if (TREE_CODE (expr) != MEM_REF
/* If this is a varying address, punt. */
@ -1435,10 +1439,11 @@ determine_locally_known_aggregate_parts (gcall *call, tree arg,
else if (TREE_CODE (arg) == ADDR_EXPR)
{
HOST_WIDE_INT arg_max_size;
bool reverse;
arg = TREE_OPERAND (arg, 0);
arg_base = get_ref_base_and_extent (arg, &arg_offset, &arg_size,
&arg_max_size);
&arg_max_size, &reverse);
if (arg_max_size == -1
|| arg_max_size != arg_size
|| arg_offset < 0)
@ -1457,13 +1462,14 @@ determine_locally_known_aggregate_parts (gcall *call, tree arg,
else
{
HOST_WIDE_INT arg_max_size;
bool reverse;
gcc_checking_assert (AGGREGATE_TYPE_P (TREE_TYPE (arg)));
by_ref = false;
check_ref = false;
arg_base = get_ref_base_and_extent (arg, &arg_offset, &arg_size,
&arg_max_size);
&arg_max_size, &reverse);
if (arg_max_size == -1
|| arg_max_size != arg_size
|| arg_offset < 0)
@ -1484,6 +1490,7 @@ determine_locally_known_aggregate_parts (gcall *call, tree arg,
gimple *stmt = gsi_stmt (gsi);
HOST_WIDE_INT lhs_offset, lhs_size, lhs_max_size;
tree lhs, rhs, lhs_base;
bool reverse;
if (!stmt_may_clobber_ref_p_1 (stmt, &r))
continue;
@ -1498,7 +1505,7 @@ determine_locally_known_aggregate_parts (gcall *call, tree arg,
break;
lhs_base = get_ref_base_and_extent (lhs, &lhs_offset, &lhs_size,
&lhs_max_size);
&lhs_max_size, &reverse);
if (lhs_max_size == -1
|| lhs_max_size != lhs_size)
break;
@ -3968,6 +3975,7 @@ ipa_modify_call_arguments (struct cgraph_edge *cs, gcall *stmt,
base = force_gimple_operand_gsi (&gsi, base,
true, NULL, true, GSI_SAME_STMT);
expr = fold_build2_loc (loc, MEM_REF, type, base, off);
REF_REVERSE_STORAGE_ORDER (expr) = adj->reverse;
/* If expr is not a valid gimple call argument emit
a load into a temporary. */
if (is_gimple_reg_type (TREE_TYPE (expr)))
@ -3987,6 +3995,7 @@ ipa_modify_call_arguments (struct cgraph_edge *cs, gcall *stmt,
else
{
expr = fold_build2_loc (loc, MEM_REF, adj->type, base, off);
REF_REVERSE_STORAGE_ORDER (expr) = adj->reverse;
expr = build_fold_addr_expr (expr);
expr = force_gimple_operand_gsi (&gsi, expr,
true, NULL, true, GSI_SAME_STMT);
@ -4091,7 +4100,10 @@ ipa_modify_expr (tree *expr, bool convert,
tree src;
if (cand->by_ref)
src = build_simple_mem_ref (cand->new_decl);
{
src = build_simple_mem_ref (cand->new_decl);
REF_REVERSE_STORAGE_ORDER (src) = cand->reverse;
}
else
src = cand->new_decl;
@ -4158,7 +4170,9 @@ ipa_get_adjustment_candidate (tree **expr, bool *convert,
}
HOST_WIDE_INT offset, size, max_size;
tree base = get_ref_base_and_extent (**expr, &offset, &size, &max_size);
bool reverse;
tree base
= get_ref_base_and_extent (**expr, &offset, &size, &max_size, &reverse);
if (!base || size == -1 || max_size == -1)
return NULL;

View File

@ -737,6 +737,10 @@ struct ipa_parm_adjustment
or one about to be removed. */
enum ipa_parm_op op;
/* Storage order of the original parameter (for the cases when the new
parameter is a component of an original one). */
unsigned reverse : 1;
/* The parameter is to be passed by reference. */
unsigned by_ref : 1;
};
@ -774,7 +778,7 @@ ipa_parm_adjustment *ipa_get_adjustment_candidate (tree **, bool *,
/* From tree-sra.c: */
tree build_ref_for_offset (location_t, tree, HOST_WIDE_INT, tree,
tree build_ref_for_offset (location_t, tree, HOST_WIDE_INT, bool, tree,
gimple_stmt_iterator *, bool);
/* In ipa-cp.c */

View File

@ -958,7 +958,8 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
hstate.add_flag (TREE_PRIVATE (t));
if (TYPE_P (t))
{
hstate.add_flag (TYPE_SATURATING (t));
hstate.add_flag (AGGREGATE_TYPE_P (t)
? TYPE_REVERSE_STORAGE_ORDER (t) : TYPE_SATURATING (t));
hstate.add_flag (TYPE_ADDR_SPACE (t));
}
else if (code == SSA_NAME)

View File

@ -1,3 +1,7 @@
2015-11-08 Eric Botcazou <ebotcazou@adacore.com>
* lto.c (compare_tree_sccs_1): Deal with TYPE_REVERSE_STORAGE_ORDER.
2015-11-07 Richard Sandiford <richard.sandiford@arm.com>
* lto-lang.c: Don't undef DEF_BUILTIN.

View File

@ -1021,7 +1021,10 @@ compare_tree_sccs_1 (tree t1, tree t2, tree **map)
compare_values (TREE_DEPRECATED);
if (TYPE_P (t1))
{
compare_values (TYPE_SATURATING);
if (AGGREGATE_TYPE_P (t1))
compare_values (TYPE_REVERSE_STORAGE_ORDER);
else
compare_values (TYPE_SATURATING);
compare_values (TYPE_ADDR_SPACE);
}
else if (code == SSA_NAME)

View File

@ -278,10 +278,11 @@ extern section *get_named_text_section (tree, const char *, const char *);
#define assemble_aligned_integer(SIZE, VALUE) \
assemble_integer (VALUE, SIZE, (SIZE) * BITS_PER_UNIT, 1)
#ifdef REAL_VALUE_TYPE_SIZE
/* Assemble the floating-point constant D into an object of size MODE. */
extern void assemble_real (REAL_VALUE_TYPE, machine_mode, unsigned);
#endif
/* 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. */
extern void assemble_real (REAL_VALUE_TYPE, machine_mode, unsigned,
bool = false);
/* Write the address of the entity given by SYMBOL to SEC. */
extern void assemble_addr_to_section (rtx, section *);

View File

@ -565,6 +565,13 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
if (TYPE_NEEDS_CONSTRUCTING (node))
fputs (" needs-constructing", file);
if ((code == RECORD_TYPE
|| code == UNION_TYPE
|| code == QUAL_UNION_TYPE
|| code == ARRAY_TYPE)
&& TYPE_REVERSE_STORAGE_ORDER (node))
fputs (" reverse-storage-order", file);
/* The transparent-union flag is used for different things in
different nodes. */
if ((code == UNION_TYPE || code == RECORD_TYPE)

View File

@ -301,10 +301,11 @@ delegitimize_mem_from_attrs (rtx x)
{
HOST_WIDE_INT bitsize, bitpos;
tree toffset;
int unsignedp, volatilep = 0;
int unsignedp, reversep, volatilep = 0;
decl = get_inner_reference (decl, &bitsize, &bitpos, &toffset,
&mode, &unsignedp, &volatilep, false);
decl
= get_inner_reference (decl, &bitsize, &bitpos, &toffset, &mode,
&unsignedp, &reversep, &volatilep, false);
if (bitsize != GET_MODE_BITSIZE (mode)
|| (bitpos % BITS_PER_UNIT)
|| (toffset && !tree_fits_shwi_p (toffset)))

View File

@ -2035,11 +2035,16 @@ finish_record_layout (record_layout_info rli, int free_p)
/* Compute bitfield representatives. */
finish_bitfield_layout (rli->t);
/* Propagate TYPE_PACKED to variants. With C++ templates,
handle_packed_attribute is too early to do this. */
/* Propagate TYPE_PACKED and TYPE_REVERSE_STORAGE_ORDER to variants.
With C++ templates, it is too early to do this when the attribute
is being parsed. */
for (variant = TYPE_NEXT_VARIANT (rli->t); variant;
variant = TYPE_NEXT_VARIANT (variant))
TYPE_PACKED (variant) = TYPE_PACKED (rli->t);
{
TYPE_PACKED (variant) = TYPE_PACKED (rli->t);
TYPE_REVERSE_STORAGE_ORDER (variant)
= TYPE_REVERSE_STORAGE_ORDER (rli->t);
}
/* Lay out any static members. This is done now because their type
may use the record's type. */

View File

@ -1,3 +1,26 @@
2015-11-08 Eric Botcazou <ebotcazou@adacore.com>
* gcc.dg/sso-1.c: New test.
* gcc.dg/sso-2.c: Likewise.
* gcc.dg/sso-3.c: Likewise.
* gcc.dg/sso-4.c: Likewise.
* gcc.dg/sso-5.c: Likewise.
* gcc.dg/sso-6.c: Likewise.
* gcc.dg/sso-7.c: Likewise.
* gcc.dg/sso-8.c: Likewise.
* gcc.dg/sso: New directory.
* gcc.target/i386/movbe-3.c: New test.
* gnat.dg/sso1.adb: Likewise.
* gnat.dg/sso2.ad[sb]: Likewise.
* gnat.dg/sso3.adb: Likewise.
* gnat.dg/sso4.adb: Likewise.
* gnat.dg/sso5.adb: Likewise.
* gnat.dg/sso6.adb: Likewise.
* gnat.dg/sso7.adb: Likewise.
* gnat.dg/specs/sso1.ads: Likewise.
* gnat.dg/specs/sso2.ads: Likewise.
* gnat.dg/sso: New directory.
2015-11-08 Andre Vehreschild <vehre@gcc.gnu.org>
PR fortran/68218

View File

@ -0,0 +1,19 @@
/* Test support of scalar_storage_order attribute */
/* { dg-do compile } */
int i;
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
struct __attribute__((scalar_storage_order("big-endian"))) Rec
{
int *p;
};
#else
struct __attribute__((scalar_storage_order("little-endian"))) Rec
{
int *p;
};
#endif
struct Rec r = { &i }; /* { dg-error "element is not constant" } */

View File

@ -0,0 +1,94 @@
/* Test support of scalar_storage_order attribute */
/* { dg-do compile } */
struct __attribute__((scalar_storage_order("big-endian"))) S1
{
int i;
};
struct __attribute__((scalar_storage_order("little-endian"))) S2
{
int i;
};
struct __attribute__((scalar_storage_order("other"))) S3 { int i; }; /* { dg-error "must be one of .big-endian. or .little-endian." } */
void incompatible_assign (struct S1 *s1, struct S2 *s2)
{
*s1 = *s2; /* { dg-error "(incompatible types|no match)" } */
}
int *addr1 (int which, struct S1 *s1, struct S2 *s2)
{
return (which == 1 ? &s1->i : &s2->i); /* { dg-error "address of scalar with reverse storage order" } */
}
struct __attribute__((scalar_storage_order("big-endian"))) S4
{
int a[4];
struct S2 s2;
};
struct __attribute__((scalar_storage_order("little-endian"))) S5
{
int a[4];
struct S1 s1;
};
void *addr2 (int which, struct S4 *s4, struct S5 *s5)
{
return (which == 1 ? (void *)s4->a : (void *)s5->a); /* { dg-warning "address of array with reverse scalar storage order" } */
}
void *addr3 (int which, struct S4 *s4, struct S5 *s5)
{
return (which == 1 ? (void *)&s4->a : (void *)&s5->a); /* { dg-warning "address of array with reverse scalar storage order" } */
}
void *addr4 (int which, struct S4 *s4, struct S5 *s5)
{
return (which == 1 ? (void *)&s4->a[0] : (void *)&s5->a[0]); /* { dg-error "address of scalar with reverse storage order" } */
}
void *addr5 (int which, struct S4 *s4, struct S5 *s5)
{
return (which == 1 ? (void *)&s4->s2 : (void *) &s5->s1); /* ok */
}
struct __attribute__((scalar_storage_order("big-endian"))) S6
{
int a[4][2];
struct S2 s2[2];
};
struct __attribute__((scalar_storage_order("little-endian"))) S7
{
int a[4][2];
struct S1 s1[2];
};
void *addr6 (int which, struct S6 *s6, struct S7 *s7)
{
return (which == 1 ? (void *)s6->a : (void *)s7->a); /* { dg-warning "address of array with reverse scalar storage order" } */
}
void *addr7 (int which, struct S6 *s6, struct S7 *s7)
{
return (which == 1 ? (void *)&s6->a : (void *)&s7->a); /* { dg-warning "address of array with reverse scalar storage order" } */
}
void *addr8 (int which, struct S6 *s6, struct S7 *s7)
{
return (which == 1 ? (void *)&s6->a[0] : (void *)&s7->a[0]); /* { dg-warning "address of array with reverse scalar storage order" } */
}
void *addr9 (int which, struct S6 *s6, struct S7 *s7)
{
return (which == 1 ? (void *)&s6->a[0][0] : (void *)&s7->a[0][0]); /* { dg-error "address of scalar with reverse storage order" } */
}
void *addr10 (int which, struct S6 *s6, struct S7 *s7)
{
return (which == 1 ? (void *)&s6->s2 : (void *)&s7->s1); /* ok */
}

View File

@ -0,0 +1,94 @@
/* Test support of scalar_storage_order attribute */
/* { dg-do compile } */
struct S1
{
int i;
} __attribute__((scalar_storage_order("big-endian")));
struct S2
{
int i;
} __attribute__((scalar_storage_order("little-endian")));
struct S3 { int i; } __attribute__((scalar_storage_order("other"))); /* { dg-error "must be one of .big-endian. or .little-endian." } */
void incompatible_assign (struct S1 *s1, struct S2 *s2)
{
*s1 = *s2; /* { dg-error "(incompatible types|no match)" } */
}
int *addr1 (int which, struct S1 *s1, struct S2 *s2)
{
return (which == 1 ? &s1->i : &s2->i); /* { dg-error "address of scalar with reverse storage order" } */
}
struct S4
{
int a[4];
struct S2 s2;
} __attribute__((scalar_storage_order("big-endian")));
struct S5
{
int a[4];
struct S1 s1;
} __attribute__((scalar_storage_order("little-endian")));
void *addr2 (int which, struct S4 *s4, struct S5 *s5)
{
return (which == 1 ? (void *)s4->a : (void *)s5->a); /* { dg-warning "address of array with reverse scalar storage order" } */
}
void *addr3 (int which, struct S4 *s4, struct S5 *s5)
{
return (which == 1 ? (void *)&s4->a : (void *)&s5->a); /* { dg-warning "address of array with reverse scalar storage order" } */
}
void *addr4 (int which, struct S4 *s4, struct S5 *s5)
{
return (which == 1 ? (void *)&s4->a[0] : (void *)&s5->a[0]); /* { dg-error "address of scalar with reverse storage order" } */
}
void *addr5 (int which, struct S4 *s4, struct S5 *s5)
{
return (which == 1 ? (void *)&s4->s2 : (void *) &s5->s1); /* ok */
}
struct S6
{
int a[4][2];
struct S2 s2[2];
} __attribute__((scalar_storage_order("big-endian")));
struct S7
{
int a[4][2];
struct S1 s1[2];
} __attribute__((scalar_storage_order("little-endian")));
void *addr6 (int which, struct S6 *s6, struct S7 *s7)
{
return (which == 1 ? (void *)s6->a : (void *)s7->a); /* { dg-warning "address of array with reverse scalar storage order" } */
}
void *addr7 (int which, struct S6 *s6, struct S7 *s7)
{
return (which == 1 ? (void *)&s6->a : (void *)&s7->a); /* { dg-warning "address of array with reverse scalar storage order" } */
}
void *addr8 (int which, struct S6 *s6, struct S7 *s7)
{
return (which == 1 ? (void *)&s6->a[0] : (void *)&s7->a[0]); /* { dg-warning "address of array with reverse scalar storage order" } */
}
void *addr9 (int which, struct S6 *s6, struct S7 *s7)
{
return (which == 1 ? (void *)&s6->a[0][0] : (void *)&s7->a[0][0]); /* { dg-error "address of scalar with reverse storage order" } */
}
void *addr10 (int which, struct S6 *s6, struct S7 *s7)
{
return (which == 1 ? (void *)&s6->s2 : (void *)&s7->s1); /* ok */
}

View File

@ -0,0 +1,20 @@
/* Test support of scalar_storage_order attribute */
/* { dg-do compile } */
struct S
{
int i;
};
typedef struct S __attribute__((scalar_storage_order("big-endian"))) S1;
typedef struct S __attribute__((scalar_storage_order("little-endian"))) S2;
typedef struct S __attribute__((scalar_storage_order("other"))) S3; /* { dg-error "must be one of .big-endian. or .little-endian." } */
void incompatible_assign (struct S *s, S1 *s1, S2 *s2)
{
*s = *s1, *s = *s2; /* { dg-error "(incompatible types|no match)" } */
*s1 = *s2; /* { dg-error "(incompatible types|no match)" } */
}

View File

@ -0,0 +1,24 @@
/* Test support of scalar_storage_order attribute */
/* { dg-do compile } */
struct S3
{
struct __attribute__((scalar_storage_order("big-endian"))) S1
{
int i;
} s1;
};
struct S4
{
struct __attribute__((scalar_storage_order("little-endian"))) S2
{
int i;
} s2;
};
void incompatible_assign (struct S3 *s3, struct S4 *s4)
{
s3->s1 = s4->s2; /* { dg-error "(incompatible types|no match)" } */
}

View File

@ -0,0 +1,72 @@
/* Test support of scalar_storage_order pragma */
/* { dg-do run } */
#pragma scalar_storage_order /* { dg-warning "missing .big-endian.little-endian.default." } */
#pragma scalar_storage_order big-endian
struct S1
{
int i;
};
struct __attribute__((scalar_storage_order("little-endian"))) S2
{
int i;
};
#pragma scalar_storage_order little-endian
struct S3
{
int i;
};
struct __attribute__((scalar_storage_order("big-endian"))) S4
{
int i;
};
#pragma scalar_storage_order default
struct S5
{
int i;
};
#pragma scalar_storage_order other /* { dg-warning "expected .big-endian.little-endian.default." } */
struct S1 my_s1 = { 0x12345678 };
struct S2 my_s2 = { 0x12345678 };
struct S3 my_s3 = { 0x12345678 };
struct S4 my_s4 = { 0x12345678 };
struct S5 my_s5 = { 0x12345678 };
unsigned char big_endian_pattern[4] = { 0x12, 0x34, 0x56, 0x78 };
unsigned char little_endian_pattern[4] = { 0x78, 0x56, 0x34, 0x12 };
int main (void)
{
if (__builtin_memcmp (&my_s1, &big_endian_pattern, 4) != 0)
__builtin_abort ();
if (__builtin_memcmp (&my_s2, &little_endian_pattern, 4) != 0)
__builtin_abort ();
if (__builtin_memcmp (&my_s3, &little_endian_pattern, 4) != 0)
__builtin_abort ();
if (__builtin_memcmp (&my_s4, &big_endian_pattern, 4) != 0)
__builtin_abort ();
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
if (__builtin_memcmp (&my_s5, &little_endian_pattern, 4) != 0)
__builtin_abort ();
#else
if (__builtin_memcmp (&my_s5, &big_endian_pattern, 4) != 0)
__builtin_abort ();
#endif
return 0;
}

View File

@ -0,0 +1,44 @@
/* Test support of scalar_storage_order pragma */
/* { dg-do run } */
/* { dg-options "-fsso-struct=big-endian" } */
struct S1
{
int i;
};
#pragma scalar_storage_order little-endian
struct S2
{
int i;
};
#pragma scalar_storage_order default
struct S3
{
int i;
};
struct S1 my_s1 = { 0x12345678 };
struct S2 my_s2 = { 0x12345678 };
struct S3 my_s3 = { 0x12345678 };
unsigned char big_endian_pattern[4] = { 0x12, 0x34, 0x56, 0x78 };
unsigned char little_endian_pattern[4] = { 0x78, 0x56, 0x34, 0x12 };
int main (void)
{
if (__builtin_memcmp (&my_s1, &big_endian_pattern, 4) != 0)
__builtin_abort ();
if (__builtin_memcmp (&my_s2, &little_endian_pattern, 4) != 0)
__builtin_abort ();
if (__builtin_memcmp (&my_s3, &big_endian_pattern, 4) != 0)
__builtin_abort ();
return 0;
}

View File

@ -0,0 +1,44 @@
/* Test support of scalar_storage_order pragma */
/* { dg-do run } */
/* { dg-options "-fsso-struct=little-endian" } */
struct S1
{
int i;
};
#pragma scalar_storage_order big-endian
struct S2
{
int i;
};
#pragma scalar_storage_order default
struct S3
{
int i;
};
struct S1 my_s1 = { 0x12345678 };
struct S2 my_s2 = { 0x12345678 };
struct S3 my_s3 = { 0x12345678 };
unsigned char big_endian_pattern[4] = { 0x12, 0x34, 0x56, 0x78 };
unsigned char little_endian_pattern[4] = { 0x78, 0x56, 0x34, 0x12 };
int main (void)
{
if (__builtin_memcmp (&my_s1, &little_endian_pattern, 4) != 0)
__builtin_abort ();
if (__builtin_memcmp (&my_s2, &big_endian_pattern, 4) != 0)
__builtin_abort ();
if (__builtin_memcmp (&my_s3, &little_endian_pattern, 4) != 0)
__builtin_abort ();
return 0;
}

View File

@ -0,0 +1,23 @@
void dump (void *p, unsigned int len)
{
const char digits[17] = "0123456789abcdef";
unsigned char *a = (unsigned char *)p;
int i;
for (i = 0; i < len; i++)
{
putchar (' ');
putchar (digits[a[i] / 16]);
putchar (digits[a[i] % 16]);
}
}
void put (const char s[])
{
fputs (s, stdout);
}
void new_line (void)
{
putchar ('\n');
}

View File

@ -0,0 +1,12 @@
struct __attribute__((scalar_storage_order("little-endian"))) R1
{
int I;
};
struct __attribute__((scalar_storage_order("big-endian"))) R2
{
int I;
};
struct R1 My_R1 = { 0x12345678 };
struct R2 My_R2 = { 0x12345678 };

View File

@ -0,0 +1,15 @@
#define I (__extension__ 1.0iF)
#define Pi 3.1415927f
struct __attribute__((scalar_storage_order("little-endian"))) R1
{
_Complex float F;
};
struct __attribute__((scalar_storage_order("big-endian"))) R2
{
_Complex float F;
};
struct R1 My_R1 = { Pi - Pi * I };
struct R2 My_R2 = { Pi - Pi * I };

View File

@ -0,0 +1,24 @@
struct __attribute__((scalar_storage_order("little-endian"), packed)) R1
{
unsigned S1 : 2;
unsigned I : 32;
unsigned S2 : 2;
unsigned A1 : 9;
unsigned A2 : 9;
unsigned A3 : 9;
unsigned B : 1;
};
struct __attribute__((scalar_storage_order("big-endian"), packed)) R2
{
unsigned S1 : 2;
unsigned I : 32;
unsigned S2 : 2;
unsigned A1 : 9;
unsigned A2 : 9;
unsigned A3 : 9;
unsigned B : 1;
};
struct R1 My_R1 = { 2, 0x12345678, 1, 0xAB, 0xCD, 0xEF, 1 };
struct R2 My_R2 = { 2, 0x12345678, 1, 0xAB, 0xCD, 0xEF, 1 };

View File

@ -0,0 +1,34 @@
struct __attribute__((scalar_storage_order("little-endian"), packed)) Nested1
{
unsigned C1 : 7;
unsigned C2 : 7;
unsigned C3 : 7;
unsigned B : 3;
};
struct __attribute__((scalar_storage_order("little-endian"), packed)) R1
{
unsigned S1 : 6;
unsigned I : 32;
unsigned S2 : 2;
struct Nested1 N;
};
struct __attribute__((scalar_storage_order("big-endian"), packed)) Nested2
{
unsigned C1 : 7;
unsigned C2 : 7;
unsigned C3 : 7;
unsigned B : 3;
};
struct __attribute__((scalar_storage_order("big-endian"), packed)) R2
{
unsigned S1 : 6;
unsigned I : 32;
unsigned S2 : 2;
struct Nested2 N;
};
struct R1 My_R1 = { 2, 0x78ABCDEF, 1, { 0x12, 0x34, 0x56, 4 } };
struct R2 My_R2 = { 2, 0x78ABCDEF, 1, { 0x12, 0x34, 0x56, 4 } };

View File

@ -0,0 +1,14 @@
#define Pi 3.1415927f
struct __attribute__((scalar_storage_order("little-endian"))) R1
{
float F;
};
struct __attribute__((scalar_storage_order("big-endian"))) R2
{
float F;
};
struct R1 My_R1 = { Pi };
struct R2 My_R2 = { Pi };

View File

@ -0,0 +1,14 @@
struct __attribute__((scalar_storage_order("little-endian"))) R1
{
int I;
int A[3];
};
struct __attribute__((scalar_storage_order("big-endian"))) R2
{
int I;
int A[3];
};
struct R1 My_R1 = { 0x12345678, { 0xAB0012, 0xCD0034, 0xEF0056 } };
struct R2 My_R2 = { 0x12345678, { 0xAB0012, 0xCD0034, 0xEF0056 } };

View File

@ -0,0 +1,24 @@
struct __attribute__((scalar_storage_order("big-endian"))) Nested1
{
int A[3];
};
struct __attribute__((scalar_storage_order("little-endian"))) R1
{
int I;
struct Nested1 N;
};
struct __attribute__((scalar_storage_order("little-endian"))) Nested2
{
int A[3];
};
struct __attribute__((scalar_storage_order("big-endian"))) R2
{
int I;
struct Nested2 N;
};
struct R1 My_R1 = { 0x12345678, { { 0xAB0012, 0xCD0034, 0xEF0056 } } };
struct R2 My_R2 = { 0x12345678, { { 0xAB0012, 0xCD0034, 0xEF0056 } } };

View File

@ -0,0 +1,28 @@
struct __attribute__((scalar_storage_order("little-endian"))) Nested1
{
int C1;
int C2;
int C3;
};
struct __attribute__((scalar_storage_order("little-endian"))) R1
{
int I;
struct Nested1 N;
};
struct __attribute__((scalar_storage_order("big-endian"))) Nested2
{
int C1;
int C2;
int C3;
};
struct __attribute__((scalar_storage_order("big-endian"))) R2
{
int I;
struct Nested2 N;
};
struct R1 My_R1 = { 0x12345678, { 0xAB0012, 0xCD0034, 0xEF0056 } };
struct R2 My_R2 = { 0x12345678, { 0xAB0012, 0xCD0034, 0xEF0056 } };

View File

@ -0,0 +1,28 @@
struct __attribute__((scalar_storage_order("big-endian"))) Nested1
{
int C1;
int C2;
int C3;
};
struct __attribute__((scalar_storage_order("little-endian"))) R1
{
int I;
struct Nested1 N;
};
struct __attribute__((scalar_storage_order("little-endian"))) Nested2
{
int C1;
int C2;
int C3;
};
struct __attribute__((scalar_storage_order("big-endian"))) R2
{
int I;
struct Nested2 N;
};
struct R1 My_R1 = { 0x12345678, { 0xAB0012, 0xCD0034, 0xEF0056 } };
struct R2 My_R2 = { 0x12345678, { 0xAB0012, 0xCD0034, 0xEF0056 } };

View File

@ -0,0 +1,14 @@
#define Pi 3.14159265358979323846
struct __attribute__((scalar_storage_order("little-endian"))) R1
{
double F;
};
struct __attribute__((scalar_storage_order("big-endian"))) R2
{
double F;
};
struct R1 My_R1 = { Pi };
struct R2 My_R2 = { Pi };

View File

@ -0,0 +1,64 @@
/* { dg-do run } */
#include <stdio.h>
#include "init1.h"
#include "dump.h"
int main (void)
{
struct R1 Local_R1;
struct R2 Local_R2;
put ("My_R1 :");
dump (&My_R1, sizeof (struct R1));
new_line ();
/* { dg-output "My_R1 : 78 56 34 12\n" } */
put ("My_R2 :");
dump (&My_R2, sizeof (struct R2));
new_line ();
/* { dg-output "My_R2 : 12 34 56 78\n" } */
Local_R1 = My_R1;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : 78 56 34 12\n" } */
Local_R2 = My_R2;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 12 34 56 78\n" } */
Local_R1.I = 0x12345678;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : 78 56 34 12\n" } */
Local_R2.I = 0x12345678;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 12 34 56 78\n" } */
Local_R1.I = Local_R2.I;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : 78 56 34 12\n" } */
Local_R2.I = Local_R1.I;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 12 34 56 78\n" } */
return 0;
}

View File

@ -0,0 +1,64 @@
/* { dg-do run } */
#include <stdio.h>
#include "init13.h"
#include "dump.h"
int main (void)
{
struct R1 Local_R1;
struct R2 Local_R2;
put ("My_R1 :");
dump (&My_R1, sizeof (struct R1));
new_line ();
/* { dg-output "My_R1 : db 0f 49 40 db 0f 49 c0\n" } */
put ("My_R2 :");
dump (&My_R2, sizeof (struct R2));
new_line ();
/* { dg-output "My_R2 : 40 49 0f db c0 49 0f db\n" } */
Local_R1 = My_R1;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : db 0f 49 40 db 0f 49 c0\n" } */
Local_R2 = My_R2;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 40 49 0f db c0 49 0f db\n" } */
Local_R1.F = Pi - Pi * I;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : db 0f 49 40 db 0f 49 c0\n" } */
Local_R2.F = Pi - Pi * I;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 40 49 0f db c0 49 0f db\n" } */
Local_R1.F = Local_R2.F;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : db 0f 49 40 db 0f 49 c0\n" } */
Local_R2.F = Local_R1.F;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 40 49 0f db c0 49 0f db\n" } */
return 0;
}

View File

@ -0,0 +1,88 @@
/* { dg-do run } */
#include <stdio.h>
#include "init2.h"
#include "dump.h"
int main (void)
{
struct R1 Local_R1;
struct R2 Local_R2;
put ("My_R1 :");
dump (&My_R1, sizeof (struct R1));
new_line ();
/* { dg-output "My_R1 : e2 59 d1 48 b4 aa d9 bb\n" } */
put ("My_R2 :");
dump (&My_R2, sizeof (struct R2));
new_line ();
/* { dg-output "My_R2 : 84 8d 15 9e 15 5b 35 df\n" } */
Local_R1 = My_R1;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : e2 59 d1 48 b4 aa d9 bb\n" } */
Local_R2 = My_R2;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 84 8d 15 9e 15 5b 35 df\n" } */
Local_R1.S1 = 2;
Local_R1.I = 0x12345678;
Local_R1.S2 = 1;
Local_R1.A1 = 0xAB;
Local_R1.A2 = 0xCD;
Local_R1.A3 = 0xEF;
Local_R1.B = 1;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : e2 59 d1 48 b4 aa d9 bb\n" } */
Local_R2.S1 = 2;
Local_R2.I = 0x12345678;
Local_R2.S2 = 1;
Local_R2.A1 = 0xAB;
Local_R2.A2 = 0xCD;
Local_R2.A3 = 0xEF;
Local_R2.B = 1;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 84 8d 15 9e 15 5b 35 df\n" } */
Local_R1.S1 = Local_R2.S1;
Local_R1.I = Local_R2.I;
Local_R1.S2 = Local_R2.S2;
Local_R1.A1 = Local_R2.A1;
Local_R1.A2 = Local_R2.A2;
Local_R1.A3 = Local_R2.A3;
Local_R1.B = Local_R2.B;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : e2 59 d1 48 b4 aa d9 bb\n" } */
Local_R2.S1 = Local_R1.S1;
Local_R2.I = Local_R1.I;
Local_R2.S2 = Local_R1.S2;
Local_R2.A1 = Local_R1.A1;
Local_R2.A2 = Local_R1.A2;
Local_R2.A3 = Local_R1.A3;
Local_R2.B = Local_R1.B;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 84 8d 15 9e 15 5b 35 df\n" } */
return 0;
}

View File

@ -0,0 +1,88 @@
/* { dg-do run } */
#include <stdio.h>
#include "init3.h"
#include "dump.h"
int main (void)
{
struct R1 Local_R1;
struct R2 Local_R2;
put ("My_R1 :");
dump (&My_R1, sizeof (struct R1));
new_line ();
/* { dg-output "My_R1 : c2 7b f3 2a 5e 12 9a 95\n" } */
put ("My_R2 :");
dump (&My_R2, sizeof (struct R2));
new_line ();
/* { dg-output "My_R2 : 09 e2 af 37 bd 24 d2 b4\n" } */
Local_R1 = My_R1;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : c2 7b f3 2a 5e 12 9a 95\n" } */
Local_R2 = My_R2;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 09 e2 af 37 bd 24 d2 b4\n" } */
Local_R1.S1 = 2;
Local_R1.I = 0x78ABCDEF;
Local_R1.S2 = 1;
Local_R1.N.C1 = 0x12;
Local_R1.N.C2 = 0x34;
Local_R1.N.C3 = 0x56;
Local_R1.N.B = 4;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : c2 7b f3 2a 5e 12 9a 95\n" } */
Local_R2.S1 = 2;
Local_R2.I = 0x78ABCDEF;
Local_R2.S2 = 1;
Local_R2.N.C1 = 0x12;
Local_R2.N.C2 = 0x34;
Local_R2.N.C3 = 0x56;
Local_R2.N.B = 4;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 09 e2 af 37 bd 24 d2 b4\n" } */
Local_R1.S1 = Local_R2.S1;
Local_R1.I = Local_R2.I;
Local_R1.S2 = Local_R2.S2;
Local_R1.N.C1 = Local_R2.N.C1;
Local_R1.N.C2 = Local_R2.N.C2;
Local_R1.N.C3 = Local_R2.N.C3;
Local_R1.N.B = Local_R2.N.B;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : c2 7b f3 2a 5e 12 9a 95\n" } */
Local_R2.S1 = Local_R1.S1;
Local_R2.I = Local_R1.I;
Local_R2.S2 = Local_R1.S2;
Local_R2.N.C1 = Local_R1.N.C1;
Local_R2.N.C2 = Local_R1.N.C2;
Local_R2.N.C3 = Local_R1.N.C3;
Local_R2.N.B = Local_R1.N.B;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 09 e2 af 37 bd 24 d2 b4\n" } */
return 0;
}

View File

@ -0,0 +1,64 @@
/* { dg-do run } */
#include <stdio.h>
#include "init4.h"
#include "dump.h"
int main (void)
{
struct R1 Local_R1;
struct R2 Local_R2;
put ("My_R1 :");
dump (&My_R1, sizeof (struct R1));
new_line ();
/* { dg-output "My_R1 : db 0f 49 40\n" } */
put ("My_R2 :");
dump (&My_R2, sizeof (struct R2));
new_line ();
/* { dg-output "My_R2 : 40 49 0f db\n" } */
Local_R1 = My_R1;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : db 0f 49 40\n" } */
Local_R2 = My_R2;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 40 49 0f db\n" } */
Local_R1.F = Pi;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : db 0f 49 40\n" } */
Local_R2.F = Pi;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 40 49 0f db\n" } */
Local_R1.F = Local_R2.F;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : db 0f 49 40\n" } */
Local_R2.F = Local_R1.F;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 40 49 0f db\n" } */
return 0;
}

View File

@ -0,0 +1,74 @@
/* { dg-do run } */
#include <stdio.h>
#include "init5.h"
#include "dump.h"
int main (void)
{
struct R1 Local_R1;
struct R2 Local_R2;
put ("My_R1 :");
dump (&My_R1, sizeof (struct R1));
new_line ();
/* { dg-output "My_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
put ("My_R2 :");
dump (&My_R2, sizeof (struct R2));
new_line ();
/* { dg-output "My_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
Local_R1 = My_R1;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
Local_R2 = My_R2;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
Local_R1.I = 0x12345678;
Local_R1.A[0] = 0xAB0012;
Local_R1.A[1] = 0xCD0034;
Local_R1.A[2] = 0xEF0056;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
Local_R2.I = 0x12345678;
Local_R2.A[0] = 0xAB0012;
Local_R2.A[1] = 0xCD0034;
Local_R2.A[2] = 0xEF0056;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
Local_R1.I = Local_R2.I;
Local_R1.A[0] = Local_R2.A[0];
Local_R1.A[1] = Local_R2.A[1];
Local_R1.A[2] = Local_R2.A[2];
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
Local_R2.I = Local_R1.I;
Local_R2.A[0] = Local_R1.A[0];
Local_R2.A[1] = Local_R1.A[1];
Local_R2.A[2] = Local_R1.A[2];
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
return 0;
}

View File

@ -0,0 +1,74 @@
/* { dg-do run } */
#include <stdio.h>
#include "init6.h"
#include "dump.h"
int main (void)
{
struct R1 Local_R1;
struct R2 Local_R2;
put ("My_R1 :");
dump (&My_R1, sizeof (struct R1));
new_line ();
/* { dg-output "My_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
put ("My_R2 :");
dump (&My_R2, sizeof (struct R2));
new_line ();
/* { dg-output "My_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
Local_R1 = My_R1;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
Local_R2 = My_R2;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
Local_R1.I = 0x12345678;
Local_R1.N.A[0] = 0xAB0012;
Local_R1.N.A[1] = 0xCD0034;
Local_R1.N.A[2] = 0xEF0056;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
Local_R2.I = 0x12345678;
Local_R2.N.A[0] = 0xAB0012;
Local_R2.N.A[1] = 0xCD0034;
Local_R2.N.A[2] = 0xEF0056;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
Local_R1.I = Local_R2.I;
Local_R1.N.A[0] = Local_R2.N.A[0];
Local_R1.N.A[1] = Local_R2.N.A[1];
Local_R1.N.A[2] = Local_R2.N.A[2];
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
Local_R2.I = Local_R1.I;
Local_R2.N.A[0] = Local_R1.N.A[0];
Local_R2.N.A[1] = Local_R1.N.A[1];
Local_R2.N.A[2] = Local_R1.N.A[2];
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
return 0;
}

View File

@ -0,0 +1,74 @@
/* { dg-do run } */
#include <stdio.h>
#include "init7.h"
#include "dump.h"
int main (void)
{
struct R1 Local_R1;
struct R2 Local_R2;
put ("My_R1 :");
dump (&My_R1, sizeof (struct R1));
new_line ();
/* { dg-output "My_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
put ("My_R2 :");
dump (&My_R2, sizeof (struct R2));
new_line ();
/* { dg-output "My_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
Local_R1 = My_R1;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
Local_R2 = My_R2;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
Local_R1.I = 0x12345678;
Local_R1.N.C1 = 0xAB0012;
Local_R1.N.C2 = 0xCD0034;
Local_R1.N.C3 = 0xEF0056;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
Local_R2.I = 0x12345678;
Local_R2.N.C1 = 0xAB0012;
Local_R2.N.C2 = 0xCD0034;
Local_R2.N.C3 = 0xEF0056;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
Local_R1.I = Local_R2.I;
Local_R1.N.C1 = Local_R2.N.C1;
Local_R1.N.C2 = Local_R2.N.C2;
Local_R1.N.C3 = Local_R2.N.C3;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
Local_R2.I = Local_R1.I;
Local_R2.N.C1 = Local_R1.N.C1;
Local_R2.N.C2 = Local_R1.N.C2;
Local_R2.N.C3 = Local_R1.N.C3;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
return 0;
}

View File

@ -0,0 +1,74 @@
/* { dg-do run } */
#include <stdio.h>
#include "init8.h"
#include "dump.h"
int main (void)
{
struct R1 Local_R1;
struct R2 Local_R2;
put ("My_R1 :");
dump (&My_R1, sizeof (struct R1));
new_line ();
/* { dg-output "My_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
put ("My_R2 :");
dump (&My_R2, sizeof (struct R2));
new_line ();
/* { dg-output "My_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
Local_R1 = My_R1;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
Local_R2 = My_R2;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
Local_R1.I = 0x12345678;
Local_R1.N.C1 = 0xAB0012;
Local_R1.N.C2 = 0xCD0034;
Local_R1.N.C3 = 0xEF0056;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
Local_R2.I = 0x12345678;
Local_R2.N.C1 = 0xAB0012;
Local_R2.N.C2 = 0xCD0034;
Local_R2.N.C3 = 0xEF0056;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
Local_R1.I = Local_R2.I;
Local_R1.N.C1 = Local_R2.N.C1;
Local_R1.N.C2 = Local_R2.N.C2;
Local_R1.N.C3 = Local_R2.N.C3;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
Local_R2.I = Local_R1.I;
Local_R2.N.C1 = Local_R1.N.C1;
Local_R2.N.C2 = Local_R1.N.C2;
Local_R2.N.C3 = Local_R1.N.C3;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
return 0;
}

View File

@ -0,0 +1,64 @@
/* { dg-do run } */
#include <stdio.h>
#include "init9.h"
#include "dump.h"
int main (void)
{
struct R1 Local_R1;
struct R2 Local_R2;
put ("My_R1 :");
dump (&My_R1, sizeof (struct R1));
new_line ();
/* { dg-output "My_R1 : 18 2d 44 54 fb 21 09 40\n" } */
put ("My_R2 :");
dump (&My_R2, sizeof (struct R2));
new_line ();
/* { dg-output "My_R2 : 40 09 21 fb 54 44 2d 18\n" } */
Local_R1 = My_R1;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : 18 2d 44 54 fb 21 09 40\n" } */
Local_R2 = My_R2;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 40 09 21 fb 54 44 2d 18\n" } */
Local_R1.F = Pi;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : 18 2d 44 54 fb 21 09 40\n" } */
Local_R2.F = Pi;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 40 09 21 fb 54 44 2d 18\n" } */
Local_R1.F = Local_R2.F;
put ("Local_R1 :");
dump (&Local_R1, sizeof (struct R1));
new_line ();
/* { dg-output "Local_R1 : 18 2d 44 54 fb 21 09 40\n" } */
Local_R2.F = Local_R1.F;
put ("Local_R2 :");
dump (&Local_R2, sizeof (struct R2));
new_line ();
/* { dg-output "Local_R2 : 40 09 21 fb 54 44 2d 18\n" } */
return 0;
}

View File

@ -0,0 +1,50 @@
/* { dg-do run } */
#include <stdio.h>
#include "init1.h"
#include "dump.h"
#ifdef __cplusplus
extern "C"
#endif
void abort (void);
int main (void)
{
struct R1 A1 = My_R1;
struct R1 B1 = My_R1;
struct R2 A2 = My_R2;
struct R2 B2 = My_R2;
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
/* { dg-output "A1 : 78 56 34 12\n" } */
put ("B1 :");
dump (&B1, sizeof (struct R1));
new_line ();
/* { dg-output "B1 : 78 56 34 12\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
/* { dg-output "A2 : 12 34 56 78\n" } */
put ("B2 :");
dump (&B2, sizeof (struct R2));
new_line ();
/* { dg-output "B2 : 12 34 56 78\n" } */
if (A1.I != B1.I) abort ();
if (A1.I != 0x12345678) abort ();
if (A2.I != B2.I) abort ();
if (A2.I != 0x12345678) abort ();
return 0;
}

View File

@ -0,0 +1,50 @@
/* { dg-do run } */
#include <stdio.h>
#include "init13.h"
#include "dump.h"
#ifdef __cplusplus
extern "C"
#endif
void abort (void);
int main (void)
{
struct R1 A1 = My_R1;
struct R1 B1 = My_R1;
struct R2 A2 = My_R2;
struct R2 B2 = My_R2;
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
/* { dg-output "A1 : db 0f 49 40 db 0f 49 c0\n" } */
put ("B1 :");
dump (&B1, sizeof (struct R1));
new_line ();
/* { dg-output "B1 : db 0f 49 40 db 0f 49 c0\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
/* { dg-output "A2 : 40 49 0f db c0 49 0f db\n" } */
put ("B2 :");
dump (&B2, sizeof (struct R2));
new_line ();
/* { dg-output "B2 : 40 49 0f db c0 49 0f db\n" } */
if (A1.F != B1.F) abort ();
if (A1.F != Pi - Pi * I) abort ();
if (A2.F != B2.F) abort ();
if (A2.F != Pi - Pi * I) abort ();
return 0;
}

View File

@ -0,0 +1,54 @@
/* { dg-do run } */
#include <stdio.h>
#include "init2.h"
#include "dump.h"
#ifdef __cplusplus
extern "C"
#endif
void abort (void);
int main (void)
{
struct R1 A1 = My_R1;
struct R1 B1 = My_R1;
struct R2 A2 = My_R2;
struct R2 B2 = My_R2;
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
/* { dg-output "A1 : e2 59 d1 48 b4 aa d9 bb\n" } */
put ("B1 :");
dump (&B1, sizeof (struct R1));
new_line ();
/* { dg-output "B1 : e2 59 d1 48 b4 aa d9 bb\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
/* { dg-output "A2 : 84 8d 15 9e 15 5b 35 df\n" } */
put ("B2 :");
dump (&B2, sizeof (struct R2));
new_line ();
/* { dg-output "B2 : 84 8d 15 9e 15 5b 35 df\n" } */
if (A1.S1 != B1.S1) abort ();
if (A1.S1 != 2) abort ();
if (A2.S1 != B2.S1) abort ();
if (A2.S1 != 2) abort ();
if (A1.I != B1.I || A1.A1 != B1.A1) abort ();
if (A2.I != B2.I || A2.A1 != B2.A1) abort ();
return 0;
}

View File

@ -0,0 +1,54 @@
/* { dg-do run } */
#include <stdio.h>
#include "init3.h"
#include "dump.h"
#ifdef __cplusplus
extern "C"
#endif
void abort (void);
int main (void)
{
struct R1 A1 = My_R1;
struct R1 B1 = My_R1;
struct R2 A2 = My_R2;
struct R2 B2 = My_R2;
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
/* { dg-output "A1 : c2 7b f3 2a 5e 12 9a 95\n" } */
put ("B1 :");
dump (&B1, sizeof (struct R1));
new_line ();
/* { dg-output "B1 : c2 7b f3 2a 5e 12 9a 95\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
/* { dg-output "A2 : 09 e2 af 37 bd 24 d2 b4\n" } */
put ("B2 :");
dump (&B2, sizeof (struct R2));
new_line ();
/* { dg-output "B2 : 09 e2 af 37 bd 24 d2 b4\n" } */
if (A1.S1 != B1.S1) abort ();
if (A1.S1 != 2) abort ();
if (A2.S1 != B2.S1) abort ();
if (A2.S1 != 2) abort ();
if (A1.I != B1.I || A1.N.C1 != B1.N.C1) abort ();
if (A2.I != B2.I || A2.N.C1 != B2.N.C1) abort ();
return 0;
}

View File

@ -0,0 +1,50 @@
/* { dg-do run } */
#include <stdio.h>
#include "init4.h"
#include "dump.h"
#ifdef __cplusplus
extern "C"
#endif
void abort (void);
int main (void)
{
struct R1 A1 = My_R1;
struct R1 B1 = My_R1;
struct R2 A2 = My_R2;
struct R2 B2 = My_R2;
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
/* { dg-output "A1 : db 0f 49 40\n" } */
put ("B1 :");
dump (&B1, sizeof (struct R1));
new_line ();
/* { dg-output "B1 : db 0f 49 40\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
/* { dg-output "A2 : 40 49 0f db\n" } */
put ("B2 :");
dump (&B2, sizeof (struct R2));
new_line ();
/* { dg-output "B2 : 40 49 0f db\n" } */
if (A1.F != B1.F) abort ();
if (A1.F != Pi) abort ();
if (A2.F != B2.F) abort ();
if (A2.F != Pi) abort ();
return 0;
}

View File

@ -0,0 +1,46 @@
/* { dg-do run } */
#include <stdio.h>
#include "init5.h"
#include "dump.h"
#ifdef __cplusplus
extern "C"
#endif
void abort (void);
int main (void)
{
struct R1 A1 = My_R1;
struct R1 B1 = My_R1;
struct R2 A2 = My_R2;
struct R2 B2 = My_R2;
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
/* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
put ("B1 :");
dump (&B1, sizeof (struct R1));
new_line ();
/* { dg-output "B1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
/* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
put ("B2 :");
dump (&B2, sizeof (struct R2));
new_line ();
/* { dg-output "B2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
if (A1.I != B1.I || A1.A[0] != B1.A[0]) abort();
if (A2.I != B2.I || A2.A[0] != B2.A[0]) abort ();
return 0;
}

View File

@ -0,0 +1,45 @@
/* { dg-do run } */
#include <stdio.h>
#include "init6.h"
#include "dump.h"
#ifdef __cplusplus
extern "C"
#endif
void abort (void);
int main (void)
{
struct R1 A1 = My_R1;
struct R1 B1 = My_R1;
struct R2 A2 = My_R2;
struct R2 B2 = My_R2;
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
/* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
put ("B1 :");
dump (&B1, sizeof (struct R1));
new_line ();
/* { dg-output "B1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
/* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
put ("B2 :");
dump (&B2, sizeof (struct R2));
new_line ();
/* { dg-output "B2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
if (A1.I != B1.I || A1.N.A[0] != B1.N.A[0]) abort();
if (A2.I != B2.I || A2.N.A[0] != B2.N.A[0]) abort ();
return 0;
}

View File

@ -0,0 +1,46 @@
/* { dg-do run } */
#include <stdio.h>
#include "init7.h"
#include "dump.h"
#ifdef __cplusplus
extern "C"
#endif
void abort (void);
int main (void)
{
struct R1 A1 = My_R1;
struct R1 B1 = My_R1;
struct R2 A2 = My_R2;
struct R2 B2 = My_R2;
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
/* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
put ("B1 :");
dump (&B1, sizeof (struct R1));
new_line ();
/* { dg-output "B1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
/* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
put ("B2 :");
dump (&B2, sizeof (struct R2));
new_line ();
/* { dg-output "B2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
if (A1.I != B1.I || A1.N.C1 != B1.N.C1) abort();
if (A2.I != B2.I || A2.N.C1 != B2.N.C1) abort ();
return 0;
}

View File

@ -0,0 +1,46 @@
/* { dg-do run } */
#include <stdio.h>
#include "init8.h"
#include "dump.h"
#ifdef __cplusplus
extern "C"
#endif
void abort (void);
int main (void)
{
struct R1 A1 = My_R1;
struct R1 B1 = My_R1;
struct R2 A2 = My_R2;
struct R2 B2 = My_R2;
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
/* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
put ("B1 :");
dump (&B1, sizeof (struct R1));
new_line ();
/* { dg-output "B1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
/* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
put ("B2 :");
dump (&B2, sizeof (struct R2));
new_line ();
/* { dg-output "B2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
if (A1.I != B1.I || A1.N.C1 != B1.N.C1) abort();
if (A2.I != B2.I || A2.N.C1 != B2.N.C1) abort ();
return 0;
}

View File

@ -0,0 +1,50 @@
/* { dg-do run } */
#include <stdio.h>
#include "init9.h"
#include "dump.h"
#ifdef __cplusplus
extern "C"
#endif
void abort (void);
int main (void)
{
struct R1 A1 = My_R1;
struct R1 B1 = My_R1;
struct R2 A2 = My_R2;
struct R2 B2 = My_R2;
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
/* { dg-output "A1 : 18 2d 44 54 fb 21 09 40\n" } */
put ("B1 :");
dump (&B1, sizeof (struct R1));
new_line ();
/* { dg-output "B1 : 18 2d 44 54 fb 21 09 40\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
/* { dg-output "A2 : 40 09 21 fb 54 44 2d 18\n" } */
put ("B2 :");
dump (&B2, sizeof (struct R2));
new_line ();
/* { dg-output "B2 : 40 09 21 fb 54 44 2d 18\n" } */
if (A1.F != B1.F) abort ();
if (A1.F != Pi) abort ();
if (A2.F != B2.F) abort ();
if (A2.F != Pi) abort ();
return 0;
}

View File

@ -0,0 +1,65 @@
/* { dg-do run } */
#include <stdio.h>
#include "init3.h"
#include "dump.h"
#ifdef __cplusplus
extern "C"
#endif
void abort (void);
int Get_Elem1 (struct R1 R)
{
struct R1 Tmp = R;
return Tmp.I;
}
void Set_Elem1 (struct R1 *R, int I)
{
struct R1 Tmp = *R;
Tmp.I = I;
*R = Tmp;
}
int Get_Elem2 (struct R2 R)
{
struct R2 Tmp = R;
return Tmp.I;
}
void Set_Elem2 (struct R2 *R, int I)
{
struct R2 Tmp = *R;
Tmp.I = I;
*R = Tmp;
}
int main (void)
{
struct R1 A1 = My_R1;
struct R2 A2 = My_R2;
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
/* { dg-output "A1 : c2 7b f3 2a 5e 12 9a 95\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
/* { dg-output "A2 : 09 e2 af 37 bd 24 d2 b4\n" } */
if (Get_Elem1 (A1) != 0x78ABCDEF) abort ();
Set_Elem1 (&A1, 0xCD0034);
if (Get_Elem1 (A1) != 0xCD0034) abort ();
if (Get_Elem2 (A2) != 0x78ABCDEF) abort ();
Set_Elem2 (&A2, 0xCD0034);
if (Get_Elem2 (A2) != 0xCD0034) abort ();
return 0;
}

View File

@ -0,0 +1,65 @@
/* { dg-do run } */
#include <stdio.h>
#include "init5.h"
#include "dump.h"
#ifdef __cplusplus
extern "C"
#endif
void abort (void);
int Get_Elem1 (struct R1 R)
{
struct R1 Tmp = R;
return Tmp.A[0];
}
void Set_Elem1 (struct R1 *R, int I)
{
struct R1 Tmp = *R;
Tmp.A[0] = I;
*R = Tmp;
}
int Get_Elem2 (struct R2 R)
{
struct R2 Tmp = R;
return Tmp.A[0];
}
void Set_Elem2 (struct R2 *R, int I)
{
struct R2 Tmp = *R;
Tmp.A[0] = I;
*R = Tmp;
}
int main (void)
{
struct R1 A1 = My_R1;
struct R2 A2 = My_R2;
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
/* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
/* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
if (Get_Elem1 (A1) != 0xAB0012) abort ();
Set_Elem1 (&A1, 0xCD0034);
if (Get_Elem1 (A1) != 0xCD0034) abort ();
if (Get_Elem2 (A2) != 0xAB0012) abort ();
Set_Elem2 (&A2, 0xCD0034);
if (Get_Elem2 (A2) != 0xCD0034) abort ();
return 0;
}

View File

@ -0,0 +1,65 @@
/* { dg-do run } */
#include <stdio.h>
#include "init6.h"
#include "dump.h"
#ifdef __cplusplus
extern "C"
#endif
void abort (void);
int Get_Elem1 (struct R1 R)
{
struct R1 Tmp = R;
return Tmp.N.A[0];
}
void Set_Elem1 (struct R1 *R, int I)
{
struct R1 Tmp = *R;
Tmp.N.A[0] = I;
*R = Tmp;
}
int Get_Elem2 (struct R2 R)
{
struct R2 Tmp = R;
return Tmp.N.A[0];
}
void Set_Elem2 (struct R2 *R, int I)
{
struct R2 Tmp = *R;
Tmp.N.A[0] = I;
*R = Tmp;
}
int main (void)
{
struct R1 A1 = My_R1;
struct R2 A2 = My_R2;
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
/* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
/* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
if (Get_Elem1 (A1) != 0xAB0012) abort ();
Set_Elem1 (&A1, 0xCD0034);
if (Get_Elem1 (A1) != 0xCD0034) abort ();
if (Get_Elem2 (A2) != 0xAB0012) abort ();
Set_Elem2 (&A2, 0xCD0034);
if (Get_Elem2 (A2) != 0xCD0034) abort ();
return 0;
}

View File

@ -0,0 +1,65 @@
/* { dg-do run } */
#include <stdio.h>
#include "init7.h"
#include "dump.h"
#ifdef __cplusplus
extern "C"
#endif
void abort (void);
int Get_Elem1 (struct R1 R)
{
struct R1 Tmp = R;
return Tmp.N.C1;
}
void Set_Elem1 (struct R1 *R, int I)
{
struct R1 Tmp = *R;
Tmp.N.C1 = I;
*R = Tmp;
}
int Get_Elem2 (struct R2 R)
{
struct R2 Tmp = R;
return Tmp.N.C1;
}
void Set_Elem2 (struct R2 *R, int I)
{
struct R2 Tmp = *R;
Tmp.N.C1 = I;
*R = Tmp;
}
int main (void)
{
struct R1 A1 = My_R1;
struct R2 A2 = My_R2;
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
/* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
/* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
if (Get_Elem1 (A1) != 0xAB0012) abort ();
Set_Elem1 (&A1, 0xCD0034);
if (Get_Elem1 (A1) != 0xCD0034) abort ();
if (Get_Elem2 (A2) != 0xAB0012) abort ();
Set_Elem2 (&A2, 0xCD0034);
if (Get_Elem2 (A2) != 0xCD0034) abort ();
return 0;
}

View File

@ -0,0 +1,65 @@
/* { dg-do run } */
#include <stdio.h>
#include "init8.h"
#include "dump.h"
#ifdef __cplusplus
extern "C"
#endif
void abort (void);
int Get_Elem1 (struct R1 R)
{
struct R1 Tmp = R;
return Tmp.N.C1;
}
void Set_Elem1 (struct R1 *R, int I)
{
struct R1 Tmp = *R;
Tmp.N.C1 = I;
*R = Tmp;
}
int Get_Elem2 (struct R2 R)
{
struct R2 Tmp = R;
return Tmp.N.C1;
}
void Set_Elem2 (struct R2 *R, int I)
{
struct R2 Tmp = *R;
Tmp.N.C1 = I;
*R = Tmp;
}
int main (void)
{
struct R1 A1 = My_R1;
struct R2 A2 = My_R2;
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
/* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
/* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
if (Get_Elem1 (A1) != 0xAB0012) abort ();
Set_Elem1 (&A1, 0xCD0034);
if (Get_Elem1 (A1) != 0xCD0034) abort ();
if (Get_Elem2 (A2) != 0xAB0012) abort ();
Set_Elem2 (&A2, 0xCD0034);
if (Get_Elem2 (A2) != 0xCD0034) abort ();
return 0;
}

View File

@ -0,0 +1,79 @@
/* { dg-do run } */
#include <stdio.h>
#include "init3.h"
#include "dump.h"
int main (void)
{
struct R1 A1 = My_R1;
struct R2 A2 = My_R2;
struct Nested1 N1;
struct Nested2 N2;
unsigned C1;
unsigned C2;
unsigned C3;
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
/* { dg-output "A1 : c2 7b f3 2a 5e 12 9a 95\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
/* { dg-output "A2 : 09 e2 af 37 bd 24 d2 b4\n" } */
N1 = A1.N;
C1 = N1.C1;
C2 = N1.C2;
C3 = N1.C3;
printf ("C1 : %d\n", C1);
/* { dg-output "C1 : 18\n" } */
printf ("C2 : %d\n", C2);
/* { dg-output "C2 : 52\n" } */
printf ("C3 : %d\n", C3);
/* { dg-output "C3 : 86\n" } */
N1.C1 = C1;
N1.C2 = C2;
N1.C3 = C3;
A1.N = N1;
N2 = A2.N;
C1 = N2.C1;
C2 = N2.C2;
C3 = N2.C3;
printf ("C1 : %d\n", C1);
/* { dg-output "C1 : 18\n" } */
printf ("C2 : %d\n", C2);
/* { dg-output "C2 : 52\n" } */
printf ("C3 : %d\n", C3);
/* { dg-output "C3 : 86\n" } */
N2.C1 = C1;
N2.C2 = C2;
N2.C3 = C3;
A2.N = N2;
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
/* { dg-output "A1 : c2 7b f3 2a 5e 12 9a 95\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
/* { dg-output "A2 : 09 e2 af 37 bd 24 d2 b4\n" } */
return 0;
}

View File

@ -0,0 +1,91 @@
/* { dg-do run } */
#include <stdio.h>
#include "init5.h"
#include "dump.h"
#pragma GCC diagnostic ignored "-Wscalar-storage-order"
int main (void)
{
struct R1 A1 = My_R1;
struct R2 A2 = My_R2;
struct __attribute__((scalar_storage_order("little-endian"))) Nested1
{
int A[3];
};
struct __attribute__((scalar_storage_order("big-endian"))) Nested2
{
int A[3];
};
struct Nested1 N1;
struct Nested2 N2;
int C1;
int C2;
int C3;
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
/* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
/* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
__builtin_memcpy (N1.A, A1.A, sizeof (int) * 3);
C1 = N1.A[0];
C2 = N1.A[1];
C3 = N1.A[2];
printf ("C1 : %d\n", C1);
/* { dg-output "C1 : 11206674\n" } */
printf ("C2 : %d\n", C2);
/* { dg-output "C2 : 13434932\n" } */
printf ("C3 : %d\n", C3);
/* { dg-output "C3 : 15663190\n" } */
N1.A[0] = C1;
N1.A[1] = C2;
N1.A[2] = C3;
__builtin_memcpy (A1.A, N1.A, sizeof (int) * 3);
__builtin_memcpy (N2.A, A2.A, sizeof (int) * 3);
C1 = N2.A[0];
C2 = N2.A[1];
C3 = N2.A[2];
printf ("C1 : %d\n", C1);
/* { dg-output "C1 : 11206674\n" } */
printf ("C2 : %d\n", C2);
/* { dg-output "C2 : 13434932\n" } */
printf ("C3 : %d\n", C3);
/* { dg-output "C3 : 15663190\n" } */
N2.A[0] = C1;
N2.A[1] = C2;
N2.A[2] = C3;
__builtin_memcpy (A2.A, N2.A, sizeof (int) * 3);
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
/* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
/* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
return 0;
}

View File

@ -0,0 +1,81 @@
/* { dg-do run } */
#include <stdio.h>
#include "init6.h"
#include "dump.h"
#pragma GCC diagnostic ignored "-Wscalar-storage-order"
int main (void)
{
struct R1 A1 = My_R1;
struct R2 A2 = My_R2;
struct Nested1 N1;
struct Nested2 N2;
int C1;
int C2;
int C3;
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
/* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
/* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
__builtin_memcpy (N1.A, A1.N.A, sizeof (int) * 3);
C1 = N1.A[0];
C2 = N1.A[1];
C3 = N1.A[2];
printf ("C1 : %d\n", C1);
/* { dg-output "C1 : 11206674\n" } */
printf ("C2 : %d\n", C2);
/* { dg-output "C2 : 13434932\n" } */
printf ("C3 : %d\n", C3);
/* { dg-output "C3 : 15663190\n" } */
N1.A[0] = C1;
N1.A[1] = C2;
N1.A[2] = C3;
__builtin_memcpy (A1.N.A, N1.A, sizeof (int) * 3);
__builtin_memcpy (N2.A, A2.N.A, sizeof (int) * 3);
C1 = N2.A[0];
C2 = N2.A[1];
C3 = N2.A[2];
printf ("C1 : %d\n", C1);
/* { dg-output "C1 : 11206674\n" } */
printf ("C2 : %d\n", C2);
/* { dg-output "C2 : 13434932\n" } */
printf ("C3 : %d\n", C3);
/* { dg-output "C3 : 15663190\n" } */
N2.A[0] = C1;
N2.A[1] = C2;
N2.A[2] = C3;
__builtin_memcpy (A2.N.A, N2.A, sizeof (int) * 3);
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
/* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
/* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
return 0;
}

View File

@ -0,0 +1,79 @@
/* { dg-do run } */
#include <stdio.h>
#include "init7.h"
#include "dump.h"
int main (void)
{
struct R1 A1 = My_R1;
struct R2 A2 = My_R2;
struct Nested1 N1;
struct Nested2 N2;
int C1;
int C2;
int C3;
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
/* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
/* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
N1 = A1.N;
C1 = N1.C1;
C2 = N1.C2;
C3 = N1.C3;
printf ("C1 : %d\n", C1);
/* { dg-output "C1 : 11206674\n" } */
printf ("C2 : %d\n", C2);
/* { dg-output "C2 : 13434932\n" } */
printf ("C3 : %d\n", C3);
/* { dg-output "C3 : 15663190\n" } */
N1.C1 = C1;
N1.C2 = C2;
N1.C3 = C3;
A1.N = N1;
N2 = A2.N;
C1 = N2.C1;
C2 = N2.C2;
C3 = N2.C3;
printf ("C1 : %d\n", C1);
/* { dg-output "C1 : 11206674\n" } */
printf ("C2 : %d\n", C2);
/* { dg-output "C2 : 13434932\n" } */
printf ("C3 : %d\n", C3);
/* { dg-output "C3 : 15663190\n" } */
N2.C1 = C1;
N2.C2 = C2;
N2.C3 = C3;
A2.N = N2;
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
/* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
/* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
return 0;
}

View File

@ -0,0 +1,79 @@
/* { dg-do run } */
#include <stdio.h>
#include "init8.h"
#include "dump.h"
int main (void)
{
struct R1 A1 = My_R1;
struct R2 A2 = My_R2;
struct Nested1 N1;
struct Nested2 N2;
int C1;
int C2;
int C3;
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
/* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
/* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
N1 = A1.N;
C1 = N1.C1;
C2 = N1.C2;
C3 = N1.C3;
printf ("C1 : %d\n", C1);
/* { dg-output "C1 : 11206674\n" } */
printf ("C2 : %d\n", C2);
/* { dg-output "C2 : 13434932\n" } */
printf ("C3 : %d\n", C3);
/* { dg-output "C3 : 15663190\n" } */
N1.C1 = C1;
N1.C2 = C2;
N1.C3 = C3;
A1.N = N1;
N2 = A2.N;
C1 = N2.C1;
C2 = N2.C2;
C3 = N2.C3;
printf ("C1 : %d\n", C1);
/* { dg-output "C1 : 11206674\n" } */
printf ("C2 : %d\n", C2);
/* { dg-output "C2 : 13434932\n" } */
printf ("C3 : %d\n", C3);
/* { dg-output "C3 : 15663190\n" } */
N2.C1 = C1;
N2.C2 = C2;
N2.C3 = C3;
A2.N = N2;
put ("A1 :");
dump (&A1, sizeof (struct R1));
new_line ();
/* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
put ("A2 :");
dump (&A2, sizeof (struct R2));
new_line ();
/* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
return 0;
}

Some files were not shown because too many files have changed in this diff Show More