public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 0/6] Add 128-bit integers to Ada and Rust parsers
@ 2023-03-28 15:49 Tom Tromey
  2023-03-28 15:49 ` [PATCH 1/6] Additions to gdb_mpz Tom Tromey
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Tom Tromey @ 2023-03-28 15:49 UTC (permalink / raw)
  To: gdb-patches

This series changes the Ada and Rust parser to support 128-bit types.

It would be reasonably easy to add this for C/C++ as well, following
the Ada model, but I haven't done this.

Regression tested on x86-64 Fedora 36.

Tom

---
Tom Tromey (6):
      Additions to gdb_mpz
      Convert long_const_operation to use gdb_mpz
      Add 128-bit integer support to the Rust parser
      Add overload of fits_in_type
      Remove some Ada parser helper functions
      Add 128-bit integer support to the Ada parser

 gdb/ada-exp.y                           | 74 ++++++++++++--------------------
 gdb/ada-lang.c                          |  6 ++-
 gdb/ada-lex.l                           | 75 +++++++++++++--------------------
 gdb/ax-gdb.c                            |  4 +-
 gdb/expop.h                             | 26 ++++++++++--
 gdb/expprint.c                          |  6 +++
 gdb/gmp-utils.c                         | 10 +++--
 gdb/gmp-utils.h                         | 48 ++++++++++++++++++++-
 gdb/parse.c                             | 26 ++++++++++++
 gdb/parser-defs.h                       |  2 +
 gdb/rust-lang.c                         |  2 +
 gdb/rust-parse.c                        | 37 ++++++++++------
 gdb/testsuite/gdb.ada/verylong.exp      |  5 +++
 gdb/testsuite/gdb.base/parse_number.exp |  9 ++--
 gdb/testsuite/gdb.rust/onetwoeight.exp  |  4 ++
 15 files changed, 211 insertions(+), 123 deletions(-)
---
base-commit: 134ec14b1502f30f0028293b35f57c18e44614d0
change-id: 20230328-expr-128-bit-d8d749b7089a

Best regards,
-- 
Tom Tromey <tromey@adacore.com>


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/6] Additions to gdb_mpz
  2023-03-28 15:49 [PATCH 0/6] Add 128-bit integers to Ada and Rust parsers Tom Tromey
@ 2023-03-28 15:49 ` Tom Tromey
  2023-03-28 15:49 ` [PATCH 2/6] Convert long_const_operation to use gdb_mpz Tom Tromey
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Tom Tromey @ 2023-03-28 15:49 UTC (permalink / raw)
  To: gdb-patches

In preparation for adding more 128-bit support to gdb, a few additions
to gdb_mpz are needed.

First, this adds a new 'as_integer_truncate' method.  This method
works like 'as_integer' but does not require the value to fit in the
target type -- it just truncates.

Second, gdb_mpz::export_bits is changed to handle the somewhat unusual
situation of zero-length types.  This can happen for a Rust '()' type;
but I think other languages have zero-bit integer types as well.

Finally, this adds some operator== overloads.
---
 gdb/gmp-utils.c | 10 ++++++----
 gdb/gmp-utils.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 52 insertions(+), 6 deletions(-)

diff --git a/gdb/gmp-utils.c b/gdb/gmp-utils.c
index 0afa344781b..13fa61d61e3 100644
--- a/gdb/gmp-utils.c
+++ b/gdb/gmp-utils.c
@@ -69,19 +69,21 @@ void
 gdb_mpz::export_bits (gdb::array_view<gdb_byte> buf, int endian, bool unsigned_p,
 		      bool safe) const
 {
-  gdb_assert (buf.size () > 0);
-
   int sign = mpz_sgn (m_val);
   if (sign == 0)
     {
       /* Our value is zero, so no need to call mpz_export to do the work,
 	 especially since mpz_export's documentation explicitly says
 	 that the function is a noop in this case.  Just write zero to
-	 BUF ourselves.  */
-      memset (buf.data (), 0, buf.size ());
+	 BUF ourselves, if it is non-empty.  In some languages, a
+	 zero-bit type can exist and this is also fine.  */
+      if (buf.size () > 0)
+	memset (buf.data (), 0, buf.size ());
       return;
     }
 
+  gdb_assert (buf.size () > 0);
+
   if (safe)
     {
       /* Determine the maximum range of values that our buffer can
diff --git a/gdb/gmp-utils.h b/gdb/gmp-utils.h
index f294ab622ee..d05c11ecbe4 100644
--- a/gdb/gmp-utils.h
+++ b/gdb/gmp-utils.h
@@ -119,11 +119,17 @@ struct gdb_mpz
     return result;
   }
 
-  /* Convert VAL to an integer of the given type.
+  /* Convert this value to an integer of the given type.
 
      The return type can signed or unsigned, with no size restriction.  */
   template<typename T> T as_integer () const;
 
+  /* Convert this value to an integer of the given type.  If this
+     value is too large, it is truncated.
+
+     The return type can signed or unsigned, with no size restriction.  */
+  template<typename T> T as_integer_truncate () const;
+
   /* Set VAL by importing the number stored in the byte array (BUF),
      using the given BYTE_ORDER.  The size of the data to read is
      the byte array's size.
@@ -312,7 +318,7 @@ struct gdb_mpz
     return mpz_cmp (m_val, other.m_val) <= 0;
   }
 
-  bool operator< (int other) const
+  bool operator< (long other) const
   {
     return mpz_cmp_si (m_val, other) < 0;
   }
@@ -322,6 +328,28 @@ struct gdb_mpz
     return mpz_cmp_si (m_val, other) == 0;
   }
 
+  bool operator== (long other) const
+  {
+    return mpz_cmp_si (m_val, other) == 0;
+  }
+
+  bool operator== (unsigned long other) const
+  {
+    return mpz_cmp_ui (m_val, other) == 0;
+  }
+
+  template<typename T,
+	   typename = gdb::Requires<
+	     gdb::And<std::is_integral<T>,
+		      std::integral_constant<bool,
+					     (sizeof (T) > sizeof (long))>>
+	     >
+	   >
+  bool operator== (T src)
+  {
+    return *this == gdb_mpz (src);
+  }
+
   bool operator== (const gdb_mpz &other) const
   {
     return mpz_cmp (m_val, other.m_val) == 0;
@@ -612,4 +640,20 @@ gdb_mpz::as_integer () const
   return result;
 }
 
+/* See declaration above.  */
+
+template<typename T>
+T
+gdb_mpz::as_integer_truncate () const
+{
+  T result;
+
+  this->export_bits ({(gdb_byte *) &result, sizeof (result)},
+		     0 /* endian (0 = native) */,
+		     !std::is_signed<T>::value /* unsigned_p */,
+		     false /* safe */);
+
+  return result;
+}
+
 #endif

-- 
2.39.1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 2/6] Convert long_const_operation to use gdb_mpz
  2023-03-28 15:49 [PATCH 0/6] Add 128-bit integers to Ada and Rust parsers Tom Tromey
  2023-03-28 15:49 ` [PATCH 1/6] Additions to gdb_mpz Tom Tromey
