Ejemplo n.º 1
0
tree
UI_To_gnu (Uint Input, tree type)
{
  /* We might have a TYPE with biased representation and be passed an unbiased
     value that doesn't fit.  We always use an unbiased type to be able to hold
     any such possible value for intermediate computations and then rely on a
     conversion back to TYPE to perform the bias adjustment when need be.  */
  tree comp_type
    = TREE_CODE (type) == INTEGER_TYPE && TYPE_BIASED_REPRESENTATION_P (type)
      ? get_base_type (type) : type;
  tree gnu_ret;

  if (Input <= Uint_Direct_Last)
    gnu_ret = build_cst_from_int (comp_type, Input - Uint_Direct_Bias);
  else
    {
      Int Idx = Uints_Ptr[Input].Loc;
      Pos Length = Uints_Ptr[Input].Length;
      Int First = Udigits_Ptr[Idx];
      tree gnu_base;

      gcc_assert (Length > 0);

      /* The computations we perform below always require a type at least as
	 large as an integer not to overflow.  FP types are always fine, but
	 INTEGER or ENUMERAL types we are handed may be too short.  We use a
	 base integer type node for the computations in this case and will
	 convert the final result back to the incoming type later on.  */
      if (!SCALAR_FLOAT_TYPE_P (comp_type) && TYPE_PRECISION (comp_type) < 32)
	comp_type = gnat_type_for_size (32, 0);

      gnu_base = build_cst_from_int (comp_type, Base);

      gnu_ret = build_cst_from_int (comp_type, First);
      if (First < 0)
	for (Idx++, Length--; Length; Idx++, Length--)
	  gnu_ret = fold_build2 (MINUS_EXPR, comp_type,
				 fold_build2 (MULT_EXPR, comp_type,
					      gnu_ret, gnu_base),
				 build_cst_from_int (comp_type,
						     Udigits_Ptr[Idx]));
      else
	for (Idx++, Length--; Length; Idx++, Length--)
	  gnu_ret = fold_build2 (PLUS_EXPR, comp_type,
				 fold_build2 (MULT_EXPR, comp_type,
					      gnu_ret, gnu_base),
				 build_cst_from_int (comp_type,
						     Udigits_Ptr[Idx]));
    }

  gnu_ret = convert (type, gnu_ret);

  /* We don't need any NOP_EXPR or NON_LVALUE_EXPR on GNU_RET.  */
  while ((TREE_CODE (gnu_ret) == NOP_EXPR
	  || TREE_CODE (gnu_ret) == NON_LVALUE_EXPR)
	 && TREE_TYPE (TREE_OPERAND (gnu_ret, 0)) == TREE_TYPE (gnu_ret))
    gnu_ret = TREE_OPERAND (gnu_ret, 0);

  return gnu_ret;
}
Ejemplo n.º 2
0
tree
UI_To_gnu (Uint Input, tree type)
{
  tree gnu_ret;

  if (Input <= Uint_Direct_Last)
    gnu_ret = build_cst_from_int (type, Input - Uint_Direct_Bias);
  else
    {
      Int Idx = Uints_Ptr[Input].Loc;
      Pos Length = Uints_Ptr[Input].Length;
      Int First = Udigits_Ptr[Idx];
      /* Do computations in integer type or TYPE whichever is wider, then
	 convert later.  This avoid overflow if type is short integer.  */
      tree comp_type
	= ((TREE_CODE (type) == REAL_TYPE
	    || TYPE_PRECISION (type) >= TYPE_PRECISION (integer_type_node))
	   ? type : integer_type_node);
      tree gnu_base = build_cst_from_int (comp_type, Base);

      gcc_assert (Length > 0);
      gnu_ret = build_cst_from_int (comp_type, First);
      if (First < 0)
	for (Idx++, Length--; Length; Idx++, Length--)
	  gnu_ret = fold (build2 (MINUS_EXPR, comp_type,
				  fold (build2 (MULT_EXPR, comp_type,
						gnu_ret, gnu_base)),
				  build_cst_from_int (comp_type,
						      Udigits_Ptr[Idx])));
      else
	for (Idx++, Length--; Length; Idx++, Length--)
	  gnu_ret = fold (build2 (PLUS_EXPR, comp_type,
				  fold (build2 (MULT_EXPR, comp_type,
						gnu_ret, gnu_base)),
				  build_cst_from_int (comp_type,
						      Udigits_Ptr[Idx])));
    }

  gnu_ret = convert (type, gnu_ret);

  /* We don't need any NOP_EXPR or NON_LVALUE_EXPR on GNU_RET.  */
  while ((TREE_CODE (gnu_ret) == NOP_EXPR
	  || TREE_CODE (gnu_ret) == NON_LVALUE_EXPR)
	 && TREE_TYPE (TREE_OPERAND (gnu_ret, 0)) == TREE_TYPE (gnu_ret))
    gnu_ret = TREE_OPERAND (gnu_ret, 0);

  return gnu_ret;
}