8sa1-gcc/gcc/double-int.c
Ian Lance Taylor bbbbb16a88 Fix enum conversions which are invalid in C++:
gcc/:
	Fix enum conversions which are invalid in C++:
	* auto-inc-dec.c (attempt_change): Change 0 to SET in function
	call.
	* calls.c (store_one_arg): Change 0 to EXPAND_NORMAL in function
	call.
	* cse.c (hash_rtx_cb): Change 0 to VOIDmode in function call.
	* dbgcnt.c (dbg_cnt_set_limit_by_name): Add cast to enum type.
	* dbxout.c (dbxout_symbol): Change 0 to VOIDmode in function
	call.
	(dbxout_parms): Likewise.
	* df-core.c (df_set_flags): Change changeable_flags parameter to
	int.
	(df_clear_flags): Likewise.
	* df-problems.c (df_rd_bb_local_compute_process_def): Change
	top_flag parameter to int.
	(df_chain_create_bb_process_use): Likewise.
	(df_chain_add_problem): Change chain_flags parameter to unsigned
	int.  Remove cast.
	* df-scan.c (df_ref_create): Change ref_flags parameter to int.
	(df_ref_create_structure, df_def_record_1): Likewise.
	(df_defs_record, df_uses_record, df_get_call_refs): Likewise.
	(df_notes_rescan): Change 0 to VOIDmode in function call.
	(df_get_call_refs, df_insn_refs_collect): Likewise.
	(df_bb_regs_collect): Likewise.
	(df_entry_block_defs_collect): Likewise.
	(df_exit_block_uses_collect): Likewise.
	* df.h: Update declarations.
	* double-int.c (double_int_divmod): Add cast to enum type.
	* dse.c (replace_inc_dec): Reverse parameters to gen_int_mode.
	* dwarf2out.c (new_reg_loc_descr): Add casts to enum type.
	(based_loc_descr): Likewise.
	(loc_descriptor_from_tree_1): Change first_op and second_op to
	enum dwarf_location_atom.  Add cast to enum type.
	* expmed.c (init_expmed): Change 0 to SET in function call.
	* expr.c (init_expr_target): Change 0 to VOIDmode in function
	call.
	(expand_expr_real_1): Change 0 to EXPAND_NORMAL in function call.
	(do_store_flag): Likewise.
	* fixed-value.h (struct fixed_value): Change mode to enum
	machine_mode.
	* function.c (assign_parms): Change 0 to VOIDmode in function
	call.
	* genautomata.c (insert_automaton_decl): Change 1 to INSERT in
	function call.
	(insert_insn_decl, insert_decl, insert_state): Likewise.
	(automata_list_finish): Likewise.
	* genrecog.c (process_define_predicate): Add cast to enum type.
	* gensupport.c (init_predicate_table): Add cast to enum type.
	* gimple.c (gimple_build_return): Change 0 to ERROR_MARK in
	function call.
	(gimple_build_call_1, gimple_build_label): Likewise.
	(gimple_build_goto, gimple_build_asm_1): Likewise.
	(gimple_build_switch_1, gimple_build_cdt): Likewise.
	* gimple.h (GIMPLE_CHECK): Change 0 to ERROR_MARK in function
	call.
	(enum fallback): Rename from enum fallback_t.
	(fallback_t): Typedef as int.
	* gimple-low.c (lower_builtin_setjmp): Change TSI_SAME_STMT to
	GSI_SAME_STMT in function call.
	* ira.c (setup_class_subset_and_memory_move_costs): Add casts to
	enum type.
	(setup_reg_class_relations): Likewise.
	(setup_reg_class_nregs): Change cl to int.  Add casts to enum
	type.
	(setup_prohibited_class_mode_regs): Add cast to enum type.
	(setup_prohibited_mode_move_regs): Likewise.
	* ira-costs.c (record_reg_classes): Change rclass to enum
	reg_class.
	(record_address_regs): Change i to enum reg_class.
	* lists.c (alloc_EXPR_LIST): Add cast to enum type.
	* machmode.h (GET_MODE_CLASS): Cast value to enum mode_class.
	(GET_MODE_WIDER_MODE): Cast value to enum machine_mode.
	(GET_MODE_2XWIDER_MODE): Likewise.
	(GET_CLASS_NARROWEST_MODE): Likewise.
	* omp-low.c (expand_omp_for): Add cast to enum type.
	* optabs.c (debug_optab_libfuncs): Add casts to enum type.
	* opts.c (enable_warning_as_error): Change kind to diagostic_t.
	* postreload.c (reload_cse_simplify_operands): Change rclass local
	to enum reg_class.
	* predict.c (combine_predictions_for_insn): Change best_predictor
	and predictor to enum br_predictor.
	(combine_predictions_for_bb): Likewise.
	(build_predict_expr): Change assignment to PREDICT_EXPR_OUTCOME to
	use SET_PREDICT_EXPR_OUTCOME.
	* real.c (real_arithmetic): Change icode to code in function
	call.
	* reginfo.c (init_move_cost): Add casts to enum type.
	(init_reg_sets_1, init_fake_stack_mems): Likewise.
	* regmove.c (regclass_compatible_p): Change class0 and class1 to
	enum reg_class.
	* reload.c (find_valid_class): Add casts to enum type.
	(push_reload): Change 0 to NO_REGS in function call.
	(find_reloads): Change this_alternative to array of enum
	reg_class.  Remove some now-unnecessary casts.
	(make_memloc): Change 0 to VOIDmode in function call.
	* reload1.c (reload): Change 0 to VOIDmode in function call.
	(eliminate_regs_1, elimination_effects): Likewise.
	(eliminate_regs_in_insn): Likewise.
	(emit_input_reload_insns): Add cast to enum type.
	(delete_output_reload): Change 0 to VOIDmode in function call.
	* reorg.c (insn_sets_resource_p): Convert include_delayed_effects
	to enum type in function call.
	* tree.h (PREDICT_EXPR_OUTCOME): Add cast to enum type.
	(SET_PREDICT_EXPR_OUTCOME): Define.
	* tree-dump.c (get_dump_file_info): Change phase parameter to
	int.
	(get_dump_file_name, dump_begin, dump_enabled_p): Likewise.
	(dump_initialized_p, dump_flag_name, dump_end): Likewise.
	(dump_function): Likewise.
	* tree-dump.h: Update declarations.
	* tree-pass.h: Update declarations.
	* varasm.c (assemble_integer): Change mclass to enum mode_class.
	* config/arm/arm.c (thumb_legitimize_reload_address): Add cast to
	enum type.
	(arm_rtx_costs_1): Correct parenthesization.
	(arm_rtx_costs): Add casts to enum type.
	(adjacent_mem_locations): Reverse arguments to const_ok_for_op.
	(vfp_emit_fstmd): Use add_rg_note.
	(emit_multi_reg_push, emit_sfm): Likewise.
	(thumb_set_frame_pointer): Likewise.
	(arm_expand_prologue): Likewise.
	(arm_regno_class): Change return type to enum reg_class.
	(thumb1_expand_prologue): Use add_reg_note.
	* config/arm/arm-protos.h (arm_regno_class): Update declaration.
	* config/arm/arm.h (INITIALIZE_TRAMPOLINE): Change 0 to LCT_NORMAL
	in function call.
	* config/arm/gentune.sh: Add cast to enum type.
	* config/arm/arm-tune.md: Rebuild.
	* config/i386/i386.c (ix86_expand_prologue): Use add_reg_note.
	(ix86_split_fp_branch, predict_jump): Likewise.
	(ix86_expand_multi_arg_builtin): Change sub_code from enum
	insn_code to enum rtx_code.
	(ix86_builtin_vectorized_function): Add cast to enum type.
	* config/i386/i386.md (truncdfsf2): Change slot to enum
	ix86_stack_slot.
	(truncxf<mode>2, isinf<mode>2): Likewise.
	* config/i386/i386-c.c (ix86_pragma_target_parse): Add cast to
	enum type.
	* config/ia64/ia64.c (ia64_split_tmode_move): Use add_reg_note.
	(spill_restore_mem, do_spill, ia64_expand_prologue): Likewise.
	(insert_bundle_state): Change 1 to INSERT in function call.
	(ia64_add_bundle_selector_before): Likewise.
	* config/ia64/ia64.md (cpu attr): Add cast to enum type.
	(save_stack_nonlocal): Change 0 to LCT_NORMAL in function call.
	(restore_stack_nonlocal): Likewise.
	* config/mips/mips.h (MIPS_ICACHE_SYNC): Change 0 to LCT_NORMAL in
	function call.
	* config/mips/mips.c (mips_binary_cost): Change 0 to SET in
	function call.
	(mips_rtx_costs): Likewise.
	(mips_override_options): Add casts to enum type.
	* config/mips/sdemtk.h (MIPS_ICACHE_SYNC): Change 0 to LCT_NORMAL
	in function call.
	* config/pa/pa.c (legitimize_pic_address): Use add_reg_note.
	(store_reg, set_reg_plus_d): Likewise.
	(hppa_expand_prologue, hppa_profile_hook): Likewise.
	* config/rs6000/rs6000.c (rs6000_init_hard_regno_mode_ok): Add
	cast to enum type.
	(altivec_expand_vec_set_builtin): Change 0 to EXPAND_NORMAL in
	function call.
	(emit_unlikely_jump): Use add_reg_note.
	(rs6000_emit_allocate_stack): Likewise.
	(rs6000_frame_related, rs6000_emit_prologue): Likewise.
	(output_toc): Change 1 to INSERT in function call.
	(output_profile_hook): Change 0 to LCT_NORMAL in function call.
	(rs6000_initialize_trampoline): Likewise.
	(rs6000_init_dwarf_reg_sizes_extra): Change 0 to EXPAND_NORMAL in
	function call.
	* config/s390/s390.c (s390_rtx_costs): Add cast to enum type.
	(s390_expand_movmem): Change 0 to OPTAB_DIRECT in function call.
	(s390_expand_setmem, s390_expand_cmpmem): Likewise.
	(save_gprs): Use add_reg_note.
	(s390_emit_prologue): Likewise.
	(s390_expand_builtin): Change 0 to EXPAND_NORMAL in function
	call.
	* config/sparc/sparc.c (sparc_expand_prologue): Use add_reg_note.
	(sparc_fold_builtin): Add cast to enum type.
	* config/spu/spu.c (spu_emit_branch_or_set): Change ior_code to
	enum insn_code.
	(spu_expand_prologue): Use add_reg_note.
	(expand_builtin_args): Change 0 to EXPAND_NORMAL in function
	call.

	* c-parser.c (c_parser_attributes): Change VEC back to tree list.
	(c_parser_postfix_expression_after_primary): Get VEC for list of
	arguments.  Get original types of arguments.  Call
	build_function_call_vec.
	(cached_expr_list_1, cached_expr_list_2): New static variables.
	(c_parser_expr_list): Change return type to VEC *.  Add
	p_orig_types parameter.  Change all callers.
	(c_parser_release_expr): New static function.
	(c_parser_vec_to_tree_list): New static function.
	* c-typeck.c (build_function_call): Rewrite to build a VEC and
	call build_function_call_vec.
	(build_function_call_vec): New function, based on old
	build_function_call.
	(convert_arguments): Remove nargs and argarray parameters.  Change
	values to a VEC.  Add origtypes parameter.
	(build_modify_expr): Add rhs_origtype parameter.  Change all
	callers.
	(convert_for_assignment): Add origtype parameter.  Change all
	callers.  If warn_cxx_compat, check for conversion to an enum
	type when calling a function.
	(store_init_value): Add origtype parameter.  Change all callers.
	(digest_init): Likewise.
	(struct init_node): Add origtype field.
	(add_pending_init): Add origtype parameter.  Change all callers.
	(output_init_element): Likewise.
	(output_pending_init_elements): Pass origtype from init_node to
	output_init_element.
	(process_init_elemnt): Pass origtype from c_expr to
	output_init_element.
	(c_finish_return): Add origtype parameter.  Change all callers.
	* c-common.c (sync_resolve_size): Change params to VEC *.  Change
	caller.
	(sync_resolve_params): Likewise.
	(sync_resolve_return): Change params to first_param.  Change
	caller.
	(resolve_overloaded_builtins): Change params to VEC *.  Change
	callers.   Save first parameter around call to
	build_function_call_vec.
	* c-decl.c (finish_decl): Add origtype parameter.  Change all
	callers.  Call build_function_call_vec rather than
	build_function_call for cleanup.
	* c-tree.h: Update declarations.
	* c-common.h: Update declarations.
	* stub-objc.c (objc_rewrite_function_call): Change parameter from
	params to first_param.
	* target.h (struct gcc_target): Change resolve_overloaded_builtin
	params parameter from tree to void *.
	* config/rs6000/rs6000-c.c (altivec_resolve_overloaded_builtin):
	Change arglist parameter to have type void *, and to be a pointer
	to a VEC.
	* config/rs6000/rs6000-protos.h
	(altivec_resolve_overloaded_builtin): Update declaration.
	* config/spu/spu-c.c (spu_resolved_overloaded_builtin): Change
	fnargs parameter to have type void *, and to be a pointer to a
	VEC.  Call build_function_call_vec instead of
	build_function_call.
	* config/spu/spu-protos.h (spu_expand_builtin): Update
	declaration.

