summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ada/ChangeLog21
-rw-r--r--gcc/ada/gcc-interface/cuintp.c60
-rw-r--r--gcc/ada/gcc-interface/decl.c18
-rw-r--r--gcc/ada/gcc-interface/gigi.h21
-rw-r--r--gcc/ada/gcc-interface/trans.c52
-rw-r--r--gcc/ada/gcc-interface/utils.c8
-rw-r--r--gcc/ada/uintp.adb16
-rw-r--r--gcc/ada/uintp.h42
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)