@ 2023-03-28 15:49 ` Tom Tromey
  2023-03-28 15:49 ` [PATCH 3/6] Add 128-bit integer support to the Rust parser Tom Tromey
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Tom Tromey @ 2023-03-28 15:49 UTC (permalink / raw)
  To: gdb-patches

This changes long_const_operation to use gdb_mpz for its storage.
---
 gdb/ada-lang.c |  4 ++--
 gdb/ax-gdb.c   |  4 ++--
 gdb/expop.h    | 26 +++++++++++++++++++++++---
 gdb/expprint.c |  6 ++++++
 4 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 5301c72d514..e51fd082d73 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -10612,10 +10612,10 @@ ada_char_operation::replace (operation_up &&owner,
 
   if (context_type != nullptr && context_type->code () == TYPE_CODE_ENUM)
     {
+      LONGEST val = as_longest ();
       gdb_assert (result.get () == this);
       std::get<0> (m_storage) = context_type;
-      std::get<1> (m_storage)
-	= convert_char_literal (context_type, std::get<1> (m_storage));
+      std::get<1> (m_storage) = convert_char_literal (context_type, val);
     }
 
   return result;
diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c
index 1ed648ce002..9dda7fe524d 100644
--- a/gdb/ax-gdb.c
+++ b/gdb/ax-gdb.c
@@ -1630,8 +1630,8 @@ long_const_operation::do_generate_ax (struct expression *exp,
 				      struct axs_value *value,
 				      struct type *cast_type)
 {
-  gen_int_literal (ax, value, std::get<1> (m_storage),
-		   std::get<0> (m_storage));
+  LONGEST val = as_longest ();
+  gen_int_literal (ax, value, val, std::get<0> (m_storage));
 }
 
 void
diff --git a/gdb/expop.h b/gdb/expop.h
index d973d2314bb..854945c8688 100644
--- a/gdb/expop.h
+++ b/gdb/expop.h
@@ -274,6 +274,12 @@ check_objfile (ULONGEST val, struct objfile *objfile)
   return false;
 }
 
+static inline bool
+check_objfile (const gdb_mpz &val, struct objfile *objfile)
+{
+  return false;
+}
+
 template<typename T>
 static inline bool
 check_objfile (enum_flags<T> val, struct objfile *objfile)
@@ -319,6 +325,8 @@ extern void dump_for_expression (struct ui_file *stream, int depth,
 				 struct type *type);
 extern void dump_for_expression (struct ui_file *stream, int depth,
 				 CORE_ADDR addr);
+extern void dump_for_expression (struct ui_file *stream, int depth,
+				 const gdb_mpz &addr);
 extern void dump_for_expression (struct ui_file *stream, int depth,
 				 internalvar *ivar);
 extern void dump_for_expression (struct ui_file *stream, int depth,
@@ -468,6 +476,12 @@ check_constant (ULONGEST cst)
   return true;
 }
 