gcc/cp/:
	* typeck.c (build_function_call_vec): New function.
	(cp_build_function_call): Only pass first parameter to
	objc_rewrite_function_call.
	(build_modify_expr): Add rhs_origtype parameter.  Change all
	callers.
	* decl.c (finish_decl): Add origtype parameter.  Change all
	callers.
	* semantics.c (finish_call_expr): Pass VEC to
	resolve_overloaded_builtin.

gcc/objc:
	* objc-act.c (objc_rewrite_function_call): Change parameter from
	params to first_param.  Change all callers.

gcc/testsuite:
	* gcc.dg/Wcxx-compat-3.c: New testcase.

From-SVN: r146451
2009-04-20 19:35:00 +00:00

494 lines
11 KiB
C

/* Operations with long integers.
Copyright (C) 2006, 2007, 2009 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3, or (at your option) any
later version.
GCC is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
/* Returns mask for PREC bits. */
double_int
double_int_mask (unsigned prec)
{
unsigned HOST_WIDE_INT m;
double_int mask;
if (prec > HOST_BITS_PER_WIDE_INT)
{
prec -= HOST_BITS_PER_WIDE_INT;
m = ((unsigned HOST_WIDE_INT) 2 << (prec - 1)) - 1;
mask.high = (HOST_WIDE_INT) m;
mask.low = ALL_ONES;
}
else
{
mask.high = 0;
mask.low = ((unsigned HOST_WIDE_INT) 2 << (prec - 1)) - 1;
}
return mask;
}
/* Clears the bits of CST over the precision PREC. If UNS is false, the bits
outside of the precision are set to the sign bit (i.e., the PREC-th one),
otherwise they are set to zero.
This corresponds to returning the value represented by PREC lowermost bits
of CST, with the given signedness. */
double_int
double_int_ext (double_int cst, unsigned prec, bool uns)
{
if (uns)
return double_int_zext (cst, prec);
else
return double_int_sext (cst, prec);
}
/* The same as double_int_ext with UNS = true. */
double_int
double_int_zext (double_int cst, unsigned prec)
{
double_int mask = double_int_mask (prec);
double_int r;
r.low = cst.low & mask.low;
r.high = cst.high & mask.high;
return r;
}
/* The same as double_int_ext with UNS = false. */
double_int
double_int_sext (double_int cst, unsigned prec)
{
double_int mask = double_int_mask (prec);
double_int r;
unsigned HOST_WIDE_INT snum;
if (prec <= HOST_BITS_PER_WIDE_INT)
snum = cst.low;
else
{
prec -= HOST_BITS_PER_WIDE_INT;
snum = (unsigned HOST_WIDE_INT) cst.high;
}
if (((snum >> (prec - 1)) & 1) == 1)
{
r.low = cst.low | ~mask.low;
r.high = cst.high | ~mask.high;
}
else
{
r.low = cst.low & mask.low;
r.high = cst.high & mask.high;
}
return r;
}
/* Constructs long integer from tree CST. The extra bits over the precision of
the number are filled with sign bit if CST is signed, and with zeros if it
is unsigned. */
double_int
tree_to_double_int (const_tree cst)
{
/* We do not need to call double_int_restrict here to ensure the semantics as
described, as this is the default one for trees. */
return TREE_INT_CST (cst);
}
/* Returns true if CST fits in unsigned HOST_WIDE_INT. */
bool
double_int_fits_in_uhwi_p (double_int cst)
{
return cst.high == 0;
}
/* Returns true if CST fits in signed HOST_WIDE_INT. */
bool
double_int_fits_in_shwi_p (double_int cst)
{
if (cst.high == 0)
return (HOST_WIDE_INT) cst.low >= 0;
else if (cst.high == -1)
return (HOST_WIDE_INT) cst.low < 0;
else
return false;
}
/* Returns true if CST fits in HOST_WIDE_INT if UNS is false, or in
unsigned HOST_WIDE_INT if UNS is true. */
bool
double_int_fits_in_hwi_p (double_int cst, bool uns)
{
if (uns)
return double_int_fits_in_uhwi_p (cst);
else
return double_int_fits_in_shwi_p (cst);
}
/* Returns value of CST as a signed number. CST must satisfy
double_int_fits_in_shwi_p. */
HOST_WIDE_INT
double_int_to_shwi (double_int cst)
{
return (HOST_WIDE_INT) cst.low;
}
/* Returns value of CST as an unsigned number. CST must satisfy
double_int_fits_in_uhwi_p. */
unsigned HOST_WIDE_INT
double_int_to_uhwi (double_int cst)
{
return cst.low;
}
/* Returns A * B. */
double_int
double_int_mul (double_int a, double_int b)
{
double_int ret;
mul_double (a.low, a.high, b.low, b.high, &ret.low, &ret.high);
return ret;
}
/* Returns A + B. */
double_int
double_int_add (double_int a, double_int b)
{
double_int ret;
add_double (a.low, a.high, b.low, b.high, &ret.low, &ret.high);
return ret;
}
/* Returns -A. */
double_int
double_int_neg (double_int a)
{
double_int ret;
neg_double (a.low, a.high, &ret.low, &ret.high);
return ret;
}
/* Returns A / B (computed as unsigned depending on UNS, and rounded as
specified by CODE). CODE is enum tree_code in fact, but double_int.h
must be included before tree.h. The remainder after the division is
stored to MOD. */
double_int
double_int_divmod (double_int a, double_int b, bool uns, unsigned code,
double_int *mod)
{
double_int ret;
div_and_round_double ((enum tree_code) code, uns, a.low, a.high,
b.low, b.high, &ret.low, &ret.high,
&mod->low, &mod->high);
return ret;
}
/* The same as double_int_divmod with UNS = false. */
double_int
double_int_sdivmod (double_int a, double_int b, unsigned code, double_int *mod)
{
return double_int_divmod (a, b, false, code, mod);
}
/* The same as double_int_divmod with UNS = true. */
double_int
double_int_udivmod (double_int a, double_int b, unsigned code, double_int *mod)
{
return double_int_divmod (a, b, true, code, mod);
}
/* Returns A / B (computed as unsigned depending on UNS, and rounded as
specified by CODE). CODE is enum tree_code in fact, but double_int.h
must be included before tree.h. */
double_int
double_int_div (double_int a, double_int b, bool uns, unsigned code)
{
double_int mod;
return double_int_divmod (a, b, uns, code, &mod);
}
/* The same as double_int_div with UNS = false. */
double_int
double_int_sdiv (double_int a, double_int b, unsigned code)
{
return double_int_div (a, b, false, code);
}
/* The same as double_int_div with UNS = true. */
double_int
double_int_udiv (double_int a, double_int b, unsigned code)
{
return double_int_div (a, b, true, code);
}
/* Returns A % B (computed as unsigned depending on UNS, and rounded as
specified by CODE). CODE is enum tree_code in fact, but double_int.h
must be included before tree.h. */
double_int
double_int_mod (double_int a, double_int b, bool uns, unsigned code)
{
double_int mod;
double_int_divmod (a, b, uns, code, &mod);
return mod;
}
/* The same as double_int_mod with UNS = false. */
double_int
double_int_smod (double_int a, double_int b, unsigned code)
{
return double_int_mod (a, b, false, code);
}
/* The same as double_int_mod with UNS = true. */
double_int
double_int_umod (double_int a, double_int b, unsigned code)
{
return double_int_mod (a, b, true, code);
}
/* Constructs tree in type TYPE from with value given by CST. Signedness of CST
is assumed to be the same as the signedness of TYPE. */
tree
double_int_to_tree (tree type, double_int cst)
{
cst = double_int_ext (cst, TYPE_PRECISION (type), TYPE_UNSIGNED (type));
return build_int_cst_wide (type, cst.low, cst.high);
}
/* Returns true if CST fits into range of TYPE. Signedness of CST is assumed
to be the same as the signedness of TYPE. */
bool
double_int_fits_to_tree_p (const_tree type, double_int cst)
{
double_int ext = double_int_ext (cst,
TYPE_PRECISION (type),
TYPE_UNSIGNED (type));
return double_int_equal_p (cst, ext);
}
/* Returns true if CST is negative. Of course, CST is considered to
be signed. */
bool
double_int_negative_p (double_int cst)
{
return cst.high < 0;
}
/* Returns -1 if A < B, 0 if A == B and 1 if A > B. Signedness of the
comparison is given by UNS. */
int
double_int_cmp (double_int a, double_int b, bool uns)
{
if (uns)
return double_int_ucmp (a, b);
else
return double_int_scmp (a, b);
}
/* Compares two unsigned values A and B. Returns -1 if A < B, 0 if A == B,
and 1 if A > B. */
int
double_int_ucmp (double_int a, double_int b)
{
if ((unsigned HOST_WIDE_INT) a.high < (unsigned HOST_WIDE_INT) b.high)
return -1;
if ((unsigned HOST_WIDE_INT) a.high > (unsigned HOST_WIDE_INT) b.high)
return 1;
if (a.low < b.low)
return -1;
if (a.low > b.low)
return 1;
return 0;
}
/* Compares two signed values A and B. Returns -1 if A < B, 0 if A == B,
and 1 if A > B. */
int
double_int_scmp (double_int a, double_int b)
{
if (a.high < b.high)
return -1;
if (a.high > b.high)
return 1;
if (a.low < b.low)
return -1;
if (a.low > b.low)
return 1;
return 0;
}
/* Splits last digit of *CST (taken as unsigned) in BASE and returns it. */
static unsigned
double_int_split_digit (double_int *cst, unsigned base)
{
unsigned HOST_WIDE_INT resl, reml;
HOST_WIDE_INT resh, remh;
div_and_round_double (FLOOR_DIV_EXPR, true, cst->low, cst->high, base, 0,
&resl, &resh, &reml, &remh);
cst->high = resh;
cst->low = resl;
return reml;
}
/* Dumps CST to FILE. If UNS is true, CST is considered to be unsigned,
otherwise it is signed. */
void
dump_double_int (FILE *file, double_int cst, bool uns)
{
unsigned digits[100], n;
int i;
if (double_int_zero_p (cst))
{
fprintf (file, "0");
return;
}
if (!uns && double_int_negative_p (cst))
{
fprintf (file, "-");
cst = double_int_neg (cst);
}
for (n = 0; !double_int_zero_p (cst); n++)
digits[n] = double_int_split_digit (&cst, 10);
for (i = n - 1; i >= 0; i--)
fprintf (file, "%u", digits[i]);
}
/* Sets RESULT to VAL, taken unsigned if UNS is true and as signed
otherwise. */
void
mpz_set_double_int (mpz_t result, double_int val, bool uns)
{
bool negate = false;
unsigned HOST_WIDE_INT vp[2];
if (!uns && double_int_negative_p (val))
{
negate = true;
val = double_int_neg (val);
}
vp[0] = val.low;
vp[1] = (unsigned HOST_WIDE_INT) val.high;
mpz_import (result, 2, -1, sizeof (HOST_WIDE_INT), 0, 0, vp);
if (negate)
mpz_neg (result, result);
}
/* Returns VAL converted to TYPE. If WRAP is true, then out-of-range
values of VAL will be wrapped; otherwise, they will be set to the
appropriate minimum or maximum TYPE bound. */
double_int
mpz_get_double_int (const_tree type, mpz_t val, bool wrap)
{
unsigned HOST_WIDE_INT *vp;
size_t count, numb;
double_int res;
if (!wrap)
{
mpz_t min, max;
mpz_init (min);
mpz_init (max);
get_type_static_bounds (type, min, max);
if (mpz_cmp (val, min) < 0)
mpz_set (val, min);
else if (mpz_cmp (val, max) > 0)
mpz_set (val, max);
mpz_clear (min);
mpz_clear (max);
}
/* Determine the number of unsigned HOST_WIDE_INT that are required
for representing the value. The code to calculate count is
extracted from the GMP manual, section "Integer Import and Export":
http://gmplib.org/manual/Integer-Import-and-Export.html */
numb = 8*sizeof(HOST_WIDE_INT);
count = (mpz_sizeinbase (val, 2) + numb-1) / numb;
if (count < 2)
count = 2;
vp = (unsigned HOST_WIDE_INT *) alloca (count * sizeof(HOST_WIDE_INT));
vp[0] = 0;
vp[1] = 0;
mpz_export (vp, &count, -1, sizeof (HOST_WIDE_INT), 0, 0, val);
gcc_assert (wrap || count <= 2);
res.low = vp[0];
res.high = (HOST_WIDE_INT) vp[1];
res = double_int_ext (res, TYPE_PRECISION (type), TYPE_UNSIGNED (type));
if (mpz_sgn (val) < 0)
res = double_int_neg (res);
return res;
}