diff options
-rw-r--r-- | gcc/ada/ChangeLog | 21 | ||||
-rw-r--r-- | gcc/ada/gcc-interface/cuintp.c | 60 | ||||
-rw-r--r-- | gcc/ada/gcc-interface/decl.c | 18 | ||||
-rw-r--r-- | gcc/ada/gcc-interface/gigi.h | 21 | ||||
-rw-r--r-- | gcc/ada/gcc-interface/trans.c | 52 | ||||
-rw-r--r-- | gcc/ada/gcc-interface/utils.c | 8 | ||||
-rw-r--r-- | gcc/ada/uintp.adb | 16 | ||||
-rw-r--r-- | gcc/ada/uintp.h | 42 |
8 files changed, 141 insertions, 97 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index a12e7db3201..802b4d42dc6 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,26 @@ 2010-04-16 Eric Botcazou <ebotcazou@adacore.com> + * uintp.adb (UI_From_Dint): Remove useless code. + (UI_From_Int): Likewise. + * uintp.h: Reorder declarations. + (UI_From_gnu): Declare. + (UI_Base): Likewise. + (Vector_Template): Likewise. + (Vector_To_Uint): Likewise. + (Uint_0): Remove. + (Uint_1): Likewise. + * gcc-interface/gigi.h: Tweak comments. + * gcc-interface/cuintp.c (UI_From_gnu): New global function. + * gcc-interface/decl.c (maybe_pad_type): Do not warn if either size + overflows. + (annotate_value) <INTEGER_CST>: Call UI_From_gnu. + * gcc-interface/trans.c (post_error_ne_num): Call post_error_ne. + (post_error_ne_tree): Call UI_From_gnu and post_error_ne. + * gcc-interface/utils.c (max_size) <tcc_binary>: Do not special-case + TYPE_MAX_VALUE. + +2010-04-16 Eric Botcazou <ebotcazou@adacore.com> + * gcc-interface/decl.c (make_type_from_size) <INTEGER_TYPE>: Just copy TYPE_NAME. * gcc-interface/trans.c (smaller_packable_type_p): Rename into... diff --git a/gcc/ada/gcc-interface/cuintp.c b/gcc/ada/gcc-interface/cuintp.c index 642a71b21c5..31ed801e63c 100644 --- a/gcc/ada/gcc-interface/cuintp.c +++ b/gcc/ada/gcc-interface/cuintp.c @@ -6,7 +6,7 @@ * * * C Implementation File * * * - * Copyright (C) 1992-2009, Free Software Foundation, Inc. * + * Copyright (C) 1992-2010, Free Software Foundation, Inc. * * * * GNAT is free software; you can redistribute it and/or modify it under * * terms of the GNU General Public License as published by the Free Soft- * @@ -142,3 +142,61 @@ UI_To_gnu (Uint Input, tree type) return gnu_ret; } + +/* Similar to UI_From_Int, but take a GCC INTEGER_CST. We use UI_From_Int + when possible, i.e. for a 32-bit signed value, to take advantage of its + built-in caching mechanism. For values of larger magnitude, we compute + digits into a vector and call Vector_To_Uint. */ + +Uint +UI_From_gnu (tree Input) +{ + tree gnu_type = TREE_TYPE (Input), gnu_base, gnu_temp; + /* UI_Base is defined so that 5 Uint digits is sufficient to hold the + largest possible signed 64-bit value. */ + const int Max_For_Dint = 5; + int v[Max_For_Dint], i; + Vector_Template temp; + Int_Vector vec; + +#if HOST_BITS_PER_WIDE_INT == 64 + /* On 64-bit hosts, host_integerp tells whether the input fits in a + signed 64-bit integer. Then a truncation tells whether it fits + in a signed 32-bit integer. */ + if (host_integerp (Input, 0)) + { + HOST_WIDE_INT hw_input = TREE_INT_CST_LOW (Input); + if (hw_input == (int) hw_input) + return UI_From_Int (hw_input); + } + else + return No_Uint; +#else + /* On 32-bit hosts, host_integerp tells whether the input fits in a + signed 32-bit integer. Then a sign test tells whether it fits + in a signed 64-bit integer. */ + if (host_integerp (Input, 0)) + return UI_From_Int (TREE_INT_CST_LOW (Input)); + else if (TREE_INT_CST_HIGH (Input) < 0 + && TYPE_UNSIGNED (gnu_type) + && !(TREE_CODE (gnu_type) == INTEGER_TYPE + && TYPE_IS_SIZETYPE (gnu_type))) + return No_Uint; +#endif + + gnu_base = build_int_cst (gnu_type, UI_Base); + gnu_temp = Input; + + for (i = Max_For_Dint - 1; i >= 0; i--) + { + v[i] = tree_low_cst (fold_build1 (ABS_EXPR, gnu_type, + fold_build2 (TRUNC_MOD_EXPR, gnu_type, + gnu_temp, gnu_base)), + 0); + gnu_temp = fold_build2 (TRUNC_DIV_EXPR, gnu_type, gnu_temp, gnu_base); + } + + temp.Low_Bound = 1, temp.High_Bound = Max_For_Dint; + vec.Array = v, vec.Bounds = &temp; + return Vector_To_Uint (vec, tree_int_cst_sgn (Input) < 0); +} diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index 44c39299558..1a42ff7f8f8 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -6281,7 +6281,9 @@ maybe_pad_type (tree type, tree size, unsigned int align, && !operand_equal_p (size, orig_size, 0) && !(TREE_CODE (size) == INTEGER_CST && TREE_CODE (orig_size) == INTEGER_CST - && tree_int_cst_lt (size, orig_size))) + && (TREE_OVERFLOW (size) + || TREE_OVERFLOW (orig_size) + || tree_int_cst_lt (size, orig_size)))) { Node_Id gnat_error_node = Empty; @@ -7087,7 +7089,7 @@ annotate_value (tree gnu_size) TCode tcode; Node_Ref_Or_Val ops[3], ret; struct tree_int_map **h = NULL; - int size, i; + int i; /* See if we've already saved the value for this node. */ if (EXPR_P (gnu_size)) @@ -7143,17 +7145,7 @@ annotate_value (tree gnu_size) return annotate_value (temp); } - if (!host_integerp (gnu_size, 1)) - return No_Uint; - - size = tree_low_cst (gnu_size, 1); - - /* This peculiar test is to make sure that the size fits in an int - on machines where HOST_WIDE_INT is not "int". */ - if (tree_low_cst (gnu_size, 1) == size) - return UI_From_Int (size); - else - return No_Uint; + return UI_From_gnu (gnu_size); case COMPONENT_REF: /* The only case we handle here is a simple discriminant reference. */ diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h index f0c577799e2..d6101be4da5 100644 --- a/gcc/ada/gcc-interface/gigi.h +++ b/gcc/ada/gcc-interface/gigi.h @@ -232,28 +232,25 @@ extern bool Sloc_to_locus (Source_Ptr Sloc, location_t *locus); /* Post an error message. MSG is the error message, properly annotated. NODE is the node at which to post the error and the node to use for the - "&" substitution. */ + '&' substitution. */ extern void post_error (const char *msg, Node_Id node); -/* Similar, but NODE is the node at which to post the error and ENT - is the node to use for the "&" substitution. */ +/* Similar to post_error, but NODE is the node at which to post the error and + ENT is the node to use for the '&' substitution. */ extern void post_error_ne (const char *msg, Node_Id node, Entity_Id ent); -/* Similar, but NODE is the node at which to post the error, ENT is the node - to use for the "&" substitution, and NUM is the number to use for ^. */ +/* Similar to post_error_ne, but NUM is the number to use for the '^'. */ extern void post_error_ne_num (const char *msg, Node_Id node, Entity_Id ent, int num); -/* Similar to post_error_ne_num, but T is a GCC tree representing the number - to write. If the tree represents a constant that fits within a - host integer, the text inside curly brackets in MSG will be output - (presumably including a '^'). Otherwise that text will not be output - and the text inside square brackets will be output instead. */ +/* Similar to post_error_ne, but T is a GCC tree representing the number to + write. If T represents a constant, the text inside curly brackets in + MSG will be output (presumably including a '^'). Otherwise it will not + be output and the text inside square brackets will be output instead. */ extern void post_error_ne_tree (const char *msg, Node_Id node, Entity_Id ent, tree t); -/* Similar to post_error_ne_tree, except that NUM is a second integer to write - in the message. */ +/* Similar to post_error_ne_tree, but NUM is a second integer to write. */ extern void post_error_ne_tree_2 (const char *msg, Node_Id node, Entity_Id ent, tree t, int num); diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c index ee8eedcd15b..7cf15dafb11 100644 --- a/gcc/ada/gcc-interface/trans.c +++ b/gcc/ada/gcc-interface/trans.c @@ -7404,7 +7404,7 @@ decode_name (const char *name) /* Post an error message. MSG is the error message, properly annotated. NODE is the node at which to post the error and the node to use for the - "&" substitution. */ + '&' substitution. */ void post_error (const char *msg, Node_Id node) @@ -7418,8 +7418,8 @@ post_error (const char *msg, Node_Id node) Error_Msg_N (fp, node); } -/* Similar, but NODE is the node at which to post the error and ENT - is the node to use for the "&" substitution. */ +/* Similar to post_error, but NODE is the node at which to post the error and + ENT is the node to use for the '&' substitution. */ void post_error_ne (const char *msg, Node_Id node, Entity_Id ent) @@ -7433,56 +7433,37 @@ post_error_ne (const char *msg, Node_Id node, Entity_Id ent) Error_Msg_NE (fp, node, ent); } -/* Similar, but NODE is the node at which to post the error, ENT is the node - to use for the "&" substitution, and NUM is the number to use for ^. */ +/* Similar to post_error_ne, but NUM is the number to use for the '^'. */ void post_error_ne_num (const char *msg, Node_Id node, Entity_Id ent, int num) { - String_Template temp; - Fat_Pointer fp; - - temp.Low_Bound = 1, temp.High_Bound = strlen (msg); - fp.Array = msg, fp.Bounds = &temp; Error_Msg_Uint_1 = UI_From_Int (num); - - if (Present (node)) - Error_Msg_NE (fp, node, ent); + post_error_ne (msg, node, ent); } -/* Similar to post_error_ne_num, but T is a GCC tree representing the - number to write. If the tree represents a constant that fits within - a host integer, the text inside curly brackets in MSG will be output - (presumably including a '^'). Otherwise that text will not be output - and the text inside square brackets will be output instead. */ +/* Similar to post_error_ne, but T is a GCC tree representing the number to + write. If T represents a constant, the text inside curly brackets in + MSG will be output (presumably including a '^'). Otherwise it will not + be output and the text inside square brackets will be output instead. */ void post_error_ne_tree (const char *msg, Node_Id node, Entity_Id ent, tree t) { - char *newmsg = XALLOCAVEC (char, strlen (msg) + 1); - String_Template temp = {1, 0}; - Fat_Pointer fp; + char *new_msg = XALLOCAVEC (char, strlen (msg) + 1); char start_yes, end_yes, start_no, end_no; const char *p; char *q; - fp.Array = newmsg, fp.Bounds = &temp; - - if (host_integerp (t, 1) -#if HOST_BITS_PER_WIDE_INT > HOST_BITS_PER_INT - && - compare_tree_int - (t, (((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_INT - 1)) - 1)) < 0 -#endif - ) + if (TREE_CODE (t) == INTEGER_CST) { - Error_Msg_Uint_1 = UI_From_Int (tree_low_cst (t, 1)); + Error_Msg_Uint_1 = UI_From_gnu (t); start_yes = '{', end_yes = '}', start_no = '[', end_no = ']'; } else start_yes = '[', end_yes = ']', start_no = '{', end_no = '}'; - for (p = msg, q = newmsg; *p; p++) + for (p = msg, q = new_msg; *p; p++) { if (*p == start_yes) for (p++; *p != end_yes; p++) @@ -7496,13 +7477,10 @@ post_error_ne_tree (const char *msg, Node_Id node, Entity_Id ent, tree t) *q = 0; - temp.High_Bound = strlen (newmsg); - if (Present (node)) - Error_Msg_NE (fp, node, ent); + post_error_ne (new_msg, node, ent); } -/* Similar to post_error_ne_tree, except that NUM is a second integer to write - in the message. */ +/* Similar to post_error_ne_tree, but NUM is a second integer to write. */ void post_error_ne_tree_2 (const char *msg, Node_Id node, Entity_Id ent, tree t, diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index 27959ea505c..68a0d0f0391 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -2228,8 +2228,7 @@ max_size (tree exp, bool max_p) In that case, if one side overflows, return the other. sizetype is signed, but we know sizes are non-negative. Likewise, handle a MINUS_EXPR or PLUS_EXPR with the LHS - overflowing or the maximum possible value and the RHS - a variable. */ + overflowing and the RHS a variable. */ if (max_p && code == MIN_EXPR && TREE_CODE (rhs) == INTEGER_CST @@ -2241,9 +2240,8 @@ max_size (tree exp, bool max_p) && TREE_OVERFLOW (lhs)) return rhs; else if ((code == MINUS_EXPR || code == PLUS_EXPR) - && ((TREE_CODE (lhs) == INTEGER_CST - && TREE_OVERFLOW (lhs)) - || operand_equal_p (lhs, TYPE_MAX_VALUE (type), 0)) + && TREE_CODE (lhs) == INTEGER_CST + && TREE_OVERFLOW (lhs) && !TREE_CONSTANT (rhs)) return lhs; else diff --git a/gcc/ada/uintp.adb b/gcc/ada/uintp.adb index 93377219175..3b72d154c10 100644 --- a/gcc/ada/uintp.adb +++ b/gcc/ada/uintp.adb @@ -1703,15 +1703,9 @@ package body Uintp is V : UI_Vector (1 .. Max_For_Dint); - Temp_Integer : Dint; + Temp_Integer : Dint := Input; begin - for J in V'Range loop - V (J) := 0; - end loop; - - Temp_Integer := Input; - for J in reverse V'Range loop V (J) := Int (abs (Temp_Integer rem Dint (Base))); Temp_Integer := Temp_Integer / Dint (Base); @@ -1752,15 +1746,9 @@ package body Uintp is V : UI_Vector (1 .. Max_For_Int); - Temp_Integer : Int; + Temp_Integer : Int := Input; begin - for J in V'Range loop - V (J) := 0; - end loop; - - Temp_Integer := Input; - for J in reverse V'Range loop V (J) := abs (Temp_Integer rem Base); Temp_Integer := Temp_Integer / Base; diff --git a/gcc/ada/uintp.h b/gcc/ada/uintp.h index 5921945f3c0..de70e115f43 100644 --- a/gcc/ada/uintp.h +++ b/gcc/ada/uintp.h @@ -6,7 +6,7 @@ * * * C Header File * * * - * Copyright (C) 1992-2007, Free Software Foundation, Inc. * + * Copyright (C) 1992-2010, Free Software Foundation, Inc. * * * * GNAT is free software; you can redistribute it and/or modify it under * * terms of the GNU General Public License as published by the Free Soft- * @@ -38,27 +38,42 @@ struct Uint_Entry #define UI_Is_In_Int_Range uintp__ui_is_in_int_range extern Boolean UI_Is_In_Int_Range (Uint); -/* Obtain Char_Code value from Uint input. Value must be in range. */ +/* Obtain Char_Code value from Uint input. Value must be in range. */ #define UI_To_CC uintp__ui_to_cc -extern Char_Code UI_To_CC (Uint); +extern Char_Code UI_To_CC (Uint); -/* Obtain Int value from Uint input. This will abort if the result is - out of range. */ +/* Convert a Char_Code into a Uint. */ +#define UI_From_CC uintp__ui_from_cc +extern Uint UI_From_CC (Char_Code); + +/* Obtain Int value from Uint input. Abort if the result is out of range. */ #define UI_To_Int uintp__ui_to_int extern Int UI_To_Int (Uint); +/* Similarly, but return a GCC INTEGER_CST. */ +extern tree UI_To_gnu (Uint, tree); + /* Convert an Int into a Uint. */ #define UI_From_Int uintp__ui_from_int extern Uint UI_From_Int (int); -/* Convert a Char_Code into a Uint. */ -#define UI_From_CC uintp__ui_from_cc -extern Uint UI_From_CC (Char_Code); +/* Similarly, but take a GCC INTEGER_CST. */ +extern Uint UI_From_gnu (tree); -/* Similarly, but return a GCC INTEGER_CST. Overflow is tested by the - constant-folding used to build the node. TYPE is the GCC type of the - resulting node. */ -extern tree UI_To_gnu (Uint, tree); +/* Uint values are represented as multiple precision integers stored in a + multi-digit format using UI_Base as the base. This value is chosen so + that the product UI_Base*UI_Base is within the range of Int values. */ +#define UI_Base uintp__base +extern const int UI_Base; + +/* Types for the fat pointer of Int vectors and the template it points to. */ +typedef struct {int Low_Bound, High_Bound; } Vector_Template; +typedef struct {const int *Array; Vector_Template *Bounds; } + __attribute ((aligned (sizeof (char *) * 2))) Int_Vector; + +/* Create and return the Uint value from the Int vector. */ +#define Vector_To_Uint uintp__vector_to_uint +extern Uint Vector_To_Uint (Int_Vector, Boolean); /* Universal integers are represented by the Uint type which is an index into the Uints_Ptr table containing Uint_Entry values. A Uint_Entry contains an @@ -75,6 +90,3 @@ extern struct Uint_Entry *uintp__uints__table; #define Udigits_Ptr uintp__udigits__table extern int *uintp__udigits__table; - -#define Uint_0 (Uint_Direct_Bias + 0) -#define Uint_1 (Uint_Direct_Bias + 1) |