+static inline bool
+check_constant (const gdb_mpz &cst)
+{
+  return true;
+}
+
 static inline bool
 check_constant (struct symbol *sym)
 {
@@ -665,18 +679,21 @@ class var_value_operation
 };
 
 class long_const_operation
-  : public tuple_holding_operation<struct type *, LONGEST>
+  : public tuple_holding_operation<struct type *, gdb_mpz>
 {
 public:
 
   using tuple_holding_operation::tuple_holding_operation;
 
+  long_const_operation (struct type *type, LONGEST val)
+    : long_const_operation (type, gdb_mpz (val))
+  { }
+
   value *evaluate (struct type *expect_type,
 		   struct expression *exp,
 		   enum noside noside) override
   {
-    return value_from_longest (std::get<0> (m_storage),
-			       std::get<1> (m_storage));
+    return value_from_mpz (std::get<0> (m_storage), std::get<1> (m_storage));
   }
 
   enum exp_opcode opcode () const override
@@ -687,6 +704,9 @@ class long_const_operation
 
 protected:
 
+  LONGEST as_longest () const
+  { return std::get<1> (m_storage).as_integer_truncate<LONGEST> (); }
+
   void do_generate_ax (struct expression *exp,
 		       struct agent_expr *ax,
 		       struct axs_value *value,
diff --git a/gdb/expprint.c b/gdb/expprint.c
index 0c7cc754179..e0ec25573c2 100644
--- a/gdb/expprint.c
+++ b/gdb/expprint.c
@@ -108,6 +108,12 @@ dump_for_expression (struct ui_file *stream, int depth, CORE_ADDR addr)
 	      core_addr_to_string (addr));
 }
 
+void
+dump_for_expression (struct ui_file *stream, int depth, const gdb_mpz &val)
+{
+  gdb_printf (stream, _("%*sConstant: %s\n"), depth, "", val.str ().c_str ());
+}
+
 void
 dump_for_expression (struct ui_file *stream, int depth, internalvar *ivar)
 {

-- 
2.39.1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 3/6] Add 128-bit integer support to the Rust parser
  2023-03-28 15:49 [PATCH 0/6] Add 128-bit integers to Ada and Rust parsers Tom Tromey
  2023-03-28 15:49 ` [PATCH 1/6] Additions to gdb_mpz Tom Tromey
  2023-03-28 15:49 ` [PATCH 2/6] Convert long_const_operation to use gdb_mpz Tom Tromey
@ 2023-03-28 15:49 ` Tom Tromey
  2023-03-28 15:49 ` [PATCH 4/6] Add overload of fits_in_type Tom Tromey
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Tom Tromey @ 2023-03-28 15:49 UTC (permalink / raw)
  To: gdb-patches

This adds support for 128-bit integers to the Rust parser.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=21185
---
 gdb/rust-lang.c                         |  2 ++
 gdb/rust-parse.c                        | 37 ++++++++++++++++++++-------------
 gdb/testsuite/gdb.base/parse_number.exp |  7 ++++---
 gdb/testsuite/gdb.rust/onetwoeight.exp  |  4 ++++
 4 files changed, 33 insertions(+), 17 deletions(-)

diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c
index cb128f13f0e..3ef8fcaa329 100644
--- a/gdb/rust-lang.c
+++ b/gdb/rust-lang.c
@@ -1607,6 +1607,8 @@ rust_language::language_arch_info (struct gdbarch *gdbarch,
   add (init_integer_type (alloc, 32, 1, "u32"));
   add (init_integer_type (alloc, 64, 0, "i64"));
   add (init_integer_type (alloc, 64, 1, "u64"));
+  add (init_integer_type (alloc, 128, 0, "i128"));
+  add (init_integer_type (alloc, 128, 1, "u128"));
 
   unsigned int length = 8 * builtin->builtin_data_ptr->length ();
   add (init_integer_type (alloc, length, 0, "isize"));
diff --git a/gdb/rust-parse.c b/gdb/rust-parse.c
index eca98aa286f..6c7922de9c7 100644
--- a/gdb/rust-parse.c
+++ b/gdb/rust-parse.c
@@ -69,7 +69,7 @@ static const char number_regex_text[] =
 #define INT_TEXT 5
 #define INT_TYPE 6
   "(0x[a-fA-F0-9_]+|0o[0-7_]+|0b[01_]+|[0-9][0-9_]*)"
-  "([iu](size|8|16|32|64))?"
+  "([iu](size|8|16|32|64|128))?"
   ")";
 /* The number of subexpressions to allocate space for, including the
    "0th" whole match subexpression.  */
@@ -126,7 +126,7 @@ enum token_type : int
 
 struct typed_val_int
 {
-  ULONGEST val;
+  gdb_mpz val;
   struct type *type;
 };
 
@@ -1007,7 +1007,6 @@ rust_parser::lex_number ()
   /* Parse the number.  */
   if (is_integer)
     {
-      uint64_t value;
       int radix = 10;
       int offset = 0;
 
@@ -1026,14 +1025,22 @@ rust_parser::lex_number ()
 	    }
 	}
 
