diff options
Diffstat (limited to 'gcc/tree.c')
-rw-r--r-- | gcc/tree.c | 70 |
1 files changed, 59 insertions, 11 deletions
@@ -1684,8 +1684,7 @@ integer_pow2p (const_tree expr) if (TREE_CODE (expr) != INTEGER_CST) return 0; - prec = (POINTER_TYPE_P (TREE_TYPE (expr)) - ? POINTER_SIZE : TYPE_PRECISION (TREE_TYPE (expr))); + prec = int_or_pointer_precision (TREE_TYPE (expr)); high = TREE_INT_CST_HIGH (expr); low = TREE_INT_CST_LOW (expr); @@ -1749,9 +1748,7 @@ tree_log2 (const_tree expr) if (TREE_CODE (expr) == COMPLEX_CST) return tree_log2 (TREE_REALPART (expr)); - prec = (POINTER_TYPE_P (TREE_TYPE (expr)) - ? POINTER_SIZE : TYPE_PRECISION (TREE_TYPE (expr))); - + prec = int_or_pointer_precision (TREE_TYPE (expr)); high = TREE_INT_CST_HIGH (expr); low = TREE_INT_CST_LOW (expr); @@ -1787,9 +1784,7 @@ tree_floor_log2 (const_tree expr) if (TREE_CODE (expr) == COMPLEX_CST) return tree_log2 (TREE_REALPART (expr)); - prec = (POINTER_TYPE_P (TREE_TYPE (expr)) - ? POINTER_SIZE : TYPE_PRECISION (TREE_TYPE (expr))); - + prec = int_or_pointer_precision (TREE_TYPE (expr)); high = TREE_INT_CST_HIGH (expr); low = TREE_INT_CST_LOW (expr); @@ -6746,7 +6741,10 @@ build_pointer_type_for_mode (tree to_type, enum machine_mode mode, tree build_pointer_type (tree to_type) { - return build_pointer_type_for_mode (to_type, ptr_mode, false); + addr_space_t as = to_type == error_mark_node? ADDR_SPACE_GENERIC + : TYPE_ADDR_SPACE (to_type); + enum machine_mode pointer_mode = targetm.addr_space.pointer_mode (as); + return build_pointer_type_for_mode (to_type, pointer_mode, false); } /* Same as build_pointer_type_for_mode, but for REFERENCE_TYPE. */ @@ -6810,7 +6808,10 @@ build_reference_type_for_mode (tree to_type, enum machine_mode mode, tree build_reference_type (tree to_type) { - return build_reference_type_for_mode (to_type, ptr_mode, false); + addr_space_t as = to_type == error_mark_node? ADDR_SPACE_GENERIC + : TYPE_ADDR_SPACE (to_type); + enum machine_mode pointer_mode = targetm.addr_space.pointer_mode (as); + return build_reference_type_for_mode (to_type, pointer_mode, false); } /* Build a type that is compatible with t but has no cv quals anywhere @@ -9675,7 +9676,19 @@ signed_or_unsigned_type_for (int unsignedp, tree type) { tree t = type; if (POINTER_TYPE_P (type)) - t = size_type_node; + { + /* If the pointer points to the normal address space, use the + size_type_node. Otherwise use an appropriate size for the pointer + based on the named address space it points to. */ + if (!TYPE_ADDR_SPACE (TREE_TYPE (t))) + t = size_type_node; + + else + { + int prec = int_or_pointer_precision (t); + return lang_hooks.types.type_for_size (prec, unsignedp); + } + } if (!INTEGRAL_TYPE_P (t) || TYPE_UNSIGNED (t) == unsignedp) return t; @@ -10549,6 +10562,41 @@ build_target_option_node (void) return t; } +/* Return the size in bits of an integer or pointer type. TYPE_PRECISION + contains the bits, but in the past it was not set in some cases and there + was special purpose code that checked for POINTER_TYPE_P or OFFSET_TYPE, so + check that it is consitant when assertion checking is used. */ + +unsigned int +int_or_pointer_precision (const_tree type) +{ +#if ENABLE_ASSERT_CHECKING + unsigned int prec; + + if (POINTER_TYPE_P (type)) + { + addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (type)); + prec = GET_MODE_BITSIZE (targetm.addr_space.pointer_mode (as)); + gcc_assert (prec == TYPE_PRECISION (type)); + } + else if (TREE_CODE (type) == OFFSET_TYPE) + { + prec = POINTER_SIZE; + gcc_assert (prec == TYPE_PRECISION (type)); + } + else + { + prec = TYPE_PRECISION (type); + gcc_assert (prec != 0); + } + + return prec; + +#else + return TYPE_PRECISION (type); +#endif +} + /* Determine the "ultimate origin" of a block. The block may be an inlined instance of an inlined instance of a block which is local to an inline function, so we have to trace all of the way back through the origin chain |