Merge of the scalar-storage-order branch.
From-SVN: r229965
This commit is contained in:
parent
eb11eb157c
commit
ee45a32dae
273
gcc/ChangeLog
273
gcc/ChangeLog
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
10
gcc/calls.c
10
gcc/calls.c
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
266
gcc/expmed.c
266
gcc/expmed.c
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
326
gcc/expr.c
326
gcc/expr.c
|
@ -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))
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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. */
|
||||
|
|
132
gcc/fold-const.c
132
gcc/fold-const.c
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" } */
|
|
@ -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 */
|
||||
}
|
|
@ -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 */
|
||||
}
|
|
@ -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)" } */
|
||||
}
|
|
@ -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)" } */
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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');
|
||||
}
|
|
@ -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 };
|
|
@ -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 };
|
|
@ -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 };
|
|
@ -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 } };
|
|
@ -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 };
|
|
@ -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 } };
|
|
@ -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 } } };
|
|
@ -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 } };
|
|
@ -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 } };
|
|
@ -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 };
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
Loading…
Reference in New Issue