-      const char *trailer;
-      value = strtoulst (number.c_str () + offset, &trailer, radix);
-      if (*trailer != '\0')
-	error (_("Integer literal is too large"));
-      if (implicit_i32 && value >= ((uint64_t) 1) << 31)
-	type = get_type ("i64");
+      if (!current_int_val.val.set (number.c_str () + offset, radix))
+	{
+	  /* Shouldn't be possible.  */
+	  error (_("Invalid integer"));
+	}
+      if (implicit_i32)
+	{
+	  static gdb_mpz sixty_three_bit = gdb_mpz::pow (2, 63);
+	  static gdb_mpz thirty_one_bit = gdb_mpz::pow (2, 31);
+
+	  if (current_int_val.val >= sixty_three_bit)
+	    type = get_type ("i128");
+	  else if (current_int_val.val >= thirty_one_bit)
+	    type = get_type ("i64");
+	}
 
-      current_int_val.val = value;
       current_int_val.type = type;
     }
   else
@@ -1556,9 +1563,11 @@ rust_parser::parse_field (operation_up &&lhs)
       break;
 
     case DECIMAL_INTEGER:
-      result = make_operation<rust_struct_anon> (current_int_val.val,
-						 std::move (lhs));
-      lex ();
+      {
+	int idx = current_int_val.val.as_integer<int> ();
+	result = make_operation<rust_struct_anon> (idx, std::move (lhs));
+	lex ();
+      }
       break;
 
     case INTEGER:
@@ -1659,7 +1668,7 @@ rust_parser::parse_array_type ()
 
   if (current_token != INTEGER && current_token != DECIMAL_INTEGER)
     error (_("integer expected"));
-  ULONGEST val = current_int_val.val;
+  ULONGEST val = current_int_val.val.as_integer<ULONGEST> ();
   lex ();
   require (']');
 
diff --git a/gdb/testsuite/gdb.base/parse_number.exp b/gdb/testsuite/gdb.base/parse_number.exp
index 07104433a16..5dd4fa705e9 100644
--- a/gdb/testsuite/gdb.base/parse_number.exp
+++ b/gdb/testsuite/gdb.base/parse_number.exp
@@ -108,9 +108,10 @@ proc parse_number { lang n } {
 	    return [list "i32" $n]
 	} elseif { [fits_in_type $n 64 s] } {
 	    return [list "i64" $n]
-	} elseif { [fits_in_type $n 64 u] } {
-	    # Note: Interprets MAX_U64 as -1.
-	    return [list "i64" $n]
+	} elseif { [fits_in_type $n 128 u] } {
+	    return [list "i128" $n]
+	} elseif { [fits_in_type $n 128 u] } {
+	    return [list "i128" $n]
 	} else {
 	    # Overflow.
 	    return [list $re_overflow $re_overflow]
diff --git a/gdb/testsuite/gdb.rust/onetwoeight.exp b/gdb/testsuite/gdb.rust/onetwoeight.exp
index ef56bcafda2..5ca30712830 100644
--- a/gdb/testsuite/gdb.rust/onetwoeight.exp
+++ b/gdb/testsuite/gdb.rust/onetwoeight.exp
@@ -64,3 +64,7 @@ gdb_test "print x >> 2" "= 85070591730234615865843651857942052863"
 gdb_test "print/x x & mask" " = 0xf0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0"
 gdb_test "print/x x ^ mask" " = 0xf0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f"
 gdb_test "print/x mask | (mask >> 4)" " = 0xffffffffffffffffffffffffffffffff"
+
+gdb_test "print 170141183460469231731687303715884105727" \
+    " = 170141183460469231731687303715884105727"
+gdb_test "ptype 23i128" "type = i128"

-- 
2.39.1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 4/6] Add overload of fits_in_type
  2023-03-28 15:49 [PATCH 0/6] Add 128-bit integers to Ada and Rust parsers Tom Tromey
                   ` (2 preceding siblings ...)
  2023-03-28 15:49 ` [PATCH 3/6] Add 128-bit integer support to the Rust parser Tom Tromey
@ 2023-03-28 15:49 ` Tom Tromey
  2023-03-28 15:49 ` [PATCH 5/6] Remove some Ada parser helper functions Tom Tromey
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Tom Tromey @ 2023-03-28 15:49 UTC (permalink / raw)
  To: gdb-patches

This adds an overload of fits_in_type that accepts a gdb_mpz.  A
subsequent patch will use this.
---
 gdb/parse.c       | 26 ++++++++++++++++++++++++++
 gdb/parser-defs.h |  2 ++
 2 files changed, 28 insertions(+)

diff --git a/gdb/parse.c b/gdb/parse.c
index 24db3ca57d9..23545e32160 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -648,6 +648,32 @@ fits_in_type (int n_sign, ULONGEST n, int type_bits, bool type_signed_p)
   else
     gdb_assert_not_reached ("");
 }
