aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/gcc-interface/decl.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/gcc-interface/decl.c')
-rw-r--r--gcc/ada/gcc-interface/decl.c72
1 files changed, 70 insertions, 2 deletions
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index 385b720..760c7f4 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -44,6 +44,7 @@
#include "repinfo.h"
#include "snames.h"
#include "uintp.h"
+#include "urealp.h"
#include "fe.h"
#include "sinfo.h"
#include "einfo.h"
@@ -1619,13 +1620,80 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
break;
case E_Signed_Integer_Type:
- case E_Ordinary_Fixed_Point_Type:
- case E_Decimal_Fixed_Point_Type:
/* For integer types, just make a signed type the appropriate number
of bits. */
gnu_type = make_signed_type (esize);
goto discrete_type;
+ case E_Ordinary_Fixed_Point_Type:
+ case E_Decimal_Fixed_Point_Type:
+ {
+ /* Small_Value is the scale factor. */
+ const Ureal gnat_small_value = Small_Value (gnat_entity);
+ tree scale_factor = NULL_TREE;
+
+ gnu_type = make_signed_type (esize);
+
+ /* Try to decode the scale factor and to save it for the fixed-point
+ types debug hook. */
+
+ /* There are various ways to describe the scale factor, however there
+ are cases where back-end internals cannot hold it. In such cases,
+ we output invalid scale factor for such cases (i.e. the 0/0
+ rational constant) but we expect GNAT to output GNAT encodings,
+ then. Thus, keep this in sync with
+ Exp_Dbug.Is_Handled_Scale_Factor. */
+
+ /* When encoded as 1/2**N or 1/10**N, describe the scale factor as a
+ binary or decimal scale: it is easier to read for humans. */
+ if (UI_Eq (Numerator (gnat_small_value), Uint_1)
+ && (Rbase (gnat_small_value) == 2
+ || Rbase (gnat_small_value) == 10))
+ {
+ /* Given RM restrictions on 'Small values, we assume here that
+ the denominator fits in an int. */
+ const tree base = build_int_cst (integer_type_node,
+ Rbase (gnat_small_value));
+ const tree exponent
+ = build_int_cst (integer_type_node,
+ UI_To_Int (Denominator (gnat_small_value)));
+ scale_factor
+ = build2 (RDIV_EXPR, integer_type_node,
+ integer_one_node,
+ build2 (POWER_EXPR, integer_type_node,
+ base, exponent));
+ }
+
+ /* Default to arbitrary scale factors descriptions. */
+ else
+ {
+ const Uint num = Norm_Num (gnat_small_value);
+ const Uint den = Norm_Den (gnat_small_value);
+
+ if (UI_Is_In_Int_Range (num) && UI_Is_In_Int_Range (den))
+ {
+ const tree gnu_num
+ = build_int_cst (integer_type_node,
+ UI_To_Int (Norm_Num (gnat_small_value)));
+ const tree gnu_den
+ = build_int_cst (integer_type_node,
+ UI_To_Int (Norm_Den (gnat_small_value)));
+ scale_factor = build2 (RDIV_EXPR, integer_type_node,
+ gnu_num, gnu_den);
+ }
+ else
+ /* If compiler internals cannot represent arbitrary scale
+ factors, output an invalid scale factor so that debugger
+ don't try to handle them but so that we still have a type
+ in the output. Note that GNAT */
+ scale_factor = integer_zero_node;
+ }
+
+ TYPE_FIXED_POINT_P (gnu_type) = 1;
+ SET_TYPE_SCALE_FACTOR (gnu_type, scale_factor);
+ }
+ goto discrete_type;
+
case E_Modular_Integer_Type:
{
/* For modular types, make the unsigned type of the proper number