Mercurial > hg > CbC > CbC_gcc
diff gcc/convert.c @ 55:77e2b8dfacca gcc-4.4.5
update it from 4.4.3 to 4.5.0
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:39:51 +0900 |
parents | 58ad6c70ea60 |
children | b7f97abdc517 |
line wrap: on
line diff
--- a/gcc/convert.c Sun Feb 07 18:28:00 2010 +0900 +++ b/gcc/convert.c Fri Feb 12 23:39:51 2010 +0900 @@ -42,6 +42,7 @@ tree convert_to_pointer (tree type, tree expr) { + location_t loc = EXPR_LOCATION (expr); if (TREE_TYPE (expr) == type) return expr; @@ -53,17 +54,36 @@ { case POINTER_TYPE: case REFERENCE_TYPE: - return fold_build1 (NOP_EXPR, type, expr); + { + /* If the pointers point to different address spaces, conversion needs + to be done via a ADDR_SPACE_CONVERT_EXPR instead of a NOP_EXPR. */ + addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (type)); + addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (expr))); + + if (to_as == from_as) + return fold_build1_loc (loc, NOP_EXPR, type, expr); + else + return fold_build1_loc (loc, ADDR_SPACE_CONVERT_EXPR, type, expr); + } case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE: - if (TYPE_PRECISION (TREE_TYPE (expr)) != POINTER_SIZE) - expr = fold_build1 (NOP_EXPR, - lang_hooks.types.type_for_size (POINTER_SIZE, 0), - expr); - return fold_build1 (CONVERT_EXPR, type, expr); + { + /* If the input precision differs from the target pointer type + precision, first convert the input expression to an integer type of + the target precision. Some targets, e.g. VMS, need several pointer + sizes to coexist so the latter isn't necessarily POINTER_SIZE. */ + unsigned int pprec = TYPE_PRECISION (type); + unsigned int eprec = TYPE_PRECISION (TREE_TYPE (expr)); + if (eprec != pprec) + expr = fold_build1_loc (loc, NOP_EXPR, + lang_hooks.types.type_for_size (pprec, 0), + expr); + } + + return fold_build1_loc (loc, CONVERT_EXPR, type, expr); default: error ("cannot convert to a pointer type"); @@ -326,7 +346,8 @@ && (flag_unsafe_math_optimizations || (TYPE_PRECISION (newtype) == TYPE_PRECISION (type) && real_can_shorten_arithmetic (TYPE_MODE (itype), - TYPE_MODE (type))))) + TYPE_MODE (type)) + && !excess_precision_type (newtype)))) { expr = build2 (TREE_CODE (expr), newtype, fold (convert_to_real (newtype, arg0)), @@ -413,7 +434,7 @@ tree s_intype = TREE_TYPE (s_expr); const enum built_in_function fcode = builtin_mathfn_code (s_expr); tree fn = 0; - + switch (fcode) { CASE_FLT_FN (BUILT_IN_CEIL): @@ -473,7 +494,38 @@ default: break; } - + + if (fn) + { + tree newexpr = build_call_expr (fn, 1, CALL_EXPR_ARG (s_expr, 0)); + return convert_to_integer (type, newexpr); + } + } + + /* Convert (int)logb(d) -> ilogb(d). */ + if (optimize + && flag_unsafe_math_optimizations + && !flag_trapping_math && !flag_errno_math && flag_finite_math_only + && integer_type_node + && (outprec > TYPE_PRECISION (integer_type_node) + || (outprec == TYPE_PRECISION (integer_type_node) + && !TYPE_UNSIGNED (type)))) + { + tree s_expr = strip_float_extensions (expr); + tree s_intype = TREE_TYPE (s_expr); + const enum built_in_function fcode = builtin_mathfn_code (s_expr); + tree fn = 0; + + switch (fcode) + { + CASE_FLT_FN (BUILT_IN_LOGB): + fn = mathfn_built_in (s_intype, BUILT_IN_ILOGB); + break; + + default: + break; + } + if (fn) { tree newexpr = build_call_expr (fn, 1, CALL_EXPR_ARG (s_expr, 0)); @@ -488,10 +540,13 @@ if (integer_zerop (expr)) return build_int_cst (type, 0); - /* Convert to an unsigned integer of the correct width first, - and from there widen/truncate to the required type. */ + /* Convert to an unsigned integer of the correct width first, and from + there widen/truncate to the required type. Some targets support the + coexistence of multiple valid pointer sizes, so fetch the one we need + from the type. */ expr = fold_build1 (CONVERT_EXPR, - lang_hooks.types.type_for_size (POINTER_SIZE, 0), + lang_hooks.types.type_for_size + (TYPE_PRECISION (intype), 0), expr); return fold_convert (type, expr);