+
+/* Return true if the number N_SIGN * N fits in a type with TYPE_BITS and
+   TYPE_SIGNED_P.  N_SIGNED is either 1 or -1.  */
+
+bool
+fits_in_type (int n_sign, const gdb_mpz &n, int type_bits, bool type_signed_p)
+{
+  /* N must be nonnegative.  */
+  gdb_assert (n.sgn () >= 0);
+
+  /* Zero always fits.  */
+  /* Normalize -0.  */
+  if (n.sgn () == 0)
+    return true;
+
+  if (n_sign == -1 && !type_signed_p)
+    /* Can't fit a negative number in an unsigned type.  */
+    return false;
+
+  gdb_mpz max = gdb_mpz::pow (2, (type_signed_p
+				  ? type_bits - 1
+				  : type_bits));
+  if (n_sign == -1)
+    return n <= max;
+  return n < max;
+}
 \f
 /* This function avoids direct calls to fprintf 
    in the parser generated debug code.  */
diff --git a/gdb/parser-defs.h b/gdb/parser-defs.h
index 1780d856744..62829a86f9a 100644
--- a/gdb/parser-defs.h
+++ b/gdb/parser-defs.h
@@ -414,6 +414,8 @@ extern bool parse_float (const char *p, int len,
 			 const struct type *type, gdb_byte *data);
 extern bool fits_in_type (int n_sign, ULONGEST n, int type_bits,
 			  bool type_signed_p);
