Commit a4f7374e by Eric Botcazou Committed by Eric Botcazou

trans.c (convert_with_check): Use a custom base type if the base type of the…

trans.c (convert_with_check): Use a custom base type if the base type of the expression has a different...

	* gcc-interface/trans.c (convert_with_check): Use a custom base type
	if the base type of the expression has a different machine mode.
	Rename a couple of parameters and local variable.

From-SVN: r251705
parent 3fd9ae96
2017-09-05 Eric Botcazou <ebotcazou@adacore.com> 2017-09-05 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/trans.c (convert_with_check): Use a custom base type
if the base type of the expression has a different machine mode.
Rename a couple of parameters and local variable.
2017-09-05 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/trans.c (Attribute_to_gnu) <Attr_Address>: Do not strip * gcc-interface/trans.c (Attribute_to_gnu) <Attr_Address>: Do not strip
conversions around prefixes that are not references. conversions around prefixes that are not references.
......
...@@ -9252,63 +9252,71 @@ emit_check (tree gnu_cond, tree gnu_expr, int reason, Node_Id gnat_node) ...@@ -9252,63 +9252,71 @@ emit_check (tree gnu_cond, tree gnu_expr, int reason, Node_Id gnat_node)
/* Return an expression that converts GNU_EXPR to GNAT_TYPE, doing overflow /* Return an expression that converts GNU_EXPR to GNAT_TYPE, doing overflow
checks if OVERFLOW_P is true and range checks if RANGE_P is true. checks if OVERFLOW_P is true and range checks if RANGE_P is true.
GNAT_TYPE is known to be an integral type. If TRUNCATE_P true, do a If TRUNCATE_P true, do a float-to-integer conversion with truncation,
float to integer conversion with truncation; otherwise round. otherwise round. GNAT_NODE is the GNAT node conveying the source location
GNAT_NODE is the GNAT node conveying the source location for which the for which the error should be signaled. */
error should be signaled. */
static tree static tree
convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflowp, convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflow_p,
bool rangep, bool truncatep, Node_Id gnat_node) bool range_p, bool truncate_p, Node_Id gnat_node)
{ {
tree gnu_type = get_unpadded_type (gnat_type); tree gnu_type = get_unpadded_type (gnat_type);
tree gnu_in_type = TREE_TYPE (gnu_expr);
tree gnu_in_basetype = get_base_type (gnu_in_type);
tree gnu_base_type = get_base_type (gnu_type); tree gnu_base_type = get_base_type (gnu_type);
tree gnu_in_type = TREE_TYPE (gnu_expr);
tree gnu_in_base_type = get_base_type (gnu_in_type);
tree gnu_result = gnu_expr; tree gnu_result = gnu_expr;
/* If we are not doing any checks, the output is an integral type and the /* If we are not doing any checks, the output is an integral type and the
input is not a floating-point type, just do the conversion. This is input is not a floating-point type, just do the conversion. This is
required for packed array types and is simpler in all cases anyway. */ required for packed array types and is simpler in all cases anyway. */
if (!rangep if (!range_p
&& !overflowp && !overflow_p
&& INTEGRAL_TYPE_P (gnu_base_type) && INTEGRAL_TYPE_P (gnu_base_type)
&& !FLOAT_TYPE_P (gnu_in_type)) && !FLOAT_TYPE_P (gnu_in_base_type))
return convert (gnu_type, gnu_expr); return convert (gnu_type, gnu_expr);
/* First convert the expression to its base type. This /* If the mode of the input base type is larger, then converting to it below
will never generate code, but makes the tests below much simpler. may pessimize the final conversion step, for example generate a libcall
But don't do this if converting from an integer type to an unconstrained instead of a simple instruction, so use a narrower type in this case. */
array type since then we need to get the bounds from the original if (TYPE_MODE (gnu_in_base_type) != TYPE_MODE (gnu_in_type)
(unpacked) type. */ && !(TREE_CODE (gnu_in_type) == INTEGER_TYPE
&& TYPE_BIASED_REPRESENTATION_P (gnu_in_type)))
gnu_in_base_type = gnat_type_for_mode (TYPE_MODE (gnu_in_type),
TYPE_UNSIGNED (gnu_in_type));
/* First convert the expression to the base type. This will never generate
code, but makes the tests below simpler. But don't do this if converting
from an integer type to an unconstrained array type since then we need to
get the bounds from the original (unpacked) type. */
if (TREE_CODE (gnu_type) != UNCONSTRAINED_ARRAY_TYPE) if (TREE_CODE (gnu_type) != UNCONSTRAINED_ARRAY_TYPE)
gnu_result = convert (gnu_in_basetype, gnu_result); gnu_result = convert (gnu_in_base_type, gnu_result);
/* If overflow checks are requested, we need to be sure the result will /* If overflow checks are requested, we need to be sure the result will fit
fit in the output base type. But don't do this if the input in the output base type. But don't do this if the input is integer and
is integer and the output floating-point. */ the output floating-point. */
if (overflowp if (overflow_p
&& !(FLOAT_TYPE_P (gnu_base_type) && INTEGRAL_TYPE_P (gnu_in_basetype))) && !(FLOAT_TYPE_P (gnu_base_type) && INTEGRAL_TYPE_P (gnu_in_base_type)))
{ {
/* Ensure GNU_EXPR only gets evaluated once. */ /* Ensure GNU_EXPR only gets evaluated once. */
tree gnu_input = gnat_protect_expr (gnu_result); tree gnu_input = gnat_protect_expr (gnu_result);
tree gnu_cond = boolean_false_node; tree gnu_cond = boolean_false_node;
tree gnu_in_lb = TYPE_MIN_VALUE (gnu_in_basetype); tree gnu_in_lb = TYPE_MIN_VALUE (gnu_in_base_type);
tree gnu_in_ub = TYPE_MAX_VALUE (gnu_in_basetype); tree gnu_in_ub = TYPE_MAX_VALUE (gnu_in_base_type);
tree gnu_out_lb = TYPE_MIN_VALUE (gnu_base_type); tree gnu_out_lb = TYPE_MIN_VALUE (gnu_base_type);
tree gnu_out_ub = TYPE_MAX_VALUE (gnu_base_type); tree gnu_out_ub = TYPE_MAX_VALUE (gnu_base_type);
/* Convert the lower bounds to signed types, so we're sure we're /* Convert the lower bounds to signed types, so we're sure we're
comparing them properly. Likewise, convert the upper bounds comparing them properly. Likewise, convert the upper bounds
to unsigned types. */ to unsigned types. */
if (INTEGRAL_TYPE_P (gnu_in_basetype) && TYPE_UNSIGNED (gnu_in_basetype)) if (INTEGRAL_TYPE_P (gnu_in_base_type)
&& TYPE_UNSIGNED (gnu_in_base_type))
gnu_in_lb gnu_in_lb
= convert (gnat_signed_type_for (gnu_in_basetype), gnu_in_lb); = convert (gnat_signed_type_for (gnu_in_base_type), gnu_in_lb);
if (INTEGRAL_TYPE_P (gnu_in_basetype) if (INTEGRAL_TYPE_P (gnu_in_base_type)
&& !TYPE_UNSIGNED (gnu_in_basetype)) && !TYPE_UNSIGNED (gnu_in_base_type))
gnu_in_ub gnu_in_ub
= convert (gnat_unsigned_type_for (gnu_in_basetype), gnu_in_ub); = convert (gnat_unsigned_type_for (gnu_in_base_type), gnu_in_ub);
if (INTEGRAL_TYPE_P (gnu_base_type) && TYPE_UNSIGNED (gnu_base_type)) if (INTEGRAL_TYPE_P (gnu_base_type) && TYPE_UNSIGNED (gnu_base_type))
gnu_out_lb gnu_out_lb
...@@ -9328,7 +9336,7 @@ convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflowp, ...@@ -9328,7 +9336,7 @@ convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflowp,
Note that we have to do the comparison which would *fail* in the Note that we have to do the comparison which would *fail* in the
case of an error since if it's an FP comparison and one of the case of an error since if it's an FP comparison and one of the
values is a NaN or Inf, the comparison will fail. */ values is a NaN or Inf, the comparison will fail. */
if (INTEGRAL_TYPE_P (gnu_in_basetype) if (INTEGRAL_TYPE_P (gnu_in_base_type)
? tree_int_cst_lt (gnu_in_lb, gnu_out_lb) ? tree_int_cst_lt (gnu_in_lb, gnu_out_lb)
: (FLOAT_TYPE_P (gnu_base_type) : (FLOAT_TYPE_P (gnu_base_type)
? real_less (&TREE_REAL_CST (gnu_in_lb), ? real_less (&TREE_REAL_CST (gnu_in_lb),
...@@ -9337,10 +9345,10 @@ convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflowp, ...@@ -9337,10 +9345,10 @@ convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflowp,
gnu_cond gnu_cond
= invert_truthvalue = invert_truthvalue
(build_binary_op (GE_EXPR, boolean_type_node, (build_binary_op (GE_EXPR, boolean_type_node,
gnu_input, convert (gnu_in_basetype, gnu_input, convert (gnu_in_base_type,
gnu_out_lb))); gnu_out_lb)));
if (INTEGRAL_TYPE_P (gnu_in_basetype) if (INTEGRAL_TYPE_P (gnu_in_base_type)
? tree_int_cst_lt (gnu_out_ub, gnu_in_ub) ? tree_int_cst_lt (gnu_out_ub, gnu_in_ub)
: (FLOAT_TYPE_P (gnu_base_type) : (FLOAT_TYPE_P (gnu_base_type)
? real_less (&TREE_REAL_CST (gnu_out_ub), ? real_less (&TREE_REAL_CST (gnu_out_ub),
...@@ -9351,7 +9359,7 @@ convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflowp, ...@@ -9351,7 +9359,7 @@ convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflowp,
invert_truthvalue invert_truthvalue
(build_binary_op (LE_EXPR, boolean_type_node, (build_binary_op (LE_EXPR, boolean_type_node,
gnu_input, gnu_input,
convert (gnu_in_basetype, convert (gnu_in_base_type,
gnu_out_ub)))); gnu_out_ub))));
if (!integer_zerop (gnu_cond)) if (!integer_zerop (gnu_cond))
...@@ -9362,8 +9370,8 @@ convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflowp, ...@@ -9362,8 +9370,8 @@ convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflowp,
/* Now convert to the result base type. If this is a non-truncating /* Now convert to the result base type. If this is a non-truncating
float-to-integer conversion, round. */ float-to-integer conversion, round. */
if (INTEGRAL_TYPE_P (gnu_base_type) if (INTEGRAL_TYPE_P (gnu_base_type)
&& FLOAT_TYPE_P (gnu_in_basetype) && FLOAT_TYPE_P (gnu_in_base_type)
&& !truncatep) && !truncate_p)
{ {
REAL_VALUE_TYPE half_minus_pred_half, pred_half; REAL_VALUE_TYPE half_minus_pred_half, pred_half;
tree gnu_conv, gnu_zero, gnu_comp, calc_type; tree gnu_conv, gnu_zero, gnu_comp, calc_type;
...@@ -9375,7 +9383,7 @@ convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflowp, ...@@ -9375,7 +9383,7 @@ convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflowp,
precision from spoiling this property, use the widest hardware precision from spoiling this property, use the widest hardware
floating-point type if FP_ARITH_MAY_WIDEN is true. */ floating-point type if FP_ARITH_MAY_WIDEN is true. */
calc_type calc_type
= fp_arith_may_widen ? longest_float_type_node : gnu_in_basetype; = fp_arith_may_widen ? longest_float_type_node : gnu_in_base_type;
/* Compute the exact value calc_type'Pred (0.5) at compile time. */ /* Compute the exact value calc_type'Pred (0.5) at compile time. */
fmt = REAL_MODE_FORMAT (TYPE_MODE (calc_type)); fmt = REAL_MODE_FORMAT (TYPE_MODE (calc_type));
...@@ -9400,7 +9408,7 @@ convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflowp, ...@@ -9400,7 +9408,7 @@ convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflowp,
to be scheduled in parallel with retrieval of the constant and to be scheduled in parallel with retrieval of the constant and
conversion of the input to the calc_type (if necessary). */ conversion of the input to the calc_type (if necessary). */
gnu_zero = build_real (gnu_in_basetype, dconst0); gnu_zero = build_real (gnu_in_base_type, dconst0);
gnu_result = gnat_protect_expr (gnu_result); gnu_result = gnat_protect_expr (gnu_result);
gnu_conv = convert (calc_type, gnu_result); gnu_conv = convert (calc_type, gnu_result);
gnu_comp gnu_comp
...@@ -9422,9 +9430,10 @@ convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflowp, ...@@ -9422,9 +9430,10 @@ convert_with_check (Entity_Id gnat_type, tree gnu_expr, bool overflowp,
/* Finally, do the range check if requested. Note that if the result type /* Finally, do the range check if requested. Note that if the result type
is a modular type, the range check is actually an overflow check. */ is a modular type, the range check is actually an overflow check. */
if (rangep if (range_p
|| (TREE_CODE (gnu_base_type) == INTEGER_TYPE || (overflow_p
&& TYPE_MODULAR_P (gnu_base_type) && overflowp)) && TREE_CODE (gnu_base_type) == INTEGER_TYPE
&& TYPE_MODULAR_P (gnu_base_type)))
gnu_result = emit_range_check (gnu_result, gnat_type, gnat_node); gnu_result = emit_range_check (gnu_result, gnat_type, gnat_node);
return convert (gnu_type, gnu_result); return convert (gnu_type, gnu_result);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment