public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [RFA 5/6] Remove rust_type_alignment
  2018-04-24 15:22 [RFA 0/6] Teach gdb about type alignment Tom Tromey
@ 2018-04-24 15:22 ` Tom Tromey
  2018-04-24 15:22 ` [RFA 3/6] Reindent type_object_getset in py-type.c Tom Tromey
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 22+ messages in thread
From: Tom Tromey @ 2018-04-24 15:22 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

rust_type_alignment is not needed now that gdb has type alignment
code.  So, this removes it.

2018-04-24  Tom Tromey  <tom@tromey.com>

	* rust-lang.c (rust_type_alignment): Remove.
	(rust_composite_type): Use type_align.
---
 gdb/ChangeLog   |  5 +++++
 gdb/rust-lang.c | 43 +------------------------------------------
 2 files changed, 6 insertions(+), 42 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 78acc26f4a..04920fbc4b 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,8 @@
+2018-04-24  Tom Tromey  <tom@tromey.com>
+
+	* rust-lang.c (rust_type_alignment): Remove.
+	(rust_composite_type): Use type_align.
+
 2018-04-24  Tom Tromey  <tom@tromey.com>
 
 	* NEWS: Mention Type.align.
diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c
index cf8a15ee43..74e86d7008 100644
--- a/gdb/rust-lang.c
+++ b/gdb/rust-lang.c
@@ -851,47 +851,6 @@ rust_print_type (struct type *type, const char *varstring,
 
 \f
 
-/* Compute the alignment of the type T.  */
-
-static int
-rust_type_alignment (struct type *t)
-{
-  t = check_typedef (t);
-  switch (TYPE_CODE (t))
-    {
-    default:
-      error (_("Could not compute alignment of type"));
-
-    case TYPE_CODE_PTR:
-    case TYPE_CODE_ENUM:
-    case TYPE_CODE_INT:
-    case TYPE_CODE_FLT:
-    case TYPE_CODE_REF:
-    case TYPE_CODE_CHAR:
-    case TYPE_CODE_BOOL:
-      return TYPE_LENGTH (t);
-
-    case TYPE_CODE_ARRAY:
-    case TYPE_CODE_COMPLEX:
-      return rust_type_alignment (TYPE_TARGET_TYPE (t));
-
-    case TYPE_CODE_STRUCT:
-    case TYPE_CODE_UNION:
-      {
-	int i;
-	int align = 1;
-
-	for (i = 0; i < TYPE_NFIELDS (t); ++i)
-	  {
-	    int a = rust_type_alignment (TYPE_FIELD_TYPE (t, i));
-	    if (a > align)
-	      align = a;
-	  }
-	return align;
-      }
-    }
-}
-
 /* Like arch_composite_type, but uses TYPE to decide how to allocate
    -- either on an obstack or on a gdbarch.  */
 
@@ -934,7 +893,7 @@ rust_composite_type (struct type *original,
   if (field2 != NULL)
     {
       struct field *field = &TYPE_FIELD (result, i);
-      int align = rust_type_alignment (type2);
+      unsigned align = type_align (type2);
 
       if (align != 0)
 	{
-- 
2.14.3

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

* [RFA 3/6] Reindent type_object_getset in py-type.c
  2018-04-24 15:22 [RFA 0/6] Teach gdb about type alignment Tom Tromey
  2018-04-24 15:22 ` [RFA 5/6] Remove rust_type_alignment Tom Tromey
@ 2018-04-24 15:22 ` Tom Tromey
  2018-04-24 15:22 ` [RFA 2/6] Handle alignof and _Alignof Tom Tromey
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 22+ messages in thread
From: Tom Tromey @ 2018-04-24 15:22 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

I noticed that type_object_getset was indented incorrectly.  This
fixes it.

2018-04-24  Tom Tromey  <tom@tromey.com>

	* python/py-type.c (type_object_getset): Reindent.
---
 gdb/ChangeLog        |  4 ++++
 gdb/python/py-type.c | 18 +++++++++---------
 2 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 563aa517b8..98ea77816b 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,7 @@
+2018-04-24  Tom Tromey  <tom@tromey.com>
+
+	* python/py-type.c (type_object_getset): Reindent.
+
 2018-04-24  Tom Tromey  <tom@tromey.com>
 
 	PR exp/17095:
diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
index 8a948eeaa6..fcd6ed5621 100644
--- a/gdb/python/py-type.c
+++ b/gdb/python/py-type.c
@@ -1410,15 +1410,15 @@ gdbpy_initialize_types (void)
 
 static gdb_PyGetSetDef type_object_getset[] =
 {
-  { "code", typy_get_code, NULL,
-    "The code for this type.", NULL },
-  { "name", typy_get_name, NULL,
-    "The name for this type, or None.", NULL },
-  { "sizeof", typy_get_sizeof, NULL,
-    "The size of this type, in bytes.", NULL },
-  { "tag", typy_get_tag, NULL,
-    "The tag name for this type, or None.", NULL },
-  { NULL }
+ { "code", typy_get_code, NULL,
+   "The code for this type.", NULL },
+ { "name", typy_get_name, NULL,
+   "The name for this type, or None.", NULL },
+ { "sizeof", typy_get_sizeof, NULL,
+   "The size of this type, in bytes.", NULL },
+ { "tag", typy_get_tag, NULL,
+   "The tag name for this type, or None.", NULL },
+ { NULL }
 };
 
 static PyMethodDef type_object_methods[] =
-- 
2.14.3

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

* [RFA 6/6] Remove long_long_align_bit gdbarch attribute
  2018-04-24 15:22 [RFA 0/6] Teach gdb about type alignment Tom Tromey
                   ` (3 preceding siblings ...)
  2018-04-24 15:22 ` [RFA 1/6] Add initial type alignment support Tom Tromey
@ 2018-04-24 15:22 ` Tom Tromey
  2018-04-24 15:24   ` Tom Tromey
  2018-04-24 17:17   ` Anton Kolesov
  2018-04-24 15:22 ` [RFA 4/6] Expose type alignment on gdb.Type Tom Tromey
  5 siblings, 2 replies; 22+ messages in thread
From: Tom Tromey @ 2018-04-24 15:22 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This removes the long_long_align_bit gdbarch attribute in favor of
type_align.  This uncovered two possible issues.

First, arc-tdep.c claimed that long long alignment was 32 bits, but
gcc's arc.h says:

    #define ADJUST_FIELD_ALIGN(FIELD, TYPE, COMPUTED) \
    (TYPE_MODE (strip_array_types (TYPE)) == DFmode \
     ? MIN ((COMPUTED), 32) : (COMPUTED))

Here, DFmode means "double".  So, I've implemented arc_type_align
according to this.  I do not have a good way to test this.

Second, jit.c, the sole user of long_long_align_bit, was confusing
"long long" with uint64_t.  The relevant structure is defined in the
JIT API part of the manual as:

     struct jit_code_entry
     {
       struct jit_code_entry *next_entry;
       struct jit_code_entry *prev_entry;
       const char *symfile_addr;
       uint64_t symfile_size;
     };

I've changed this code to use uint64_t.

2018-04-24  Tom Tromey  <tom@tromey.com>

	* jit.c (jit_read_code_entry): Use type_align.
	* i386-tdep.c (i386_gdbarch_init): Don't call
	set_gdbarch_long_long_align_bit.
	* gdbarch.sh: Remove long_long_align_bit.
	* gdbarch.c, gdbarch.h: Rebuild.
	* arc-tdep.c (arc_type_align): New function.
	(arc_gdbarch_init): Use arc_type_align.  Don't call
	set_gdbarch_long_long_align_bit.
---
 gdb/ChangeLog   | 11 +++++++++++
 gdb/arc-tdep.c  | 15 ++++++++++++++-
 gdb/gdbarch.c   | 23 -----------------------
 gdb/gdbarch.h   |  6 ------
 gdb/gdbarch.sh  |  3 ---
 gdb/i386-tdep.c |  1 -
 gdb/jit.c       |  4 ++--
 7 files changed, 27 insertions(+), 36 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 04920fbc4b..5e59d4e647 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,14 @@
+2018-04-24  Tom Tromey  <tom@tromey.com>
+
+	* jit.c (jit_read_code_entry): Use type_align.
+	* i386-tdep.c (i386_gdbarch_init): Don't call
+	set_gdbarch_long_long_align_bit.
+	* gdbarch.sh: Remove long_long_align_bit.
+	* gdbarch.c, gdbarch.h: Rebuild.
+	* arc-tdep.c (arc_type_align): New function.
+	(arc_gdbarch_init): Use arc_type_align.  Don't call
+	set_gdbarch_long_long_align_bit.
+
 2018-04-24  Tom Tromey  <tom@tromey.com>
 
 	* rust-lang.c (rust_type_alignment): Remove.
diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index b0d51addd3..86cf522443 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -1957,6 +1957,19 @@ arc_tdesc_init (struct gdbarch_info info, const struct target_desc **tdesc,
   return TRUE;
 }
 
+/* Implement the type_align gdbarch function.  */
+
+static ULONGEST
+arc_type_align (struct gdbarch *gdbarch, struct type *type)
+{
+  type = check_typedef (type);
+
+  if (TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8)
+    return 4;
+
+  return TYPE_LENGTH (type);
+}
+
 /* Implement the "init" gdbarch method.  */
 
 static struct gdbarch *
@@ -1982,7 +1995,7 @@ arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_int_bit (gdbarch, 32);
   set_gdbarch_long_bit (gdbarch, 32);
   set_gdbarch_long_long_bit (gdbarch, 64);
-  set_gdbarch_long_long_align_bit (gdbarch, 32);
+  set_gdbarch_type_align (gdbarch, arc_type_align);
   set_gdbarch_float_bit (gdbarch, 32);
   set_gdbarch_float_format (gdbarch, floatformats_ieee_single);
   set_gdbarch_double_bit (gdbarch, 64);
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index dd7c89d948..82ac751913 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -175,7 +175,6 @@ struct gdbarch
   int int_bit;
   int long_bit;
   int long_long_bit;
-  int long_long_align_bit;
   int half_bit;
   const struct floatformat ** half_format;
   int float_bit;
@@ -389,7 +388,6 @@ gdbarch_alloc (const struct gdbarch_info *info,
   gdbarch->int_bit = 4*TARGET_CHAR_BIT;
   gdbarch->long_bit = 4*TARGET_CHAR_BIT;
   gdbarch->long_long_bit = 2*gdbarch->long_bit;
-  gdbarch->long_long_align_bit = 2*gdbarch->long_bit;
   gdbarch->half_bit = 2*TARGET_CHAR_BIT;
   gdbarch->float_bit = 4*TARGET_CHAR_BIT;
   gdbarch->double_bit = 8*TARGET_CHAR_BIT;
@@ -530,7 +528,6 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of int_bit, invalid_p == 0 */
   /* Skip verify of long_bit, invalid_p == 0 */
   /* Skip verify of long_long_bit, invalid_p == 0 */
-  /* Skip verify of long_long_align_bit, invalid_p == 0 */
   /* Skip verify of half_bit, invalid_p == 0 */
   if (gdbarch->half_format == 0)
     gdbarch->half_format = floatformats_ieee_half;
@@ -1165,9 +1162,6 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
   fprintf_unfiltered (file,
                       "gdbarch_dump: long_double_format = %s\n",
                       pformat (gdbarch->long_double_format));
-  fprintf_unfiltered (file,
-                      "gdbarch_dump: long_long_align_bit = %s\n",
-                      plongest (gdbarch->long_long_align_bit));
   fprintf_unfiltered (file,
                       "gdbarch_dump: long_long_bit = %s\n",
                       plongest (gdbarch->long_long_bit));
@@ -1638,23 +1632,6 @@ set_gdbarch_long_long_bit (struct gdbarch *gdbarch,
   gdbarch->long_long_bit = long_long_bit;
 }
 
-int
-gdbarch_long_long_align_bit (struct gdbarch *gdbarch)
-{
-  gdb_assert (gdbarch != NULL);
-  /* Skip verify of long_long_align_bit, invalid_p == 0 */
-  if (gdbarch_debug >= 2)
-    fprintf_unfiltered (gdb_stdlog, "gdbarch_long_long_align_bit called\n");
-  return gdbarch->long_long_align_bit;
-}
-
-void
-set_gdbarch_long_long_align_bit (struct gdbarch *gdbarch,
-                                 int long_long_align_bit)
-{
-  gdbarch->long_long_align_bit = long_long_align_bit;
-}
-
 int
 gdbarch_half_bit (struct gdbarch *gdbarch)
 {
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 3848ec50c7..b3a15c9898 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -147,12 +147,6 @@ extern void set_gdbarch_long_bit (struct gdbarch *gdbarch, int long_bit);
 extern int gdbarch_long_long_bit (struct gdbarch *gdbarch);
 extern void set_gdbarch_long_long_bit (struct gdbarch *gdbarch, int long_long_bit);
 
-/* Alignment of a long long or unsigned long long for the target
-   machine. */
-
-extern int gdbarch_long_long_align_bit (struct gdbarch *gdbarch);
-extern void set_gdbarch_long_long_align_bit (struct gdbarch *gdbarch, int long_long_align_bit);
-
 /* The ABI default bit-size and format for "half", "float", "double", and
    "long double".  These bit/format pairs should eventually be combined
    into a single object.  For the moment, just initialize them as a pair.
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index bb62e6d620..bf12c68487 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -360,9 +360,6 @@ v;int;long_bit;;;8 * sizeof (long);4*TARGET_CHAR_BIT;;0
 # Number of bits in a long long or unsigned long long for the target
 # machine.
 v;int;long_long_bit;;;8 * sizeof (LONGEST);2*gdbarch->long_bit;;0
-# Alignment of a long long or unsigned long long for the target
-# machine.
-v;int;long_long_align_bit;;;8 * sizeof (LONGEST);2*gdbarch->long_bit;;0
 
 # The ABI default bit-size and format for "half", "float", "double", and
 # "long double".  These bit/format pairs should eventually be combined
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index e1938304bb..9b6a770a7a 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -8431,7 +8431,6 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   tdep->record_regmap = i386_record_regmap;
 
-  set_gdbarch_long_long_align_bit (gdbarch, 32);
   set_gdbarch_type_align (gdbarch, i386_type_align);
 
   /* The format used for `long double' on almost all i386 targets is
diff --git a/gdb/jit.c b/gdb/jit.c
index 2f23c058a0..8cd645cb66 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -413,8 +413,8 @@ jit_read_code_entry (struct gdbarch *gdbarch,
   ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
   ptr_size = TYPE_LENGTH (ptr_type);
 
-  /* Figure out where the longlong value will be.  */
-  align_bytes = gdbarch_long_long_align_bit (gdbarch) / 8;
+  /* Figure out where the uint64_t value will be.  */
+  align_bytes = type_align (builtin_type (gdbarch)->builtin_uint64);
   off = 3 * ptr_size;
   off = (off + (align_bytes - 1)) & ~(align_bytes - 1);
 
-- 
2.14.3

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

* [RFA 1/6] Add initial type alignment support
  2018-04-24 15:22 [RFA 0/6] Teach gdb about type alignment Tom Tromey
                   ` (2 preceding siblings ...)
  2018-04-24 15:22 ` [RFA 2/6] Handle alignof and _Alignof Tom Tromey
@ 2018-04-24 15:22 ` Tom Tromey
  2018-04-24 19:16   ` Pedro Alves
  2018-04-24 15:22 ` [RFA 6/6] Remove long_long_align_bit gdbarch attribute Tom Tromey
  2018-04-24 15:22 ` [RFA 4/6] Expose type alignment on gdb.Type Tom Tromey
  5 siblings, 1 reply; 22+ messages in thread
From: Tom Tromey @ 2018-04-24 15:22 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This adds some basic type alignment support to gdb.  It changes struct
type to store the alignment, and updates dwarf2read.c to handle
DW_AT_alignment.  It also adds a new gdbarch method and updates
i386-tdep.c.

None of this new functionality is used anywhere yet, so tests will
wait until the next patch.

2018-04-24  Tom Tromey  <tom@tromey.com>

	* i386-tdep.c (i386_type_align): New function.
	(i386_gdbarch_init): Update.
	* gdbarch.sh (type_align): New method.
	* gdbarch.c, gdbarch.h: Rebuild.
	* arch-utils.h (default_type_align): Declare.
	* arch-utils.c (default_type_align): New function.
	* gdbtypes.h (TYPE_ALIGN_BITS): New define.
	(struct type) <align_log2>: New field.
	<instance_flags>: Now a bitfield.
	(TYPE_RAW_ALIGN): New macro.
	(type_align, type_raw_align, set_type_align): Declare.
	* gdbtypes.c (type_align, type_raw_align, set_type_align): New
	functions.
	* dwarf2read.c (quirk_rust_enum): Set type alignment.
	(get_alignment, maybe_set_alignment): New functions.
	(read_structure_type, read_enumeration_type, read_array_type)
	(read_set_type, read_tag_pointer_type, read_tag_reference_type)
	(read_subrange_type, read_base_type): Set type alignment.
---
 gdb/ChangeLog    |  21 ++++++++++
 gdb/arch-utils.c |   8 ++++
 gdb/arch-utils.h |   4 ++
 gdb/dwarf2read.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 gdb/gdbarch.c    |  23 +++++++++++
 gdb/gdbarch.h    |   6 +++
 gdb/gdbarch.sh   |   3 ++
 gdb/gdbtypes.c   | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/gdbtypes.h   |  34 +++++++++++++++-
 gdb/i386-tdep.c  |  28 +++++++++++++
 10 files changed, 358 insertions(+), 5 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 0db5c46f6c..94d166e310 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,24 @@
+2018-04-24  Tom Tromey  <tom@tromey.com>
+
+	* i386-tdep.c (i386_type_align): New function.
+	(i386_gdbarch_init): Update.
+	* gdbarch.sh (type_align): New method.
+	* gdbarch.c, gdbarch.h: Rebuild.
+	* arch-utils.h (default_type_align): Declare.
+	* arch-utils.c (default_type_align): New function.
+	* gdbtypes.h (TYPE_ALIGN_BITS): New define.
+	(struct type) <align_log2>: New field.
+	<instance_flags>: Now a bitfield.
+	(TYPE_RAW_ALIGN): New macro.
+	(type_align, type_raw_align, set_type_align): Declare.
+	* gdbtypes.c (type_align, type_raw_align, set_type_align): New
+	functions.
+	* dwarf2read.c (quirk_rust_enum): Set type alignment.
+	(get_alignment, maybe_set_alignment): New functions.
+	(read_structure_type, read_enumeration_type, read_array_type)
+	(read_set_type, read_tag_pointer_type, read_tag_reference_type)
+	(read_subrange_type, read_base_type): Set type alignment.
+
 2018-04-19  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
 
 	* thread.c (thread_apply_all_command): Fix comment.
diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c
index cd9bd66430..e3cce491ee 100644
--- a/gdb/arch-utils.c
+++ b/gdb/arch-utils.c
@@ -987,6 +987,14 @@ default_in_indirect_branch_thunk (gdbarch *gdbarch, CORE_ADDR pc)
   return false;
 }
 
+/* See arch-utils.h.  */
+
+ULONGEST
+default_type_align (struct gdbarch *gdbarch, struct type *type)
+{
+  return TYPE_LENGTH (check_typedef (type));
+}
+
 void
 _initialize_gdbarch_utils (void)
 {
diff --git a/gdb/arch-utils.h b/gdb/arch-utils.h
index b785b24643..77ee9af2bf 100644
--- a/gdb/arch-utils.h
+++ b/gdb/arch-utils.h
@@ -267,4 +267,8 @@ extern CORE_ADDR gdbarch_skip_prologue_noexcept (gdbarch *gdbarch,
 extern bool default_in_indirect_branch_thunk (gdbarch *gdbarch,
 					      CORE_ADDR pc);
 
+/* Default implementation of gdbarch type_align method.  */
+extern ULONGEST default_type_align (struct gdbarch *gdbarch,
+				    struct type *type);
+
 #endif
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 4207e4c531..0ca055675f 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -9907,6 +9907,7 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
       TYPE_FIELDS (union_type)
 	= (struct field *) TYPE_ZALLOC (type, 3 * sizeof (struct field));
       TYPE_LENGTH (union_type) = TYPE_LENGTH (type);
+      set_type_align (union_type, TYPE_RAW_ALIGN (type));
 
       /* Put the discriminant must at index 0.  */
       TYPE_FIELD_TYPE (union_type, 0) = field_type;
@@ -9962,6 +9963,7 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
       TYPE_CODE (union_type) = TYPE_CODE_UNION;
       TYPE_NFIELDS (union_type) = TYPE_NFIELDS (type);
       TYPE_LENGTH (union_type) = TYPE_LENGTH (type);
+      set_type_align (union_type, TYPE_RAW_ALIGN (type));
       TYPE_FIELDS (union_type) = TYPE_FIELDS (type);
 
       struct type *field_type = TYPE_FIELD_TYPE (union_type, 0);
@@ -10027,6 +10029,7 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
       TYPE_CODE (union_type) = TYPE_CODE_UNION;
       TYPE_NFIELDS (union_type) = 1 + TYPE_NFIELDS (type);
       TYPE_LENGTH (union_type) = TYPE_LENGTH (type);
+      set_type_align (union_type, TYPE_RAW_ALIGN (type));
       TYPE_FIELDS (union_type)
 	= (struct field *) TYPE_ZALLOC (union_type,
 					(TYPE_NFIELDS (union_type)
@@ -15578,6 +15581,82 @@ quirk_gcc_member_function_pointer (struct type *type, struct objfile *objfile)
   smash_to_methodptr_type (type, new_type);
 }
 
+/* If the DIE has a DW_AT_alignment attribute, return its value, doing
+   appropriate error checking and issuing complaints if there is a
+   problem.  */
+
+static ULONGEST
+get_alignment (struct dwarf2_cu *cu, struct die_info *die)
+{
+  struct attribute *attr = dwarf2_attr (die, DW_AT_alignment, cu);
+
+  if (attr == nullptr)
+    return 0;
+
+  if (!attr_form_is_constant (attr))
+    {
+      complaint (&symfile_complaints,
+		 _("DW_AT_alignment must have constant form"
+		   " - DIE at %s [in module %s]"),
+		 sect_offset_str (die->sect_off),
+		 objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
+      return 0;
+    }
+
+  ULONGEST align;
+  if (attr->form == DW_FORM_sdata)
+    {
+      LONGEST val = DW_SND (attr);
+      if (val < 0)
+	{
+	  complaint (&symfile_complaints,
+		     _("DW_AT_alignment value must not be negative"
+		       " - DIE at %s [in module %s]"),
+		     sect_offset_str (die->sect_off),
+		     objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
+	  return 0;
+	}
+      align = val;
+    }
+  else
+    align = DW_UNSND (attr);
+
+  if (align == 0)
+    {
+      complaint (&symfile_complaints,
+		 _("DW_AT_alignment value must not be zero"
+		   " - DIE at %s [in module %s]"),
+		 sect_offset_str (die->sect_off),
+		 objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
+      return 0;
+    }
+  if ((align & (align - 1)) != 0)
+    {
+      complaint (&symfile_complaints,
+		 _("DW_AT_alignment value must be a power of 2"
+		   " - DIE at %s [in module %s]"),
+		 sect_offset_str (die->sect_off),
+		 objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
+      return 0;
+    }
+
+  return align;
+}
+
+/* If the DIE has a DW_AT_alignment attribute, use its value to set
+   the alignment for TYPE.  */
+
+static void
+maybe_set_alignment (struct dwarf2_cu *cu, struct die_info *die,
+		     struct type *type)
+{
+  if (!set_type_align (type, get_alignment (cu, die)))
+    complaint (&symfile_complaints,
+	       _("DW_AT_alignment value too large"
+		 " - DIE at %s [in module %s]"),
+	       sect_offset_str (die->sect_off),
+	       objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
+}
 
 /* Called when we find the DIE that starts a structure or union scope
    (definition) to create a type for the structure or union.  Fill in
@@ -15688,6 +15767,8 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
       TYPE_LENGTH (type) = 0;
     }
 
+  maybe_set_alignment (cu, die, type);
+
   if (producer_is_icc_lt_14 (cu) && (TYPE_LENGTH (type) == 0))
     {
       /* ICC<14 does not output the required DW_AT_declaration on
@@ -16132,6 +16213,8 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
       TYPE_LENGTH (type) = 0;
     }
 
+  maybe_set_alignment (cu, die, type);
+
   /* The enumeration DIE can be incomplete.  In Ada, any type can be
      declared as private in the package spec, and then defined only
      inside the package body.  Such types are known as Taft Amendment
@@ -16157,6 +16240,9 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
       TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TYPE_TARGET_TYPE (type));
       if (TYPE_LENGTH (type) == 0)
 	TYPE_LENGTH (type) = TYPE_LENGTH (TYPE_TARGET_TYPE (type));
+      if (TYPE_RAW_ALIGN (type) == 0
+	  && TYPE_RAW_ALIGN (TYPE_TARGET_TYPE (type)) != 0)
+	set_type_align (type, TYPE_RAW_ALIGN (TYPE_TARGET_TYPE (type)));
     }
 
   TYPE_DECLARED_CLASS (type) = dwarf2_flag_true_p (die, DW_AT_enum_class, cu);
@@ -16381,6 +16467,8 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu)
   if (name)
     TYPE_NAME (type) = name;
 
+  maybe_set_alignment (cu, die, type);
+
   /* Install the type in the die.  */
   set_die_type (die, type, cu);
 
@@ -16445,6 +16533,8 @@ read_set_type (struct die_info *die, struct dwarf2_cu *cu)
   if (attr)
     TYPE_LENGTH (set_type) = DW_UNSND (attr);
 
+  maybe_set_alignment (cu, die, set_type);
+
   return set_die_type (die, set_type, cu);
 }
 
@@ -16816,10 +16906,15 @@ read_tag_pointer_type (struct die_info *die, struct dwarf2_cu *cu)
   else
     addr_class = DW_ADDR_none;
 
-  /* If the pointer size or address class is different than the
-     default, create a type variant marked as such and set the
-     length accordingly.  */
-  if (TYPE_LENGTH (type) != byte_size || addr_class != DW_ADDR_none)
+  ULONGEST alignment = get_alignment (cu, die);
+
+  /* If the pointer size, alignment, or address class is different
+     than the default, create a type variant marked as such and set
+     the length accordingly.  */
+  if (TYPE_LENGTH (type) != byte_size
+      || (alignment != 0 && TYPE_RAW_ALIGN (type) != 0
+	  && alignment != TYPE_RAW_ALIGN (type))
+      || addr_class != DW_ADDR_none)
     {
       if (gdbarch_address_class_type_flags_p (gdbarch))
 	{
@@ -16836,6 +16931,14 @@ read_tag_pointer_type (struct die_info *die, struct dwarf2_cu *cu)
 	  complaint (&symfile_complaints,
 		     _("invalid pointer size %d"), byte_size);
 	}
+      else if (TYPE_RAW_ALIGN (type) != alignment)
+	{
+	  complaint (&symfile_complaints,
+		     _("Invalid DW_AT_alignment"
+		       " - DIE at %s [in module %s]"),
+		     sect_offset_str (die->sect_off),
+		     objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
+	}
       else
 	{
 	  /* Should we also complain about unhandled address classes?  */
@@ -16843,6 +16946,7 @@ read_tag_pointer_type (struct die_info *die, struct dwarf2_cu *cu)
     }
 
   TYPE_LENGTH (type) = byte_size;
+  set_type_align (type, alignment);
   return set_die_type (die, type, cu);
 }
 
@@ -16912,6 +17016,7 @@ read_tag_reference_type (struct die_info *die, struct dwarf2_cu *cu,
     {
       TYPE_LENGTH (type) = cu_header->addr_size;
     }
+  maybe_set_alignment (cu, die, type);
   return set_die_type (die, type, cu);
 }
 
@@ -17398,6 +17503,8 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
   if (name && strcmp (name, "char") == 0)
     TYPE_NOSIGN (type) = 1;
 
+  maybe_set_alignment (cu, die, type);
+
   return set_die_type (die, type, cu);
 }
 
@@ -17660,6 +17767,8 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
   if (attr)
     TYPE_LENGTH (range_type) = DW_UNSND (attr);
 
+  maybe_set_alignment (cu, die, range_type);
+
   set_die_type (die, range_type, cu);
 
   /* set_die_type should be already done.  */
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 1359c2fb53..dd7c89d948 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -353,6 +353,7 @@ struct gdbarch
   gdbarch_addressable_memory_unit_size_ftype *addressable_memory_unit_size;
   char ** disassembler_options;
   const disasm_options_t * valid_disassembler_options;
+  gdbarch_type_align_ftype *type_align;
 };
 
 /* Create a new ``struct gdbarch'' based on information provided by
@@ -465,6 +466,7 @@ gdbarch_alloc (const struct gdbarch_info *info,
   gdbarch->gcc_target_options = default_gcc_target_options;
   gdbarch->gnu_triplet_regexp = default_gnu_triplet_regexp;
   gdbarch->addressable_memory_unit_size = default_addressable_memory_unit_size;
+  gdbarch->type_align = default_type_align;
   /* gdbarch_alloc() */
 
   return gdbarch;
@@ -716,6 +718,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of addressable_memory_unit_size, invalid_p == 0 */
   /* Skip verify of disassembler_options, invalid_p == 0 */
   /* Skip verify of valid_disassembler_options, invalid_p == 0 */
+  /* Skip verify of type_align, invalid_p == 0 */
   if (!log.empty ())
     internal_error (__FILE__, __LINE__,
                     _("verify_gdbarch: the following are invalid ...%s"),
@@ -1441,6 +1444,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
   fprintf_unfiltered (file,
                       "gdbarch_dump: target_desc = %s\n",
                       host_address_to_string (gdbarch->target_desc));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: type_align = <%s>\n",
+                      host_address_to_string (gdbarch->type_align));
   fprintf_unfiltered (file,
                       "gdbarch_dump: gdbarch_unwind_pc_p() = %d\n",
                       gdbarch_unwind_pc_p (gdbarch));
@@ -5100,6 +5106,23 @@ set_gdbarch_valid_disassembler_options (struct gdbarch *gdbarch,
   gdbarch->valid_disassembler_options = valid_disassembler_options;
 }
 
+ULONGEST
+gdbarch_type_align (struct gdbarch *gdbarch, struct type *type)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->type_align != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_type_align called\n");
+  return gdbarch->type_align (gdbarch, type);
+}
+
+void
+set_gdbarch_type_align (struct gdbarch *gdbarch,
+                        gdbarch_type_align_ftype type_align)
+{
+  gdbarch->type_align = type_align;
+}
+
 
 /* Keep a registry of per-architecture data-pointers required by GDB
    modules.  */
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 0084f199d7..3848ec50c7 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -1560,6 +1560,12 @@ extern void set_gdbarch_disassembler_options (struct gdbarch *gdbarch, char ** d
 extern const disasm_options_t * gdbarch_valid_disassembler_options (struct gdbarch *gdbarch);
 extern void set_gdbarch_valid_disassembler_options (struct gdbarch *gdbarch, const disasm_options_t * valid_disassembler_options);
 
+/* Type alignment. */
+
+typedef ULONGEST (gdbarch_type_align_ftype) (struct gdbarch *gdbarch, struct type *type);
+extern ULONGEST gdbarch_type_align (struct gdbarch *gdbarch, struct type *type);
+extern void set_gdbarch_type_align (struct gdbarch *gdbarch, gdbarch_type_align_ftype *type_align);
+
 /* Definition for an unknown syscall, used basically in error-cases.  */
 #define UNKNOWN_SYSCALL (-1)
 
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index 4fc54cba9c..bb62e6d620 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -1163,6 +1163,9 @@ m;int;addressable_memory_unit_size;void;;;default_addressable_memory_unit_size;;
 v;char **;disassembler_options;;;0;0;;0;pstring_ptr (gdbarch->disassembler_options)
 v;const disasm_options_t *;valid_disassembler_options;;;0;0;;0;host_address_to_string (gdbarch->valid_disassembler_options)
 
+# Type alignment.
+m;ULONGEST;type_align;struct type *type;type;;default_type_align;;0
+
 EOF
 }
 
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index b3a037971e..d9cd55cd23 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -3013,6 +3013,125 @@ init_pointer_type (struct objfile *objfile,
   return t;
 }
 
+/* See gdbtypes.h.  */
+
+unsigned
+type_raw_align (struct type *type)
+{
+  if (type->align_log2 != 0)
+    return 1 << (type->align_log2 - 1);
+  return 0;
+}
+
+/* See gdbtypes.h.  */
+
+unsigned
+type_align (struct type *type)
+{
+  unsigned raw_align = type_raw_align (type);
+  if (raw_align != 0)
+    return raw_align;
+
+  ULONGEST align = 0;
+  switch (TYPE_CODE (type))
+    {
+    case TYPE_CODE_PTR:
+    case TYPE_CODE_FUNC:
+    case TYPE_CODE_FLAGS:
+    case TYPE_CODE_INT:
+    case TYPE_CODE_FLT:
+    case TYPE_CODE_ENUM:
+    case TYPE_CODE_REF:
+    case TYPE_CODE_RVALUE_REF:
+    case TYPE_CODE_CHAR:
+    case TYPE_CODE_BOOL:
+    case TYPE_CODE_DECFLOAT:
+      {
+	struct gdbarch *arch = get_type_arch (type);
+	align = gdbarch_type_align (arch, type);
+      }
+      break;
+
+    case TYPE_CODE_ARRAY:
+    case TYPE_CODE_COMPLEX:
+    case TYPE_CODE_TYPEDEF:
+      align = type_align (TYPE_TARGET_TYPE (type));
+      break;
+
+    case TYPE_CODE_STRUCT:
+    case TYPE_CODE_UNION:
+      {
+	if (TYPE_NFIELDS (type) == 0)
+	  {
+	    /* An empty struct has alignment 1.  */
+	    align = 1;
+	    break;
+	  }
+	for (unsigned i = 0; i < TYPE_NFIELDS (type); ++i)
+	  {
+	    ULONGEST f_align = type_align (TYPE_FIELD_TYPE (type, i));
+	    if (f_align == 0)
+	      {
+		/* Don't pretend we know something we don't.  */
+		align = 0;
+		break;
+	      }
+	    if (f_align > align)
+	      align = f_align;
+	  }
+      }
+      break;
+
+    case TYPE_CODE_SET:
+    case TYPE_CODE_RANGE:
+    case TYPE_CODE_STRING:
+      /* Not sure what to do here, and these can't appear in C or C++
+	 anyway.  */
+      break;
+
+    case TYPE_CODE_METHODPTR:
+    case TYPE_CODE_MEMBERPTR:
+      align = TYPE_LENGTH (type);
+      break;
+
+    case TYPE_CODE_VOID:
+    case TYPE_CODE_ERROR:
+    case TYPE_CODE_METHOD:
+    default:
+      break;
+    }
+
+  if ((align & (align - 1)) != 0)
+    {
+      /* Not a power of 2, so pass.  */
+      align = 0;
+    }
+
+  return align;
+}
+
+/* See gdbtypes.h.  */
+
+bool
+set_type_align (struct type *type, ULONGEST align)
+{
+  /* Must be a power of 2.  Zero is ok.  */
+  gdb_assert ((align & (align - 1)) == 0);
+
+  unsigned result = 0;
+  while (align != 0)
+    {
+      ++result;
+      align >>= 1;
+    }
+
+  if (result >= (1 << TYPE_ALIGN_BITS))
+    return false;
+
+  type->align_log2 = result;
+  return true;
+}
+
 \f
 /* Queries on types.  */
 
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index 552a2a2a16..59fa1e2a10 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -802,6 +802,10 @@ struct main_type
   struct dynamic_prop_list *dyn_prop_list;
 };
 
+/* * Number of bits allocated for alignment.  */
+
+#define TYPE_ALIGN_BITS 8
+
 /* * A ``struct type'' describes a particular instance of a type, with
    some particular qualification.  */
 
@@ -831,6 +835,14 @@ struct type
 
   struct type *chain;
 
+  /* * The alignment for this type.  Zero means that the alignment was
+     not specified in the debug info.  Note that this is stored in a
+     funny way: as the log base 2 (plus 1) of the alignment; so a
+     value of 1 means the alignment is 1, and a value of 9 means the
+     alignment is 256.  */
+
+  unsigned align_log2 : TYPE_ALIGN_BITS;
+
   /* * Flags specific to this instance of the type, indicating where
      on the ring we are.
 
@@ -841,7 +853,7 @@ struct type
      instance flags are completely inherited from the target type.  No
      qualifiers can be cleared by the typedef.  See also
      check_typedef.  */
-  int instance_flags;
+  unsigned instance_flags : 9;
 
   /* * Length of storage for a value of this type.  The value is the
      expression in host bytes of what sizeof(type) would return.  This
@@ -1292,6 +1304,26 @@ extern void allocate_gnat_aux_type (struct type *);
    so you only have to call check_typedef once.  Since allocate_value
    calls check_typedef, TYPE_LENGTH (VALUE_TYPE (X)) is safe.  */
 #define TYPE_LENGTH(thistype) (thistype)->length
+
+/* * Return the alignment of the type in bytes, or 0 if no alignment
+   was specified.  */
+#define TYPE_RAW_ALIGN(thistype) type_raw_align (thistype)
+
+/* * Return the alignment of the type in bytes, or 0 if no alignment
+   was specified.  */
+extern unsigned type_raw_align (struct type *);
+
+/* * Return the alignment of the type in bytes.  Return 0 if the
+   alignment cannot be determined; but note that this makes an effort
+   to compute the alignment even it it was not specified in the debug
+   info.  */
+extern unsigned type_align (struct type *);
+
+/* * Set the alignment of the type.  The alignment must be a power of
+   2.  Returns false if the given value does not fit in the available
+   space in struct type.  */
+extern bool set_type_align (struct type *, ULONGEST);
+
 /* * Note that TYPE_CODE can be TYPE_CODE_TYPEDEF, so if you want the real
    type, you need to do TYPE_CODE (check_type (this_type)).  */
 #define TYPE_CODE(thistype) TYPE_MAIN_TYPE(thistype)->code
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index bf4ca54303..e1938304bb 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -8347,6 +8347,33 @@ i386_validate_tdesc_p (struct gdbarch_tdep *tdep,
 }
 
 \f
+
+/* Implement the type_align gdbarch function.  */
+
+static ULONGEST
+i386_type_align (struct gdbarch *gdbarch, struct type *type)
+{
+  type = check_typedef (type);
+
+  if (gdbarch_ptr_bit (gdbarch) == 32 &&
+      TYPE_CODE (type) == TYPE_CODE_INT && TYPE_LENGTH (type) > 4)
+    return 4;
+
+  if (gdbarch_ptr_bit (gdbarch) == 32
+      && TYPE_CODE (type) == TYPE_CODE_FLT
+      && TYPE_LENGTH (type) > 4)
+    return 4;
+
+  /* Handle x86's funny long double.  */
+  if (TYPE_CODE (type) == TYPE_CODE_FLT
+      && gdbarch_ptr_bit (gdbarch) == 32
+      && gdbarch_long_double_bit (gdbarch) == TYPE_LENGTH (type) * 8)
+    return 4;
+
+  return TYPE_LENGTH (type);
+}
+
+\f
 /* Note: This is called for both i386 and amd64.  */
 
 static struct gdbarch *
@@ -8405,6 +8432,7 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->record_regmap = i386_record_regmap;
 
   set_gdbarch_long_long_align_bit (gdbarch, 32);
+  set_gdbarch_type_align (gdbarch, i386_type_align);
 
   /* The format used for `long double' on almost all i386 targets is
      the i387 extended floating-point format.  In fact, of all targets
-- 
2.14.3

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

* [RFA 4/6] Expose type alignment on gdb.Type
  2018-04-24 15:22 [RFA 0/6] Teach gdb about type alignment Tom Tromey
                   ` (4 preceding siblings ...)
  2018-04-24 15:22 ` [RFA 6/6] Remove long_long_align_bit gdbarch attribute Tom Tromey
@ 2018-04-24 15:22 ` Tom Tromey
  2018-04-24 16:59   ` Eli Zaretskii
  5 siblings, 1 reply; 22+ messages in thread
From: Tom Tromey @ 2018-04-24 15:22 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This adds an "align" attribute to gdb.Type in the Python API.

2018-04-24  Tom Tromey  <tom@tromey.com>

	* NEWS: Mention Type.align.
	* python/py-type.c (typy_get_align): New function.
	(type_object_getset): Add "align".

2018-04-24  Tom Tromey  <tom@tromey.com>

	* python.texi (Types In Python): Document Type.align.

2018-04-24  Tom Tromey  <tom@tromey.com>

	* gdb.python/py-type.exp: Check align attribute.
	* gdb.python/py-type.c: New "aligncheck" global.
---
 gdb/ChangeLog                        |  6 ++++++
 gdb/NEWS                             |  4 ++++
 gdb/doc/ChangeLog                    |  4 ++++
 gdb/doc/python.texi                  |  7 +++++++
 gdb/python/py-type.c                 | 24 ++++++++++++++++++++++++
 gdb/testsuite/ChangeLog              |  5 +++++
 gdb/testsuite/gdb.python/py-type.c   |  2 ++
 gdb/testsuite/gdb.python/py-type.exp |  4 ++++
 8 files changed, 56 insertions(+)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 98ea77816b..78acc26f4a 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,9 @@
+2018-04-24  Tom Tromey  <tom@tromey.com>
+
+	* NEWS: Mention Type.align.
+	* python/py-type.c (typy_get_align): New function.
+	(type_object_getset): Add "align".
+
 2018-04-24  Tom Tromey  <tom@tromey.com>
 
 	* python/py-type.c (type_object_getset): Reindent.
diff --git a/gdb/NEWS b/gdb/NEWS
index 6631b53475..6193070023 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -27,6 +27,10 @@ set|show record btrace cpu
   Controls the processor to be used for enabling errata workarounds for
   branch trace decode.
 
+* Python API
+
+  ** Type alignment is now exposed via the "align" attribute of a gdb.Type.
+
 * New targets
 
 RiscV ELF			riscv*-*-elf
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index 83d48781f9..57df264c1b 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,7 @@
+2018-04-24  Tom Tromey  <tom@tromey.com>
+
+	* python.texi (Types In Python): Document Type.align.
+
 2018-04-13  Andreas Arnez  <arnez@linux.vnet.ibm.com>
 
 	* gdb.texinfo (Symbols): Mention the fact that "info
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index ebd48fffe7..e5fd713e0a 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -930,6 +930,13 @@ description of the @code{Type.fields} method for a description of the
 
 An instance of @code{Type} has the following attributes:
 
+@defvar Type.align
+The alignment of this type, in bytes.  Type alignment comes from the
+debugging information; if it was not specified, then @value{GDBN} will
+use the relevant ABI to try to determine the alignment.  In some
+cases, even this is not possible, and zero will be returned.
+@end defvar
+
 @defvar Type.code
 The type code for this type.  The type code will be one of the
 @code{TYPE_CODE_} constants defined below.
diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
index fcd6ed5621..bc49ec66ac 100644
--- a/gdb/python/py-type.c
+++ b/gdb/python/py-type.c
@@ -730,6 +730,28 @@ typy_get_sizeof (PyObject *self, void *closure)
   return gdb_py_long_from_longest (TYPE_LENGTH (type));
 }
 
+/* Return the alignment of the type represented by SELF, in bytes.  */
+static PyObject *
+typy_get_align (PyObject *self, void *closure)
+{
+  struct type *type = ((type_object *) self)->type;
+
+  ULONGEST align = 0;
+  TRY
+    {
+      align = type_align (type);
+    }
+  CATCH (except, RETURN_MASK_ALL)
+    {
+      align = 0;
+    }
+  END_CATCH
+
+  /* Ignore exceptions.  */
+
+  return gdb_py_object_from_ulongest (align);
+}
+
 static struct type *
 typy_lookup_typename (const char *type_name, const struct block *block)
 {
@@ -1410,6 +1432,8 @@ gdbpy_initialize_types (void)
 
 static gdb_PyGetSetDef type_object_getset[] =
 {
+ { "align", typy_get_align, NULL,
+   "The alignment of this type, in bytes.", NULL },
  { "code", typy_get_code, NULL,
    "The code for this type.", NULL },
  { "name", typy_get_name, NULL,
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index ad7889b677..50c1851c4d 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2018-04-24  Tom Tromey  <tom@tromey.com>
+
+	* gdb.python/py-type.exp: Check align attribute.
+	* gdb.python/py-type.c: New "aligncheck" global.
+
 2018-04-24  Tom Tromey  <tom@tromey.com>
 
 	PR exp/17095:
diff --git a/gdb/testsuite/gdb.python/py-type.c b/gdb/testsuite/gdb.python/py-type.c
index 2626d4e418..9531c9e6cb 100644
--- a/gdb/testsuite/gdb.python/py-type.c
+++ b/gdb/testsuite/gdb.python/py-type.c
@@ -30,6 +30,8 @@ struct SS
 typedef struct s TS;
 TS ts;
 
+int aligncheck;
+
 #ifdef __cplusplus
 struct C
 {
diff --git a/gdb/testsuite/gdb.python/py-type.exp b/gdb/testsuite/gdb.python/py-type.exp
index b87e86cdf6..382bdff118 100644
--- a/gdb/testsuite/gdb.python/py-type.exp
+++ b/gdb/testsuite/gdb.python/py-type.exp
@@ -278,6 +278,10 @@ if { [build_inferior "${binfile}" "c"] == 0 } {
   gdb_test "python print(gdb.lookup_type('int').optimized_out())" \
       "<optimized out>"
 
+  set sint [get_sizeof int 0]
+  gdb_test "python print(gdb.parse_and_eval('aligncheck').type.align)" \
+      $sint
+
   with_test_prefix "lang_c" {
       runto_bp "break to inspect struct and array."
       test_fields "c"
-- 
2.14.3

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

* [RFA 2/6] Handle alignof and _Alignof
  2018-04-24 15:22 [RFA 0/6] Teach gdb about type alignment Tom Tromey
  2018-04-24 15:22 ` [RFA 5/6] Remove rust_type_alignment Tom Tromey
  2018-04-24 15:22 ` [RFA 3/6] Reindent type_object_getset in py-type.c Tom Tromey
@ 2018-04-24 15:22 ` Tom Tromey
  2018-04-24 17:04   ` Eli Zaretskii
  2018-04-24 19:17   ` Pedro Alves
  2018-04-24 15:22 ` [RFA 1/6] Add initial type alignment support Tom Tromey
                   ` (2 subsequent siblings)
  5 siblings, 2 replies; 22+ messages in thread
From: Tom Tromey @ 2018-04-24 15:22 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This adds alignof and _Alignof to the C/C++ expression parser, and
adds new tests to test the features.  The tests are written to try to
ensure that gdb's knowledge of alignment rules stays in sync with the
compiler's.

2018-04-24  Tom Tromey  <tom@tromey.com>

	PR exp/17095:
	* NEWS: Update.
	* std-operator.def (UNOP_ALIGNOF): New operator.
	* expprint.c (dump_subexp_body_standard) <case UNOP_ALIGNOF>:
	New.
	* eval.c (evaluate_subexp_standard) <case UNOP_ALIGNOF>: New.
	* c-lang.c (c_op_print_tab): Add alignof.
	* c-exp.y (ALIGNOF): New token.
	(exp): Add "ALIGNOF" production.
	(ident_tokens): Add _Alignof and alignof.

2018-04-24  Tom Tromey  <tom@tromey.com>

	PR exp/17095:
	* gdb.dwarf2/dw2-align.exp: New file.
	* gdb.cp/align.exp: New file.
	* gdb.base/align.exp: New file.
---
 gdb/ChangeLog                          |  13 ++++
 gdb/NEWS                               |   3 +
 gdb/c-exp.y                            |   8 +-
 gdb/c-lang.c                           |   1 +
 gdb/eval.c                             |  13 ++++
 gdb/expprint.c                         |   1 +
 gdb/std-operator.def                   |   1 +
 gdb/testsuite/ChangeLog                |   7 ++
 gdb/testsuite/gdb.base/align.exp       |  94 ++++++++++++++++++++++++
 gdb/testsuite/gdb.cp/align.exp         | 129 +++++++++++++++++++++++++++++++++
 gdb/testsuite/gdb.dwarf2/dw2-align.exp |  83 +++++++++++++++++++++
 11 files changed, 352 insertions(+), 1 deletion(-)
 create mode 100644 gdb/testsuite/gdb.base/align.exp
 create mode 100644 gdb/testsuite/gdb.cp/align.exp
 create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-align.exp

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 94d166e310..563aa517b8 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,16 @@
+2018-04-24  Tom Tromey  <tom@tromey.com>
+
+	PR exp/17095:
+	* NEWS: Update.
+	* std-operator.def (UNOP_ALIGNOF): New operator.
+	* expprint.c (dump_subexp_body_standard) <case UNOP_ALIGNOF>:
+	New.
+	* eval.c (evaluate_subexp_standard) <case UNOP_ALIGNOF>: New.
+	* c-lang.c (c_op_print_tab): Add alignof.
+	* c-exp.y (ALIGNOF): New token.
+	(exp): Add "ALIGNOF" production.
+	(ident_tokens): Add _Alignof and alignof.
+
 2018-04-24  Tom Tromey  <tom@tromey.com>
 
 	* i386-tdep.c (i386_type_align): New function.
diff --git a/gdb/NEWS b/gdb/NEWS
index 63fe30d175..6631b53475 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -9,6 +9,9 @@
 * 'info proc' now works on running processes on FreeBSD systems and core
   files created on FreeBSD systems.
 
+* C expressions can now use _Alignof, and C++ expressions can now use
+  alignof.
+
 * New commands
 
 set debug fbsd-nat
diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 8dc3c068a5..64ec00da07 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -173,7 +173,7 @@ static void c_print_token (FILE *file, int type, YYSTYPE value);
 %token <ssym> NAME_OR_INT
 
 %token OPERATOR
-%token STRUCT CLASS UNION ENUM SIZEOF UNSIGNED COLONCOLON
+%token STRUCT CLASS UNION ENUM SIZEOF ALIGNOF UNSIGNED COLONCOLON
 %token TEMPLATE
 %token ERROR
 %token NEW DELETE
@@ -307,6 +307,10 @@ exp	:	SIZEOF exp       %prec UNARY
 			{ write_exp_elt_opcode (pstate, UNOP_SIZEOF); }
 	;
 
+exp	:	ALIGNOF '(' type_exp ')'	%prec UNARY
+			{ write_exp_elt_opcode (pstate, UNOP_ALIGNOF); }
+	;
+
 exp	:	exp ARROW name
 			{ write_exp_elt_opcode (pstate, STRUCTOP_PTR);
 			  write_exp_string (pstate, $3);
@@ -2314,6 +2318,8 @@ static const struct token ident_tokens[] =
     {"struct", STRUCT, OP_NULL, 0},
     {"signed", SIGNED_KEYWORD, OP_NULL, 0},
     {"sizeof", SIZEOF, OP_NULL, 0},
+    {"_Alignof", ALIGNOF, OP_NULL, 0},
+    {"alignof", ALIGNOF, OP_NULL, FLAG_CXX},
     {"double", DOUBLE_KEYWORD, OP_NULL, 0},
     {"false", FALSEKEYWORD, OP_NULL, FLAG_CXX},
     {"class", CLASS, OP_NULL, FLAG_CXX},
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index 658c7f7826..15e633f8c8 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -751,6 +751,7 @@ const struct op_print c_op_print_tab[] =
   {"*", UNOP_IND, PREC_PREFIX, 0},
   {"&", UNOP_ADDR, PREC_PREFIX, 0},
   {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
+  {"alignof ", UNOP_ALIGNOF, PREC_PREFIX, 0},
   {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
   {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
   {NULL, OP_NULL, PREC_PREFIX, 0}
diff --git a/gdb/eval.c b/gdb/eval.c
index b6fbfcf6c9..47ca03b5e1 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -2662,6 +2662,19 @@ evaluate_subexp_standard (struct type *expect_type,
 	}
       return evaluate_subexp_for_sizeof (exp, pos, noside);
 
+    case UNOP_ALIGNOF:
+      {
+	struct type *type
+	  = value_type (evaluate_subexp (NULL_TYPE, exp, pos,
+					 EVAL_AVOID_SIDE_EFFECTS));
+	/* FIXME: This should be size_t.  */
+	struct type *size_type = builtin_type (exp->gdbarch)->builtin_int;
+	ULONGEST align = type_align (type);
+	if (align == 0)
+	  error (_("could not determine alignment of type"));
+	return value_from_longest (size_type, align);
+      }
+
     case UNOP_CAST:
       (*pos) += 2;
       type = exp->elts[pc + 1].type;
diff --git a/gdb/expprint.c b/gdb/expprint.c
index c906904599..5985f70a8f 100644
--- a/gdb/expprint.c
+++ b/gdb/expprint.c
@@ -846,6 +846,7 @@ dump_subexp_body_standard (struct expression *exp,
     case UNOP_PREDECREMENT:
     case UNOP_POSTDECREMENT:
     case UNOP_SIZEOF:
+    case UNOP_ALIGNOF:
     case UNOP_PLUS:
     case UNOP_CAP:
     case UNOP_CHR:
diff --git a/gdb/std-operator.def b/gdb/std-operator.def
index 87bb518877..1297c1edeb 100644
--- a/gdb/std-operator.def
+++ b/gdb/std-operator.def
@@ -234,6 +234,7 @@ OP (UNOP_POSTINCREMENT)		/* ++ after an expression */
 OP (UNOP_PREDECREMENT)		/* -- before an expression */
 OP (UNOP_POSTDECREMENT)		/* -- after an expression */
 OP (UNOP_SIZEOF)		/* Unary sizeof (followed by expression) */
+OP (UNOP_ALIGNOF)		/* Unary alignof (followed by expression) */
 
 OP (UNOP_PLUS)			/* Unary plus */
 
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index d5e9429041..ad7889b677 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2018-04-24  Tom Tromey  <tom@tromey.com>
+
+	PR exp/17095:
+	* gdb.dwarf2/dw2-align.exp: New file.
+	* gdb.cp/align.exp: New file.
+	* gdb.base/align.exp: New file.
+
 2018-04-19  Richard Bunt  <richard.bunt@arm.com>
 
 	* gdb.threads/multiple-successive-infcall.c: New test.
diff --git a/gdb/testsuite/gdb.base/align.exp b/gdb/testsuite/gdb.base/align.exp
new file mode 100644
index 0000000000..98c19e3086
--- /dev/null
+++ b/gdb/testsuite/gdb.base/align.exp
@@ -0,0 +1,94 @@
+# Copyright 2018 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the gdb testsuite
+
+# The types we're going to test.
+
+set typelist {
+    char {unsigned char}
+    short {unsigned short}
+    int {unsigned int}
+    long {unsigned long}
+    {long long} {unsigned long long}
+    float
+    double
+}
+
+# Create the test file.
+
+set filename [standard_output_file align.c]
+set outfile [open $filename w]
+
+# Prologue.
+puts -nonewline $outfile "#define DEF(T,U) struct align_pair_ ## T ## _x_ ## U "
+puts $outfile "{ T one; U two; }"
+
+# First emit single items.
+foreach type $typelist {
+    set utype [join [split $type] _]
+    if {$type != $utype} {
+	puts $outfile "typedef $type $utype;"
+    }
+    puts $outfile "$type item_$utype;"
+    puts $outfile "unsigned a_$utype\n  = _Alignof ($type);"
+    set utype [join [split $type] _]
+}
+
+# Now emit all pairs.
+foreach type $typelist {
+    set utype [join [split $type] _]
+    foreach inner $typelist {
+	set uinner [join [split $inner] _]
+	puts $outfile "DEF ($utype, $uinner);"
+	set joined "${utype}_x_${uinner}"
+	puts $outfile "struct align_pair_$joined item_${joined};"
+	puts $outfile "unsigned a_${joined}"
+	puts $outfile "  = _Alignof (struct align_pair_${joined});"
+    }
+}
+
+# Epilogue.
+puts $outfile {
+    int main() {
+	return 0;
+    }
+}
+
+close $outfile
+
+standard_testfile $filename
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug}]} {
+    return -1
+}
+
+if {![runto_main]} {
+    perror "test suppressed"
+    return
+}
+
+foreach type $typelist {
+    set utype [join [split $type] _]
+    set expected [get_integer_valueof a_$utype 0]
+    gdb_test "print _Alignof($type)" " = $expected"
+
+    foreach inner $typelist {
+	set uinner [join [split $inner] _]
+	set expected [get_integer_valueof a_${utype}_x_${uinner} 0]
+	gdb_test "print _Alignof(struct align_pair_${utype}_x_${uinner})" \
+	    " = $expected"
+    }
+}
diff --git a/gdb/testsuite/gdb.cp/align.exp b/gdb/testsuite/gdb.cp/align.exp
new file mode 100644
index 0000000000..9037aeb2c7
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/align.exp
@@ -0,0 +1,129 @@
+# Copyright 2018 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the gdb testsuite
+
+if {[skip_cplus_tests]} { continue }
+
+# The types we're going to test.
+
+set typelist {
+    char {unsigned char}
+    short {unsigned short}
+    int {unsigned int}
+    long {unsigned long}
+    {long long} {unsigned long long}
+    float
+    double {long double}
+    bigenum
+}
+
+# Create the test file.
+
+set filename [standard_output_file align.cc]
+set outfile [open $filename w]
+
+# Prologue.
+puts $outfile {
+    template<typename T, typename U>
+    struct align_pair
+    {
+	T one;
+	U two;
+    };
+
+    template<typename T, typename U>
+    struct align_union
+    {
+	T one;
+	U two;
+    };
+
+    enum bigenum { VALUE = 0xffffffffull };
+
+    struct empty { };
+    empty item_empty;
+    unsigned a_empty = alignof (empty);
+}
+
+# First emit single items.
+foreach type $typelist {
+    set utype [join [split $type] _]
+    puts $outfile "$type item_$utype;"
+    puts $outfile "unsigned a_$utype\n  = alignof ($type);"
+}
+
+# Now emit all pairs.
+foreach type $typelist {
+    set utype [join [split $type] _]
+    foreach inner $typelist {
+	set uinner [join [split $inner] _]
+	puts $outfile "align_pair<$type, $inner> item_${utype}_x_${uinner};"
+	puts $outfile "unsigned a_${utype}_x_${uinner}"
+	puts $outfile "  = alignof (align_pair<$type, $inner>);"
+
+	puts $outfile "align_union<$type, $inner> item_${utype}_u_${uinner};"
+	puts $outfile "unsigned a_${utype}_u_${uinner}"
+	puts $outfile "  = alignof (align_union<$type, $inner>);"
+    }
+}
+
+# Epilogue.
+puts $outfile {
+    int main() {
+	return 0;
+    }
+}
+
+close $outfile
+
+standard_testfile $filename
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile \
+	 {debug c++ additional_flags=-std=c++11}]} {
+    return -1
+}
+
+if {![runto_main]} {
+    perror "test suppressed"
+    return
+}
+
+foreach type $typelist {
+    set utype [join [split $type] _]
+    set expected [get_integer_valueof a_$utype 0]
+
+    # See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69560
+    # The g++ implementation of alignof is changing to match C11.
+    if {[is_x86_like_target]
+	&& ($type == "double" || $type == "long long"
+	    || $type == "unsigned long long")} {
+	setup_xfail *-*-*
+    }
+
+    gdb_test "print alignof($type)" " = $expected"
+
+    foreach inner $typelist {
+	set uinner [join [split $inner] _]
+	set expected [get_integer_valueof a_${utype}_x_${uinner} 0]
+	gdb_test "print alignof(align_pair<${type},${inner}>)" " = $expected"
+
+	set expected [get_integer_valueof a_${utype}_u_${uinner} 0]
+	gdb_test "print alignof(align_union<${type},${inner}>)" " = $expected"
+    }
+}
+
+set expected [get_integer_valueof a_empty 0]
+gdb_test "print alignof(empty)" " = $expected"
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-align.exp b/gdb/testsuite/gdb.dwarf2/dw2-align.exp
new file mode 100644
index 0000000000..2c2faf7591
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-align.exp
@@ -0,0 +1,83 @@
+# Copyright 2018 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+load_lib dwarf.exp
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+if {![dwarf2_support]} {
+    return 0
+}
+
+standard_testfile main.c align-dw.S
+
+# Make some DWARF for the test.
+
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+    global srcdir subdir srcfile
+
+    cu {} {
+	DW_TAG_compile_unit {
+                {DW_AT_language @DW_LANG_C_plus_plus}
+                {DW_AT_name     dw2-align.c}
+                {DW_AT_comp_dir /tmp}
+        } {
+	    declare_labels itype ptype
+
+            itype: DW_TAG_base_type {
+                {DW_AT_byte_size 4 DW_FORM_sdata}
+                {DW_AT_encoding  @DW_ATE_signed}
+                {DW_AT_name int_4096}
+		{DW_AT_alignment 4096 DW_FORM_sdata}
+            }
+
+            ptype: DW_TAG_pointer_type {
+                {DW_AT_byte_size 8 DW_FORM_sdata}
+                {DW_AT_type :$itype}
+		{DW_AT_alignment 4096 DW_FORM_sdata}
+            }
+
+            DW_TAG_typedef {
+                {DW_AT_name ptr_4096}
+                {DW_AT_type :$ptype}
+            }
+
+	    DW_TAG_structure_type {
+		{DW_AT_name "struct_4096"}
+		{DW_AT_byte_size 4096 DW_FORM_sdata}
+		{DW_AT_alignment 4096 DW_FORM_udata}
+	    } {
+		member {
+		    {name a}
+		    {type :$itype}
+		    {data_member_location 0 data1}
+		}
+	    }
+	}
+    }
+}
+
+if { [prepare_for_testing "failed to prepare" ${testfile} \
+	  [list $srcfile $asm_file] {nodebug}] } {
+    return -1
+}
+
+if ![runto_main] {
+    return -1
+}
+
+gdb_test_no_output "set lang c++"
+gdb_test "print alignof(int_4096)" " = 4096"
+gdb_test "print alignof(ptr_4096)" " = 4096"
+gdb_test "print alignof(struct_4096)" " = 4096"
-- 
2.14.3

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

* [RFA 0/6] Teach gdb about type alignment
@ 2018-04-24 15:22 Tom Tromey
  2018-04-24 15:22 ` [RFA 5/6] Remove rust_type_alignment Tom Tromey
                   ` (5 more replies)
  0 siblings, 6 replies; 22+ messages in thread
From: Tom Tromey @ 2018-04-24 15:22 UTC (permalink / raw)
  To: gdb-patches

This series teaches gdb about type alignment -- both how to read and
store DW_AT_alignment, and how to compute the alignment in an
ABI-sensitive way when the alignment is not specified.  It also
exposes this information to Python, and removes a bit of code made
redundant by this change.

Regression tested by the buildbot.

Tom

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

* Re: [RFA 6/6] Remove long_long_align_bit gdbarch attribute
  2018-04-24 15:22 ` [RFA 6/6] Remove long_long_align_bit gdbarch attribute Tom Tromey
@ 2018-04-24 15:24   ` Tom Tromey
  2018-04-24 17:17   ` Anton Kolesov
  1 sibling, 0 replies; 22+ messages in thread
From: Tom Tromey @ 2018-04-24 15:24 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches, Anton Kolesov

>>>>> "Tom" == Tom Tromey <tom@tromey.com> writes:

Tom> This removes the long_long_align_bit gdbarch attribute in favor of
Tom> type_align.  This uncovered two possible issues.

Tom> First, arc-tdep.c claimed that long long alignment was 32 bits, but
Tom> gcc's arc.h says:

Tom>     #define ADJUST_FIELD_ALIGN(FIELD, TYPE, COMPUTED) \
Tom>     (TYPE_MODE (strip_array_types (TYPE)) == DFmode \
Tom>      ? MIN ((COMPUTED), 32) : (COMPUTED))

Tom> Here, DFmode means "double".  So, I've implemented arc_type_align
Tom> according to this.  I do not have a good way to test this.

Anton, could you take a look at this part of the patch?

Tom

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

* Re: [RFA 4/6] Expose type alignment on gdb.Type
  2018-04-24 15:22 ` [RFA 4/6] Expose type alignment on gdb.Type Tom Tromey
@ 2018-04-24 16:59   ` Eli Zaretskii
  0 siblings, 0 replies; 22+ messages in thread
From: Eli Zaretskii @ 2018-04-24 16:59 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

> From: Tom Tromey <tom@tromey.com>
> Cc: Tom Tromey <tom@tromey.com>
> Date: Tue, 24 Apr 2018 09:22:20 -0600
> 
> This adds an "align" attribute to gdb.Type in the Python API.
> 
> 2018-04-24  Tom Tromey  <tom@tromey.com>
> 
> 	* NEWS: Mention Type.align.
> 	* python/py-type.c (typy_get_align): New function.
> 	(type_object_getset): Add "align".
> 
> 2018-04-24  Tom Tromey  <tom@tromey.com>
> 
> 	* python.texi (Types In Python): Document Type.align.
> 
> 2018-04-24  Tom Tromey  <tom@tromey.com>
> 
> 	* gdb.python/py-type.exp: Check align attribute.
> 	* gdb.python/py-type.c: New "aligncheck" global.

OK for the documentation parts.

Thanks.

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

* Re: [RFA 2/6] Handle alignof and _Alignof
  2018-04-24 15:22 ` [RFA 2/6] Handle alignof and _Alignof Tom Tromey
@ 2018-04-24 17:04   ` Eli Zaretskii
  2018-04-24 19:17   ` Pedro Alves
  1 sibling, 0 replies; 22+ messages in thread
From: Eli Zaretskii @ 2018-04-24 17:04 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

> From: Tom Tromey <tom@tromey.com>
> Cc: Tom Tromey <tom@tromey.com>
> Date: Tue, 24 Apr 2018 09:22:18 -0600
> 
> diff --git a/gdb/NEWS b/gdb/NEWS
> index 63fe30d175..6631b53475 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -9,6 +9,9 @@
>  * 'info proc' now works on running processes on FreeBSD systems and core
>    files created on FreeBSD systems.
>  
> +* C expressions can now use _Alignof, and C++ expressions can now use
> +  alignof.
> +
>  * New commands

OK for this part.

Thanks.

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

* RE: [RFA 6/6] Remove long_long_align_bit gdbarch attribute
  2018-04-24 15:22 ` [RFA 6/6] Remove long_long_align_bit gdbarch attribute Tom Tromey
  2018-04-24 15:24   ` Tom Tromey
@ 2018-04-24 17:17   ` Anton Kolesov
  2018-04-26 20:56     ` Tom Tromey
  1 sibling, 1 reply; 22+ messages in thread
From: Anton Kolesov @ 2018-04-24 17:17 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches; +Cc: Claudiu Zissulescu

> First, arc-tdep.c claimed that long long alignment was 32 bits, but gcc's arc.h
> says:
> 
>     #define ADJUST_FIELD_ALIGN(FIELD, TYPE, COMPUTED) \
>     (TYPE_MODE (strip_array_types (TYPE)) == DFmode \
>      ? MIN ((COMPUTED), 32) : (COMPUTED))
> 
> Here, DFmode means "double".  So, I've implemented arc_type_align
> according to this.  I do not have a good way to test this.
> 
> diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c index b0d51addd3..86cf522443
> 100644
> --- a/gdb/arc-tdep.c
> +++ b/gdb/arc-tdep.c
> @@ -1957,6 +1957,19 @@ arc_tdesc_init (struct gdbarch_info info, const
> struct target_desc **tdesc,
>    return TRUE;
>  }
> 
> +/* Implement the type_align gdbarch function.  */
> +
> +static ULONGEST
> +arc_type_align (struct gdbarch *gdbarch, struct type *type) {
> +  type = check_typedef (type);
> +
> +  if (TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8)
> +    return 4;
> +
> +  return TYPE_LENGTH (type);
> +}
> +

Hi Tom,

If I read this correctly, then it would set 4 byte alignment only to 8 byte
floating point type? That doesn't look right, because on ARC there is never
more than 4 byte alignment for any data type. GCC arc.h has:

    #define BIGGEST_ALIGNMENT 32

According to comments it used to be 64, but was changed to 32 at some
undefined point in the past.

I would have implemented this as:

static ULONGEST
arc_type_align (struct gdbarch *gdbarch, struct type *type) {
  type = check_typedef (type);
  return std::min<ULONGEST>(4, TYPE_LENGTH (type));
}

Anton

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

* Re: [RFA 1/6] Add initial type alignment support
  2018-04-24 15:22 ` [RFA 1/6] Add initial type alignment support Tom Tromey
@ 2018-04-24 19:16   ` Pedro Alves
  2018-04-24 20:23     ` Tom Tromey
  0 siblings, 1 reply; 22+ messages in thread
From: Pedro Alves @ 2018-04-24 19:16 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

Hi Tom,

On 04/24/2018 04:22 PM, Tom Tromey wrote:

> +/* * Number of bits allocated for alignment.  */
> +
> +#define TYPE_ALIGN_BITS 8
> +
>  /* * A ``struct type'' describes a particular instance of a type, with
>     some particular qualification.  */
>  
> @@ -831,6 +835,14 @@ struct type
>  
>    struct type *chain;
>  
> +  /* * The alignment for this type.  Zero means that the alignment was
> +     not specified in the debug info.  Note that this is stored in a
> +     funny way: as the log base 2 (plus 1) of the alignment; so a
> +     value of 1 means the alignment is 1, and a value of 9 means the
> +     alignment is 256.  */
> +
> +  unsigned align_log2 : TYPE_ALIGN_BITS;
> +
>    /* * Flags specific to this instance of the type, indicating where
>       on the ring we are.
>  
> @@ -841,7 +853,7 @@ struct type
>       instance flags are completely inherited from the target type.  No
>       qualifiers can be cleared by the typedef.  See also
>       check_typedef.  */
> -  int instance_flags;
> +  unsigned instance_flags : 9;
>  
>    /* * Length of storage for a value of this type.  The value is the
>       expression in host bytes of what sizeof(type) would return.  This
> @@ -1292,6 +1304,26 @@ extern void allocate_gnat_aux_type (struct type *);
>     so you only have to call check_typedef once.  Since allocate_value
>     calls check_typedef, TYPE_LENGTH (VALUE_TYPE (X)) is safe.  */
>  #define TYPE_LENGTH(thistype) (thistype)->length
> +
> +/* * Return the alignment of the type in bytes, or 0 if no alignment
> +   was specified.  */
> +#define TYPE_RAW_ALIGN(thistype) type_raw_align (thistype)
> +
> +/* * Return the alignment of the type in bytes, or 0 if no alignment
> +   was specified.  */
> +extern unsigned type_raw_align (struct type *);
> +
> +/* * Return the alignment of the type in bytes.  Return 0 if the
> +   alignment cannot be determined; but note that this makes an effort
> +   to compute the alignment even it it was not specified in the debug
> +   info.  */
> +extern unsigned type_align (struct type *);
> +
> +/* * Set the alignment of the type.  The alignment must be a power of
> +   2.  Returns false if the given value does not fit in the available
> +   space in struct type.  */
> +extern bool set_type_align (struct type *, ULONGEST);

Are these represented in host bytes, or target addressable memory units?
See comments around type::length and type_length_units.  The comments above
should be clarified in that direction.

> +/* Implement the type_align gdbarch function.  */
> +
> +static ULONGEST
> +i386_type_align (struct gdbarch *gdbarch, struct type *type)
> +{
> +  type = check_typedef (type);
> +
> +  if (gdbarch_ptr_bit (gdbarch) == 32 &&
> +      TYPE_CODE (type) == TYPE_CODE_INT && TYPE_LENGTH (type) > 4)
> +    return 4;

&& on the other line.

Otherwise looks good to me, but I'd like to hear Simon's opinion.

Thanks,
Pedro Alves

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

* Re: [RFA 2/6] Handle alignof and _Alignof
  2018-04-24 15:22 ` [RFA 2/6] Handle alignof and _Alignof Tom Tromey
  2018-04-24 17:04   ` Eli Zaretskii
@ 2018-04-24 19:17   ` Pedro Alves
  2018-04-24 20:23     ` Tom Tromey
                       ` (2 more replies)
  1 sibling, 3 replies; 22+ messages in thread
From: Pedro Alves @ 2018-04-24 19:17 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

Hi Tom,

What's in the patch looks good to me.  I have comments on the
tests -- I think it'd be good to extend them a bit more.

On 04/24/2018 04:22 PM, Tom Tromey wrote:

> +
> +# The types we're going to test.
> +
> +set typelist {
> +    char {unsigned char}
> +    short {unsigned short}
> +    int {unsigned int}
> +    long {unsigned long}
> +    {long long} {unsigned long long}
> +    float
> +    double

Shouldn't we test "long double"?  Patch #1 handles it.
Not sure all GCC ports support it, may require separate compilation.

Also, I'm wondering about "__int128" if the target
supports it.

In C++, do we get the alignment of non-standard layout classes right?
E.g., structs with references.  And structs with virtual methods, like:

 struct S
 {
   virtual ~S ();
   char c;
 };

This should print 8 instead of 1 on x86-64, due to the vtable pointer.

I think it'd be good to cover those things in the tests too.

Likewise arrays, bitfields and typedefs?

I didn't spot any test for the
 "could not determine alignment of type"
case to make that that works gracefully without crashing.  

What do we do with _Alignof(void)?  We treat sizeof(void) == 1,
like gcc, so I assume the _Alignof will return 1 too instead
of erroring out.

Finally, for completeness, GCC allows _Alignof applied to
expressions, so I guess we should to.  Does the series allow that?
I.e., can we do _Alignof(1 + 1)?  Does the parser handle that?

Shouldn't we test _Alignof applied to the structure fields too?

There was a snippet in the patch that made me wonder if the patch
handles alignof of a no-debug-info variable and and the return-type
of a no-debug-info function correctly (instead of e.g., crashing).
I'd be nice to add a couples test to gdb.base/nodebug.exp
to make sure.  E.g.:
   p _Alignof (dataglobal64_1)
   p _Alignof (middle())"

Also, please add intro comments to the testcase .exp files, so
that later on people can find out what the testcase is
about easily.

Thanks,
Pedro Alves

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

* Re: [RFA 2/6] Handle alignof and _Alignof
  2018-04-24 19:17   ` Pedro Alves
@ 2018-04-24 20:23     ` Tom Tromey
  2018-04-27 18:02       ` Pedro Alves
  2018-04-26 20:45     ` Tom Tromey
  2018-04-26 20:54     ` Tom Tromey
  2 siblings, 1 reply; 22+ messages in thread
From: Tom Tromey @ 2018-04-24 20:23 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro> Shouldn't we test "long double"?  Patch #1 handles it.
Pedro> Not sure all GCC ports support it, may require separate compilation.

I thought C didn't have long double (it's tested in the C++ test), but I
see it does.  I will add that.

Pedro> Also, I'm wondering about "__int128" if the target
Pedro> supports it.

I have bad feelings about trying to detect this in the test.

Pedro> In C++, do we get the alignment of non-standard layout classes right?
Pedro> Likewise arrays, bitfields and typedefs?
Pedro> What do we do with _Alignof(void)?

I will add these.

Pedro> I didn't spot any test for the
Pedro>  "could not determine alignment of type"
Pedro> case to make that that works gracefully without crashing.  

I think this one is maybe hard to test without some kind of bug (so far
I've only seen it when some part of the patch was buggy), but I will see
what I can do.

Pedro> Finally, for completeness, GCC allows _Alignof applied to
Pedro> expressions, so I guess we should to.  Does the series allow that?
Pedro> I.e., can we do _Alignof(1 + 1)?  Does the parser handle that?

No, and this is hard to do.  I've left the door open a bit by the way
the new expression emits a new OP instead of simply writing out a
constant (and this allows alignof(typeof(..)) to work as well).
However, I think the way the parser is written makes this difficult,
which is one reason that sizeof requires or does not require parens
depending on whether the argument is an expression or a type.

It would be possible to write "alignof expression", but I didn't want to
add an extension, especially since "alignof(typeof(expression))" is
pretty easy.

Pedro> Shouldn't we test _Alignof applied to the structure fields too?

It seems to me that this would necessarily be an expression, not a type.

Pedro> There was a snippet in the patch that made me wonder if the patch
Pedro> handles alignof of a no-debug-info variable and and the return-type
Pedro> of a no-debug-info function correctly (instead of e.g., crashing).
Pedro> I'd be nice to add a couples test to gdb.base/nodebug.exp
Pedro> to make sure.  E.g.:
Pedro>    p _Alignof (dataglobal64_1)
Pedro>    p _Alignof (middle())"

Pedro> Also, please add intro comments to the testcase .exp files, so
Pedro> that later on people can find out what the testcase is
Pedro> about easily.

Ok to all.

Tom

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

* Re: [RFA 1/6] Add initial type alignment support
  2018-04-24 19:16   ` Pedro Alves
@ 2018-04-24 20:23     ` Tom Tromey
  0 siblings, 0 replies; 22+ messages in thread
From: Tom Tromey @ 2018-04-24 20:23 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

>> +  if (gdbarch_ptr_bit (gdbarch) == 32 &&
>> +      TYPE_CODE (type) == TYPE_CODE_INT && TYPE_LENGTH (type) > 4)
>> +    return 4;

Pedro> && on the other line.

Hah.  Actually I think I meant to refactor this all a bit and make an
outer if that checked gdbarch_ptr_bit.

Tom

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

* Re: [RFA 2/6] Handle alignof and _Alignof
  2018-04-24 19:17   ` Pedro Alves
  2018-04-24 20:23     ` Tom Tromey
@ 2018-04-26 20:45     ` Tom Tromey
  2018-04-27 18:05       ` Pedro Alves
  2018-04-26 20:54     ` Tom Tromey
  2 siblings, 1 reply; 22+ messages in thread
From: Tom Tromey @ 2018-04-26 20:45 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro> What do we do with _Alignof(void)?  We treat sizeof(void) == 1,
Pedro> like gcc, so I assume the _Alignof will return 1 too instead
Pedro> of erroring out.

_Alignof(void) is accepted by gcc but alignof(void) is rejected by g++.
I've made the test do the former.

Tom

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

* Re: [RFA 2/6] Handle alignof and _Alignof
  2018-04-24 19:17   ` Pedro Alves
  2018-04-24 20:23     ` Tom Tromey
  2018-04-26 20:45     ` Tom Tromey
@ 2018-04-26 20:54     ` Tom Tromey
  2 siblings, 0 replies; 22+ messages in thread
From: Tom Tromey @ 2018-04-26 20:54 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro> There was a snippet in the patch that made me wonder if the patch
Pedro> handles alignof of a no-debug-info variable and and the return-type
Pedro> of a no-debug-info function correctly (instead of e.g., crashing).
Pedro> I'd be nice to add a couples test to gdb.base/nodebug.exp
Pedro> to make sure.  E.g.:
Pedro>    p _Alignof (dataglobal64_1)
Pedro>    p _Alignof (middle())"

I think these can't be done because _Alignof only applies to types.

Tom

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

* Re: [RFA 6/6] Remove long_long_align_bit gdbarch attribute
  2018-04-24 17:17   ` Anton Kolesov
@ 2018-04-26 20:56     ` Tom Tromey
  0 siblings, 0 replies; 22+ messages in thread
From: Tom Tromey @ 2018-04-26 20:56 UTC (permalink / raw)
  To: Anton Kolesov; +Cc: Tom Tromey, gdb-patches, Claudiu Zissulescu

>>>>> "Anton" == Anton Kolesov <Anton.Kolesov@synopsys.com> writes:

Anton> I would have implemented this as:

Anton> static ULONGEST
Anton> arc_type_align (struct gdbarch *gdbarch, struct type *type) {
Anton>   type = check_typedef (type);
Anton>   return std::min<ULONGEST>(4, TYPE_LENGTH (type));
Anton> }

Thanks, I've made this change locally.

Tom

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

* Re: [RFA 2/6] Handle alignof and _Alignof
  2018-04-24 20:23     ` Tom Tromey
@ 2018-04-27 18:02       ` Pedro Alves
  2018-04-27 20:53         ` Tom Tromey
  2018-04-30 16:46         ` Tom Tromey
  0 siblings, 2 replies; 22+ messages in thread
From: Pedro Alves @ 2018-04-27 18:02 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 04/24/2018 09:23 PM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
> 
> Pedro> Shouldn't we test "long double"?  Patch #1 handles it.
> Pedro> Not sure all GCC ports support it, may require separate compilation.
> 
> I thought C didn't have long double (it's tested in the C++ test), but I
> see it does.  I will add that.
> 
> Pedro> Also, I'm wondering about "__int128" if the target
> Pedro> supports it.
> 
> I have bad feelings about trying to detect this in the test.

My thought was to simply support compiling a separate testcase
binary for a given type instead of mixing all types in
the same program.  So if a type is not supported, the program
won't compile and we'd skip the testing that type.  It'd basically
require moving the body of the testing code to a procedure that
is passed a list of types to compile & test in group.  So the
basic types that must be supported by all C/C++ implementations
would be one single group.  While other types like __int128 and
any other we add in future would be in separate groups / passes.

> 
> Pedro> In C++, do we get the alignment of non-standard layout classes right?
> Pedro> Likewise arrays, bitfields and typedefs?
> Pedro> What do we do with _Alignof(void)?
> 
> I will add these.
> 
> Pedro> I didn't spot any test for the
> Pedro>  "could not determine alignment of type"
> Pedro> case to make that that works gracefully without crashing.  
> 
> I think this one is maybe hard to test without some kind of bug (so far
> I've only seen it when some part of the patch was buggy), but I will see
> what I can do.
> 
> Pedro> Finally, for completeness, GCC allows _Alignof applied to
> Pedro> expressions, so I guess we should to.  Does the series allow that?
> Pedro> I.e., can we do _Alignof(1 + 1)?  Does the parser handle that?
> 
> No, and this is hard to do.  I've left the door open a bit by the way
> the new expression emits a new OP instead of simply writing out a
> constant (and this allows alignof(typeof(..)) to work as well).
> However, I think the way the parser is written makes this difficult,

OOC, can you expand a bit on what you mean here?  I would have assumed
that at the parser level, we'd just copy exactly what is done for
supporting expressions with sizeof.

> which is one reason that sizeof requires or does not require parens
> depending on whether the argument is an expression or a type.

Not clear what you mean here.  I know that sizeof with an expression
requires parenthesis in C/C++, but I'm not connecting the dots with
the above comments.

> It would be possible to write "alignof expression", but I didn't want to
> add an extension, 

Oh, you mean, you would want to make gdb require the parens when
given an expression as prerequisite for supporting expressions?

I wouldn't think that as a blocker, since AFAICS, we already have
that "extension" for sizeof:

 (gdb) p sizeof 1 + 1
 $1 = 5

so I wouldn't see it as a problem to make alignof work the same way,
and then if/when somebody wants to make gdb require the parens,
he'd just do it to both sizeof/alignof.

Anyway, I'll take alignof/_Alignof with no expressions over
no alignof/_Alignof, for sure.  :-)

> especially since "alignof(typeof(expression))" is
> pretty easy.

Ah, if that works, then yeah, that's a good escape hatch.

Should we have a test for that?

> 
> Pedro> Shouldn't we test _Alignof applied to the structure fields too?
> 
> It seems to me that this would necessarily be an expression, not a type.

Yeah.  I think the main complication here would be related to how the
expression machinery returns values and types, and then how to
distinguish a struct field of type X with a standalone variable of
type X, for alignof purposes (given x86's funny alignments).

Thanks,
Pedro Alves

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

* Re: [RFA 2/6] Handle alignof and _Alignof
  2018-04-26 20:45     ` Tom Tromey
@ 2018-04-27 18:05       ` Pedro Alves
  0 siblings, 0 replies; 22+ messages in thread
From: Pedro Alves @ 2018-04-27 18:05 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 04/26/2018 09:45 PM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
> 
> Pedro> What do we do with _Alignof(void)?  We treat sizeof(void) == 1,
> Pedro> like gcc, so I assume the _Alignof will return 1 too instead
> Pedro> of erroring out.
> 
> _Alignof(void) is accepted by gcc but alignof(void) is rejected by g++.
> I've made the test do the former.

It's a warning, not rejected.  Just like for sizeof(void).

Thanks,
Pedro Alves

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

* Re: [RFA 2/6] Handle alignof and _Alignof
  2018-04-27 18:02       ` Pedro Alves
@ 2018-04-27 20:53         ` Tom Tromey
  2018-04-30 16:46         ` Tom Tromey
  1 sibling, 0 replies; 22+ messages in thread
From: Tom Tromey @ 2018-04-27 20:53 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:

Pedro> My thought was to simply support compiling a separate testcase
Pedro> binary for a given type instead of mixing all types in
Pedro> the same program.  So if a type is not supported, the program
Pedro> won't compile and we'd skip the testing that type.

Ok, I can do that.  I'll put the "void" test there too -- the problem
with it being that (1) we'd need "nowarnings" and (2) since it isn't
really valid, presumably some other C++ compiler might reject it.

Tom> No, and this is hard to do.  I've left the door open a bit by the way
Tom> the new expression emits a new OP instead of simply writing out a
Tom> constant (and this allows alignof(typeof(..)) to work as well).
Tom> However, I think the way the parser is written makes this difficult,

Pedro> OOC, can you expand a bit on what you mean here?  I would have assumed
Pedro> that at the parser level, we'd just copy exactly what is done for
Pedro> supporting expressions with sizeof.

Right now we have:

exp	:	ALIGNOF '(' type_exp ')'	%prec UNARY
			{ write_exp_elt_opcode (pstate, UNOP_ALIGNOF); }
	;


We could add another production like:

exp : ALIGNOF '(' exp ')' ...

... but when I tried this the resulting parser had issues with the tests
-- claiming syntax errors where there were none.

Tom> which is one reason that sizeof requires or does not require parens
Tom> depending on whether the argument is an expression or a type.

Pedro> Not clear what you mean here.  I know that sizeof with an expression
Pedro> requires parenthesis in C/C++, but I'm not connecting the dots with
Pedro> the above comments.

For sizeof there are two productions:

exp	:	SIZEOF exp       %prec UNARY
			{ write_exp_elt_opcode (pstate, UNOP_SIZEOF); }
	;

exp	:	SIZEOF '(' type ')'	%prec UNARY


I don't really know offhand why the latter is taken when a paren is
seen, it seems ambiguous to me.

Debugging this stuff is not very easy or enjoyable.  Switching to a
recursive descent parser would eliminate problems like this, because
some of the decisions would be turned into more simple programming
problems.

Tom> especially since "alignof(typeof(expression))" is
Tom> pretty easy.

Pedro> Ah, if that works, then yeah, that's a good escape hatch.

Pedro> Should we have a test for that?

Yeah, I'll add one.

Pedro> Yeah.  I think the main complication here would be related to how the
Pedro> expression machinery returns values and types, and then how to
Pedro> distinguish a struct field of type X with a standalone variable of
Pedro> type X, for alignof purposes (given x86's funny alignments).

I think with the new agreed-upon definition of alignof, this is no
longer a concern.

Tom

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

* Re: [RFA 2/6] Handle alignof and _Alignof
  2018-04-27 18:02       ` Pedro Alves
  2018-04-27 20:53         ` Tom Tromey
@ 2018-04-30 16:46         ` Tom Tromey
  1 sibling, 0 replies; 22+ messages in thread
From: Tom Tromey @ 2018-04-30 16:46 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Tom Tromey, gdb-patches

Pedro> My thought was to simply support compiling a separate testcase
Pedro> binary for a given type instead of mixing all types in
Pedro> the same program.

I ended up just adding a gdb_caching_proc that detects __int128 and then
conditionally appending __int128 to the list of types.  This seemed
simpler, and also it seemed to me that the test should have a lot of
type mixing anyway.

Tom

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

end of thread, other threads:[~2018-04-30 16:46 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-04-24 15:22 [RFA 0/6] Teach gdb about type alignment Tom Tromey
2018-04-24 15:22 ` [RFA 5/6] Remove rust_type_alignment Tom Tromey
2018-04-24 15:22 ` [RFA 3/6] Reindent type_object_getset in py-type.c Tom Tromey
2018-04-24 15:22 ` [RFA 2/6] Handle alignof and _Alignof Tom Tromey
2018-04-24 17:04   ` Eli Zaretskii
2018-04-24 19:17   ` Pedro Alves
2018-04-24 20:23     ` Tom Tromey
2018-04-27 18:02       ` Pedro Alves
2018-04-27 20:53         ` Tom Tromey
2018-04-30 16:46         ` Tom Tromey
2018-04-26 20:45     ` Tom Tromey
2018-04-27 18:05       ` Pedro Alves
2018-04-26 20:54     ` Tom Tromey
2018-04-24 15:22 ` [RFA 1/6] Add initial type alignment support Tom Tromey
2018-04-24 19:16   ` Pedro Alves
2018-04-24 20:23     ` Tom Tromey
2018-04-24 15:22 ` [RFA 6/6] Remove long_long_align_bit gdbarch attribute Tom Tromey
2018-04-24 15:24   ` Tom Tromey
2018-04-24 17:17   ` Anton Kolesov
2018-04-26 20:56     ` Tom Tromey
2018-04-24 15:22 ` [RFA 4/6] Expose type alignment on gdb.Type Tom Tromey
2018-04-24 16:59   ` Eli Zaretskii

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).