+extern bool fits_in_type (int n_sign, const gdb_mpz &n, int type_bits,
+			  bool type_signed_p);
 \f
 
 /* Function used to avoid direct calls to fprintf

-- 
2.39.1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 5/6] Remove some Ada parser helper functions
  2023-03-28 15:49 [PATCH 0/6] Add 128-bit integers to Ada and Rust parsers Tom Tromey
                   ` (3 preceding siblings ...)
  2023-03-28 15:49 ` [PATCH 4/6] Add overload of fits_in_type Tom Tromey
@ 2023-03-28 15:49 ` Tom Tromey
  2023-03-28 15:49 ` [PATCH 6/6] Add 128-bit integer support to the Ada parser Tom Tromey
  2023-04-17 17:03 ` [PATCH 0/6] Add 128-bit integers to Ada and Rust parsers Tom Tromey
  6 siblings, 0 replies; 8+ messages in thread
From: Tom Tromey @ 2023-03-28 15:49 UTC (permalink / raw)
  To: gdb-patches

These helper functions in the Ada parser don't seem all that
worthwhile to me, so this patch removes them.
---
 gdb/ada-exp.y                           | 52 ++++++---------------------------
 gdb/ada-lex.l                           |  8 ++---
 gdb/testsuite/gdb.base/parse_number.exp |  2 ++
 3 files changed, 15 insertions(+), 47 deletions(-)

diff --git a/gdb/ada-exp.y b/gdb/ada-exp.y
index a9c37bedff0..4095106bb09 100644
--- a/gdb/ada-exp.y
+++ b/gdb/ada-exp.y
@@ -93,18 +93,8 @@ static const struct block *block_lookup (const struct block *, const char *);
 static void write_ambiguous_var (struct parser_state *,
 				 const struct block *, const char *, int);
 
-static struct type *type_int (struct parser_state *);
-
-static struct type *type_long (struct parser_state *);
-
-static struct type *type_long_long (struct parser_state *);
-
-static struct type *type_long_double (struct parser_state *);
-
 static struct type *type_for_char (struct parser_state *, ULONGEST);
 
-static struct type *type_boolean (struct parser_state *);
-
 static struct type *type_system_address (struct parser_state *);
 
 static std::string find_completion_bounds (struct parser_state *);
@@ -934,9 +924,15 @@ primary	:	STRING
 	;
 
 primary :	TRUEKEYWORD
-			{ write_int (pstate, 1, type_boolean (pstate)); }
+			{
+			  write_int (pstate, 1,
+				     parse_type (pstate)->builtin_bool);
+			}
 	|	FALSEKEYWORD
-			{ write_int (pstate, 0, type_boolean (pstate)); }
+			{
+			  write_int (pstate, 0,
+				     parse_type (pstate)->builtin_bool);
+			}
 	;
 
 primary	: 	NEW NAME
@@ -1268,7 +1264,7 @@ write_object_renaming (struct parser_state *par_state,
 	    if (next == renaming_expr)
 	      goto BadEncoding;
 	    renaming_expr = next;
-	    write_int (par_state, val, type_int (par_state));
+	    write_int (par_state, val, parse_type (par_state)->builtin_int);
 	  }
 	else
 	  {
@@ -1841,30 +1837,6 @@ write_name_assoc (struct parser_state *par_state, struct stoken name)
   push_association<ada_name_association> (ada_pop ());
 }
 
-static struct type *
-type_int (struct parser_state *par_state)
-{
-  return parse_type (par_state)->builtin_int;
-}
-
-static struct type *
-type_long (struct parser_state *par_state)
-{
-  return parse_type (par_state)->builtin_long;
-}
-
-static struct type *
-type_long_long (struct parser_state *par_state)
-{
-  return parse_type (par_state)->builtin_long_long;
-}
-
-static struct type *
-type_long_double (struct parser_state *par_state)
-{
-  return parse_type (par_state)->builtin_long_double;
-}
-
 static struct type *
 type_for_char (struct parser_state *par_state, ULONGEST value)
 {
@@ -1880,12 +1852,6 @@ type_for_char (struct parser_state *par_state, ULONGEST value)
 					 "wide_wide_character");
 }
 
-static struct type *
-type_boolean (struct parser_state *par_state)
-{
-  return parse_type (par_state)->builtin_bool;
-}
-
 static struct type *
 type_system_address (struct parser_state *par_state)
 {
diff --git a/gdb/ada-lex.l b/gdb/ada-lex.l
index 69fc14f7107..0634f337cb2 100644
--- a/gdb/ada-lex.l
+++ b/gdb/ada-lex.l
@@ -471,9 +471,9 @@ processInt (struct parser_state *par_state, const char *base0,
 
   ULONGEST value = result.as_integer<ULONGEST> ();
   if (fits_in_type (1, value, int_bits, true))
-    yylval.typed_val.type = type_int (par_state);
+    yylval.typed_val.type = parse_type (par_state)->builtin_int;
   else if (fits_in_type (1, value, long_bits, true))
-    yylval.typed_val.type = type_long (par_state);
+    yylval.typed_val.type = parse_type (par_state)->builtin_long;
   else if (fits_in_type (1, value, long_bits, false))
     {
       /* We have a number representable as an unsigned integer quantity.
@@ -494,7 +494,7 @@ processInt (struct parser_state *par_state, const char *base0,
       return INT;
     }
   else if (fits_in_type (1, value, long_long_bits, true))
-    yylval.typed_val.type = type_long_long (par_state);
+    yylval.typed_val.type = parse_type (par_state)->builtin_long_long;
   else if (fits_in_type (1, value, long_long_bits, false))
     {
       yylval.typed_val.type
@@ -518,7 +518,7 @@ processInt (struct parser_state *par_state, const char *base0,
 static int
 processReal (struct parser_state *par_state, const char *num0)
 {
-  yylval.typed_val_float.type = type_long_double (par_state);
+  yylval.typed_val_float.type = parse_type (par_state)->builtin_long_double;
 
   bool parsed = parse_float (num0, strlen (num0),
 			     yylval.typed_val_float.type,
diff --git a/gdb/testsuite/gdb.base/parse_number.exp b/gdb/testsuite/gdb.base/parse_number.exp
index 5dd4fa705e9..8800dead53b 100644
--- a/gdb/testsuite/gdb.base/parse_number.exp
+++ b/gdb/testsuite/gdb.base/parse_number.exp
@@ -145,6 +145,8 @@ proc parse_number { lang n } {
 	} elseif { [fits_in_type $n $long_long_bits u] } {
 	    # Note: Interprets ULLONG_MAX as -1.
 	    return [list "<$sizeof_long_long-byte integer>" $n]
+	} elseif { [fits_in_type $n 128 u] } {
+	    return [list "<16-byte integer>" $n]
 	} else {
 	    # Overflow.
 	    return [list $re_overflow $re_overflow]

-- 
2.39.1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 6/6] Add 128-bit integer support to the Ada parser
  2023-03-28 15:49 [PATCH 0/6] Add 128-bit integers to Ada and Rust parsers Tom Tromey
                   ` (4 preceding siblings ...)
  2023-03-28 15:49 ` [PATCH 5/6] Remove some Ada parser helper functions Tom Tromey
@ 2023-03-28 15:49 ` Tom Tromey
  2023-04-17 17:03 ` [PATCH 0/6] Add 128-bit integers to Ada and Rust parsers Tom Tromey
  6 siblings, 0 replies; 8+ messages in thread
From: Tom Tromey @ 2023-03-28 15:49 UTC (permalink / raw)
  To: gdb-patches

This adds support for 128-bit integers to the Ada parser.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30188
---
 gdb/ada-exp.y                      | 22 ++++++++++---
 gdb/ada-lang.c                     |  2 ++
 gdb/ada-lex.l                      | 67 ++++++++++++++------------------------
 gdb/testsuite/gdb.ada/verylong.exp |  5 +++
 4 files changed, 50 insertions(+), 46 deletions(-)

diff --git a/gdb/ada-exp.y b/gdb/ada-exp.y
index 4095106bb09..3e31d275046 100644
--- a/gdb/ada-exp.y
+++ b/gdb/ada-exp.y
@@ -68,6 +68,11 @@ static struct parser_state *pstate = NULL;
 /* The original expression string.  */
 static const char *original_expr;
 
+/* We don't have a good way to manage non-POD data in Yacc, so store
+   values here.  The storage here is only valid for the duration of
+   the parse.  */
+static std::vector<std::unique_ptr<gdb_mpz>> int_storage;
+
 int yyparse (void);
 
 static int yylex (void);
@@ -416,9 +421,13 @@ make_tick_completer (struct stoken tok)
   {
     LONGEST lval;
     struct {
-      LONGEST val;
+      const gdb_mpz *val;
       struct type *type;
     } typed_val;
+    struct {
+      LONGEST val;
+      struct type *type;
+    } typed_char;
     struct {
       gdb_byte val[16];
       struct type *type;
@@ -433,7 +442,8 @@ make_tick_completer (struct stoken tok)
 %type <lval> aggregate_component_list 
 %type <tval> var_or_type type_prefix opt_type_prefix
 
-%token <typed_val> INT NULL_PTR CHARLIT
+%token <typed_val> INT NULL_PTR
+%token <typed_char> CHARLIT
 %token <typed_val_float> FLOAT
 %token TRUEKEYWORD FALSEKEYWORD
 %token COLONCOLON
@@ -867,7 +877,7 @@ primary :	primary TICK_ACCESS
 tick_arglist :			%prec '('
 			{ $$ = 1; }
 	| 	'(' INT ')'
-			{ $$ = $2.val; }
+			{ $$ = $2.val->as_integer<LONGEST> (); }
 	;
 
 type_prefix :
@@ -888,7 +898,10 @@ opt_type_prefix :
 
 
 primary	:	INT
-			{ write_int (pstate, (LONGEST) $1.val, $1.type); }
+			{
+			  pstate->push_new<long_const_operation> ($1.type, *$1.val);
+			  ada_wrap<ada_wrapped_operation> ();
+			}
 	;
 
 primary	:	CHARLIT
@@ -1144,6 +1157,7 @@ ada_parse (struct parser_state *par_state)
   obstack_init (&temp_parse_space);
   components.clear ();
   associations.clear ();
+  int_storage.clear ();
 
   int result = yyparse ();
   if (!result)
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index e51fd082d73..9c683888ade 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -13566,6 +13566,8 @@ class ada_language : public language_defn
 			  "long_float", gdbarch_double_format (gdbarch)));
     add (init_integer_type (alloc, gdbarch_long_long_bit (gdbarch),
 			    0, "long_long_integer"));
+    add (init_integer_type (alloc, 128, 0, "long_long_long_integer"));
+    add (init_integer_type (alloc, 128, 1, "unsigned_long_long_long_integer"));
     add (init_float_type (alloc, gdbarch_long_double_bit (gdbarch),
 			  "long_long_float",
 			  gdbarch_long_double_format (gdbarch)));
diff --git a/gdb/ada-lex.l b/gdb/ada-lex.l
index 0634f337cb2..f2af21292f4 100644
--- a/gdb/ada-lex.l
+++ b/gdb/ada-lex.l
@@ -179,15 +179,15 @@ static int paren_depth;
 		}
 
 <INITIAL>"'"({GRAPHIC}|\")"'" {
-		   yylval.typed_val.val = yytext[1];
-		   yylval.typed_val.type = type_for_char (pstate, yytext[1]);
+		   yylval.typed_char.val = yytext[1];
+		   yylval.typed_char.type = type_for_char (pstate, yytext[1]);
 		   return CHARLIT;
 		}
 
 <INITIAL>"'[\""{HEXDIG}{2,}"\"]'"   {
                    ULONGEST v = strtoulst (yytext+3, nullptr, 16);
-		   yylval.typed_val.val = v;
-                   yylval.typed_val.type = type_for_char (pstate, v);
+		   yylval.typed_char.val = v;
+                   yylval.typed_char.type = type_for_char (pstate, v);
 		   return CHARLIT;
 		}
 
@@ -462,52 +462,35 @@ processInt (struct parser_state *par_state, const char *base0,
       return FLOAT;
     }
 
-  if (result > gdb_mpz (ULONGEST_MAX))
-    error (_("Integer literal out of range"));
+  int_storage.emplace_back (new gdb_mpz (std::move (result)));
+  const gdb_mpz *value = int_storage.back ().get ();
 
   int int_bits = gdbarch_int_bit (par_state->gdbarch ());
   int long_bits = gdbarch_long_bit (par_state->gdbarch ());
   int long_long_bits = gdbarch_long_long_bit (par_state->gdbarch ());
 
-  ULONGEST value = result.as_integer<ULONGEST> ();
-  if (fits_in_type (1, value, int_bits, true))
+  if (fits_in_type (1, *value, int_bits, true))
     yylval.typed_val.type = parse_type (par_state)->builtin_int;
-  else if (fits_in_type (1, value, long_bits, true))
+  else if (fits_in_type (1, *value, long_bits, true))
     yylval.typed_val.type = parse_type (par_state)->builtin_long;
-  else if (fits_in_type (1, value, long_bits, false))
-    {
-      /* We have a number representable as an unsigned integer quantity.
-         For consistency with the C treatment, we will treat it as an
-	 anonymous modular (unsigned) quantity.  Alas, the types are such
-	 that we need to store .val as a signed quantity.  Sorry
-         for the mess, but C doesn't officially guarantee that a simple
-         assignment does the trick (no, it doesn't; read the reference manual).
-       */
-      yylval.typed_val.type
-	= builtin_type (par_state->gdbarch ())->builtin_unsigned_long;
-      if (value & LONGEST_SIGN)
-	yylval.typed_val.val =
-	  (LONGEST) (value & ~LONGEST_SIGN)
-	  - (LONGEST_SIGN>>1) - (LONGEST_SIGN>>1);
-      else
-	yylval.typed_val.val = (LONGEST) value;
-      return INT;
-    }
-  else if (fits_in_type (1, value, long_long_bits, true))
+  else if (fits_in_type (1, *value, long_bits, false))
+    yylval.typed_val.type
+      = builtin_type (par_state->gdbarch ())->builtin_unsigned_long;
+  else if (fits_in_type (1, *value, long_long_bits, true))
     yylval.typed_val.type = parse_type (par_state)->builtin_long_long;
-  else if (fits_in_type (1, value, long_long_bits, false))
-    {
-      yylval.typed_val.type
-	= builtin_type (par_state->gdbarch ())->builtin_unsigned_long_long;
-      /* See unsigned long case above.  */
-      if (value & LONGEST_SIGN)
-	yylval.typed_val.val =
-	  (LONGEST) (value & ~LONGEST_SIGN)
-	  - (LONGEST_SIGN>>1) - (LONGEST_SIGN>>1);
-      else
-	yylval.typed_val.val = (LONGEST) value;
-      return INT;
-    }
+  else if (fits_in_type (1, *value, long_long_bits, false))
+    yylval.typed_val.type
+      = builtin_type (par_state->gdbarch ())->builtin_unsigned_long_long;
+  else if (fits_in_type (1, *value, 128, true))
+    yylval.typed_val.type
+      = language_lookup_primitive_type (par_state->language (),
+					par_state->gdbarch (),
+					"long_long_long_integer");
+  else if (fits_in_type (1, *value, 128, false))
+    yylval.typed_val.type
+      = language_lookup_primitive_type (par_state->language (),
+					par_state->gdbarch (),
+					"unsigned_long_long_long_integer");
   else
     error (_("Integer literal out of range"));
 
diff --git a/gdb/testsuite/gdb.ada/verylong.exp b/gdb/testsuite/gdb.ada/verylong.exp
index 93df785862b..c8ae63f744b 100644
--- a/gdb/testsuite/gdb.ada/verylong.exp
+++ b/gdb/testsuite/gdb.ada/verylong.exp
@@ -35,3 +35,8 @@ gdb_test "print x - x" " = 0"
 gdb_test "print x - 99 + 1" " = 170141183460469231731687303715884105629"
 gdb_test "print -x" " = -170141183460469231731687303715884105727"
 gdb_test "print +x" " = 170141183460469231731687303715884105727"
+
+gdb_test "print 170141183460469231731687303715884105727" \
+    " = 170141183460469231731687303715884105727"
+gdb_test "print x = 170141183460469231731687303715884105727" \
+    " = true"

-- 
2.39.1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 0/6] Add 128-bit integers to Ada and Rust parsers
  2023-03-28 15:49 [PATCH 0/6] Add 128-bit integers to Ada and Rust parsers Tom Tromey
                   ` (5 preceding siblings ...)
  2023-03-28 15:49 ` [PATCH 6/6] Add 128-bit integer support to the Ada parser Tom Tromey
@ 2023-04-17 17:03 ` Tom Tromey
  6 siblings, 0 replies; 8+ messages in thread
From: Tom Tromey @ 2023-04-17 17:03 UTC (permalink / raw)
  To: Tom Tromey via Gdb-patches; +Cc: Tom Tromey

>>>>> "Tom" == Tom Tromey via Gdb-patches <gdb-patches@sourceware.org> writes:

Tom> This series changes the Ada and Rust parser to support 128-bit types.
Tom> It would be reasonably easy to add this for C/C++ as well, following
Tom> the Ada model, but I haven't done this.

Tom> Regression tested on x86-64 Fedora 36.

I've rebased this (no changes needed) and re-regression tested it.
I am checking it in.

Tom

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2023-04-17 17:03 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-28 15:49 [PATCH 0/6] Add 128-bit integers to Ada and Rust parsers Tom Tromey
2023-03-28 15:49 ` [PATCH 1/6] Additions to gdb_mpz Tom Tromey
2023-03-28 15:49 ` [PATCH 2/6] Convert long_const_operation to use gdb_mpz Tom Tromey
2023-03-28 15:49 ` [PATCH 3/6] Add 128-bit integer support to the Rust parser Tom Tromey
2023-03-28 15:49 ` [PATCH 4/6] Add overload of fits_in_type Tom Tromey
2023-03-28 15:49 ` [PATCH 5/6] Remove some Ada parser helper functions Tom Tromey
2023-03-28 15:49 ` [PATCH 6/6] Add 128-bit integer support to the Ada parser Tom Tromey
2023-04-17 17:03 ` [PATCH 0/6] Add 128-bit integers to Ada and Rust parsers Tom Tromey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).