[Ada] Replace packed records with integers in low-level implementation

Message ID 20210507093823.GA140787@adacore.com
State New
Headers show
Series
  • [Ada] Replace packed records with integers in low-level implementation
Related show

Commit Message

Pierre-Marie de Rodat May 7, 2021, 9:38 a.m.
Accessing components in packed record types turns out to be too slow
for practical use so this replaces them with integer types.

Tested on x86_64-pc-linux-gnu, committed on trunk

gcc/ada/

	* atree.ads (Slot): Change to modular type.
	(Slot_1_Bit): Delete.
	(Slot_2_Bit): Likewise.
	(Slot_4_Bit): Likewise.
	(Slot_8_Bit): Likewise.
	(Slot_32_Bit): Likewise.
	* atree.adb (Get_1_Bit_Val): Adjust to above change.
	(Get_2_Bit_Val): Likewise.
	(Get_4_Bit_Val): Likewise.
	(Get_8_Bit_Val): Likewise.
	(Get_32_Bit_Val): Likewise.
	(Set_1_Bit_Val): Likewise.
	(Set_2_Bit_Val): Likewise.
	(Set_4_Bit_Val): Likewise.
	(Set_8_Bit_Val): Likewise.
	(Set_32_Bit_Val): Likewise.
	(Print_Atree_Info): Likewise.
	(Zero): Likewise.
	* atree.h (Get_1_Bit_Field): Likewise.
	(Get_2_Bit_Field): Likewise.
	(Get_4_Bit_Field): Likewise.
	(Get_8_Bit_Field): Likewise.
	(Get_32_Bit_Field): Likewise.
	(Get_32_Bit_Field_With_Default): Likewise.
	* types.h (slot_1_bit): Delete.
	(slot_2_bit): Likewise.
	(slot_4_bit): Likewise.
	(slot_8_bit): Likewise.
	(slot_32_bit): Likewise.
	(any_slot): Change to unsigned int.
	(Slot_Size): New macro.

Patch

diff --git a/gcc/ada/atree.adb b/gcc/ada/atree.adb
--- a/gcc/ada/atree.adb
+++ b/gcc/ada/atree.adb
@@ -599,119 +599,55 @@  package body Atree is
         (N : Node_Or_Entity_Id; Offset : Field_Offset) return Field_1_Bit
       is
          --  We wish we were using packed arrays, but instead we're simulating
-         --  packed arrays using packed records. L here (and elsewhere) is the
-         --  'Length of that array.
-         L : constant Field_Offset := 32;
+         --  them with modular integers. L here (and elsewhere) is the 'Length
+         --  of that simulated array.
+         L : constant Field_Offset := Slot_Size / 1;
 
          pragma Debug (Validate_Node_And_Offset (N, Offset / L));
 
-         subtype Offset_In_Slot is Field_Offset range 0 .. L - 1;
          S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset / L);
+         V : constant Integer := Integer ((Offset mod L) * (Slot_Size / L));
       begin
-         case Offset_In_Slot'(Offset mod L) is
-            when 0 => return S.Slot_1.F0;
-            when 1 => return S.Slot_1.F1;
-            when 2 => return S.Slot_1.F2;
-            when 3 => return S.Slot_1.F3;
-            when 4 => return S.Slot_1.F4;
-            when 5 => return S.Slot_1.F5;
-            when 6 => return S.Slot_1.F6;
-            when 7 => return S.Slot_1.F7;
-            when 8 => return S.Slot_1.F8;
-            when 9 => return S.Slot_1.F9;
-            when 10 => return S.Slot_1.F10;
-            when 11 => return S.Slot_1.F11;
-            when 12 => return S.Slot_1.F12;
-            when 13 => return S.Slot_1.F13;
-            when 14 => return S.Slot_1.F14;
-            when 15 => return S.Slot_1.F15;
-            when 16 => return S.Slot_1.F16;
-            when 17 => return S.Slot_1.F17;
-            when 18 => return S.Slot_1.F18;
-            when 19 => return S.Slot_1.F19;
-            when 20 => return S.Slot_1.F20;
-            when 21 => return S.Slot_1.F21;
-            when 22 => return S.Slot_1.F22;
-            when 23 => return S.Slot_1.F23;
-            when 24 => return S.Slot_1.F24;
-            when 25 => return S.Slot_1.F25;
-            when 26 => return S.Slot_1.F26;
-            when 27 => return S.Slot_1.F27;
-            when 28 => return S.Slot_1.F28;
-            when 29 => return S.Slot_1.F29;
-            when 30 => return S.Slot_1.F30;
-            when 31 => return S.Slot_1.F31;
-         end case;
+         return Field_1_Bit (Shift_Right (S, V) and 1);
       end Get_1_Bit_Val;
 
       function Get_2_Bit_Val
         (N : Node_Or_Entity_Id; Offset : Field_Offset) return Field_2_Bit
       is
-         L : constant Field_Offset := 16;
+         L : constant Field_Offset := Slot_Size / 2;
 
          pragma Debug (Validate_Node_And_Offset (N, Offset / L));
 
-         subtype Offset_In_Slot is Field_Offset range 0 .. L - 1;
          S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset / L);
+         V : constant Integer := Integer ((Offset mod L) * (Slot_Size / L));
       begin
-         case Offset_In_Slot'(Offset mod L) is
-            when 0 => return S.Slot_2.F0;
-            when 1 => return S.Slot_2.F1;
-            when 2 => return S.Slot_2.F2;
-            when 3 => return S.Slot_2.F3;
-            when 4 => return S.Slot_2.F4;
-            when 5 => return S.Slot_2.F5;
-            when 6 => return S.Slot_2.F6;
-            when 7 => return S.Slot_2.F7;
-            when 8 => return S.Slot_2.F8;
-            when 9 => return S.Slot_2.F9;
-            when 10 => return S.Slot_2.F10;
-            when 11 => return S.Slot_2.F11;
-            when 12 => return S.Slot_2.F12;
-            when 13 => return S.Slot_2.F13;
-            when 14 => return S.Slot_2.F14;
-            when 15 => return S.Slot_2.F15;
-         end case;
+         return Field_2_Bit (Shift_Right (S, V) and 3);
       end Get_2_Bit_Val;
 
       function Get_4_Bit_Val
         (N : Node_Or_Entity_Id; Offset : Field_Offset) return Field_4_Bit
       is
-         L : constant Field_Offset := 8;
+         L : constant Field_Offset := Slot_Size / 4;
 
          pragma Debug (Validate_Node_And_Offset (N, Offset / L));
 
-         subtype Offset_In_Slot is Field_Offset range 0 .. L - 1;
          S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset / L);
+         V : constant Integer := Integer ((Offset mod L) * (Slot_Size / L));
       begin
-         case Offset_In_Slot'(Offset mod L) is
-            when 0 => return S.Slot_4.F0;
-            when 1 => return S.Slot_4.F1;
-            when 2 => return S.Slot_4.F2;
-            when 3 => return S.Slot_4.F3;
-            when 4 => return S.Slot_4.F4;
-            when 5 => return S.Slot_4.F5;
-            when 6 => return S.Slot_4.F6;
-            when 7 => return S.Slot_4.F7;
-         end case;
+         return Field_4_Bit (Shift_Right (S, V) and 15);
       end Get_4_Bit_Val;
 
       function Get_8_Bit_Val
         (N : Node_Or_Entity_Id; Offset : Field_Offset) return Field_8_Bit
       is
-         L : constant Field_Offset := 4;
+         L : constant Field_Offset := Slot_Size / 8;
 
          pragma Debug (Validate_Node_And_Offset (N, Offset / L));
 
-         subtype Offset_In_Slot is Field_Offset range 0 .. L - 1;
          S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset / L);
+         V : constant Integer := Integer ((Offset mod L) * (Slot_Size / L));
       begin
-         case Offset_In_Slot'(Offset mod L) is
-            when 0 => return S.Slot_8.F0;
-            when 1 => return S.Slot_8.F1;
-            when 2 => return S.Slot_8.F2;
-            when 3 => return S.Slot_8.F3;
-         end case;
+         return Field_8_Bit (Shift_Right (S, V) and 255);
       end Get_8_Bit_Val;
 
       function Get_32_Bit_Val
@@ -721,123 +657,59 @@  package body Atree is
 
          S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset);
       begin
-         return S.Slot_32;
+         return Field_32_Bit (S);
       end Get_32_Bit_Val;
 
       procedure Set_1_Bit_Val
         (N : Node_Or_Entity_Id; Offset : Field_Offset; Val : Field_1_Bit)
       is
-         L : constant Field_Offset := 32;
+         L : constant Field_Offset := Slot_Size / 1;
 
          pragma Debug (Validate_Node_And_Offset_Write (N, Offset / L));
 
-         subtype Offset_In_Slot is Field_Offset range 0 .. L - 1;
          S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset / L);
+         V : constant Integer := Integer ((Offset mod L) * (Slot_Size / L));
       begin
-         case Offset_In_Slot'(Offset mod L) is
-            when 0 => S.Slot_1.F0 := Val;
-            when 1 => S.Slot_1.F1 := Val;
-            when 2 => S.Slot_1.F2 := Val;
-            when 3 => S.Slot_1.F3 := Val;
-            when 4 => S.Slot_1.F4 := Val;
-            when 5 => S.Slot_1.F5 := Val;
-            when 6 => S.Slot_1.F6 := Val;
-            when 7 => S.Slot_1.F7 := Val;
-            when 8 => S.Slot_1.F8 := Val;
-            when 9 => S.Slot_1.F9 := Val;
-            when 10 => S.Slot_1.F10 := Val;
-            when 11 => S.Slot_1.F11 := Val;
-            when 12 => S.Slot_1.F12 := Val;
-            when 13 => S.Slot_1.F13 := Val;
-            when 14 => S.Slot_1.F14 := Val;
-            when 15 => S.Slot_1.F15 := Val;
-            when 16 => S.Slot_1.F16 := Val;
-            when 17 => S.Slot_1.F17 := Val;
-            when 18 => S.Slot_1.F18 := Val;
-            when 19 => S.Slot_1.F19 := Val;
-            when 20 => S.Slot_1.F20 := Val;
-            when 21 => S.Slot_1.F21 := Val;
-            when 22 => S.Slot_1.F22 := Val;
-            when 23 => S.Slot_1.F23 := Val;
-            when 24 => S.Slot_1.F24 := Val;
-            when 25 => S.Slot_1.F25 := Val;
-            when 26 => S.Slot_1.F26 := Val;
-            when 27 => S.Slot_1.F27 := Val;
-            when 28 => S.Slot_1.F28 := Val;
-            when 29 => S.Slot_1.F29 := Val;
-            when 30 => S.Slot_1.F30 := Val;
-            when 31 => S.Slot_1.F31 := Val;
-         end case;
+         S := (S and not Shift_Left (1, V)) or Shift_Left (Slot (Val), V);
       end Set_1_Bit_Val;
 
       procedure Set_2_Bit_Val
         (N : Node_Or_Entity_Id; Offset : Field_Offset; Val : Field_2_Bit)
       is
-         L : constant Field_Offset := 16;
+         L : constant Field_Offset := Slot_Size / 2;
 
          pragma Debug (Validate_Node_And_Offset_Write (N, Offset / L));
 
-         subtype Offset_In_Slot is Field_Offset range 0 .. L - 1;
          S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset / L);
+         V : constant Integer := Integer ((Offset mod L) * (Slot_Size / L));
       begin
-         case Offset_In_Slot'(Offset mod L) is
-            when 0 => S.Slot_2.F0 := Val;
-            when 1 => S.Slot_2.F1 := Val;
-            when 2 => S.Slot_2.F2 := Val;
-            when 3 => S.Slot_2.F3 := Val;
-            when 4 => S.Slot_2.F4 := Val;
-            when 5 => S.Slot_2.F5 := Val;
-            when 6 => S.Slot_2.F6 := Val;
-            when 7 => S.Slot_2.F7 := Val;
-            when 8 => S.Slot_2.F8 := Val;
-            when 9 => S.Slot_2.F9 := Val;
-            when 10 => S.Slot_2.F10 := Val;
-            when 11 => S.Slot_2.F11 := Val;
-            when 12 => S.Slot_2.F12 := Val;
-            when 13 => S.Slot_2.F13 := Val;
-            when 14 => S.Slot_2.F14 := Val;
-            when 15 => S.Slot_2.F15 := Val;
-         end case;
+         S := (S and not Shift_Left (3, V)) or Shift_Left (Slot (Val), V);
       end Set_2_Bit_Val;
 
       procedure Set_4_Bit_Val
         (N : Node_Or_Entity_Id; Offset : Field_Offset; Val : Field_4_Bit)
       is
-         L : constant Field_Offset := 8;
+         L : constant Field_Offset := Slot_Size / 4;
 
          pragma Debug (Validate_Node_And_Offset_Write (N, Offset / L));
 
-         subtype Offset_In_Slot is Field_Offset range 0 .. L - 1;
          S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset / L);
+         V : constant Integer := Integer ((Offset mod L) * (Slot_Size / L));
       begin
-         case Offset_In_Slot'(Offset mod L) is
-            when 0 => S.Slot_4.F0 := Val;
-            when 1 => S.Slot_4.F1 := Val;
-            when 2 => S.Slot_4.F2 := Val;
-            when 3 => S.Slot_4.F3 := Val;
-            when 4 => S.Slot_4.F4 := Val;
-            when 5 => S.Slot_4.F5 := Val;
-            when 6 => S.Slot_4.F6 := Val;
-            when 7 => S.Slot_4.F7 := Val;
-         end case;
+         S := (S and not Shift_Left (15, V)) or Shift_Left (Slot (Val), V);
       end Set_4_Bit_Val;
 
       procedure Set_8_Bit_Val
         (N : Node_Or_Entity_Id; Offset : Field_Offset; Val : Field_8_Bit)
       is
-         L : constant Field_Offset := 4;
+         L : constant Field_Offset := Slot_Size / 8;
 
          pragma Debug (Validate_Node_And_Offset_Write (N, Offset / L));
 
-         subtype Offset_In_Slot is Field_Offset range 0 .. L - 1;
          S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset / L);
+         V : constant Integer := Integer ((Offset mod L) * (Slot_Size / L));
       begin
-         case Offset_In_Slot'(Offset mod L) is
-            when 0 => S.Slot_8.F0 := Val;
-            when 1 => S.Slot_8.F1 := Val;
-            when 2 => S.Slot_8.F2 := Val;
-            when 3 => S.Slot_8.F3 := Val;
-         end case;
+         S := (S and not Shift_Left (255, V)) or Shift_Left (Slot (Val), V);
       end Set_8_Bit_Val;
 
       procedure Set_32_Bit_Val
@@ -847,7 +719,7 @@  package body Atree is
 
          S : Slot renames Slots.Table (Node_Offsets.Table (N) + Offset);
       begin
-         S.Slot_32 := Val;
+         S := Slot (Val);
       end Set_32_Bit_Val;
 
    end Atree_Private_Part;
@@ -2006,7 +1878,7 @@  package body Atree is
    ----------------------
 
    procedure Print_Atree_Info (N : Node_Or_Entity_Id) is
-      function Cast is new Unchecked_Conversion (Slot_32_Bit, Int);
+      function Cast is new Unchecked_Conversion (Slot, Int);
    begin
       Write_Int (Int (Size_In_Slots (N)));
       Write_Str (" slots (");
@@ -2017,7 +1889,7 @@  package body Atree is
 
       for Off in Off_0 (N) .. Off_L (N) loop
          Write_Str (" ");
-         Write_Int (Cast (Slots.Table (Off).Slot_32));
+         Write_Int (Cast (Slots.Table (Off)));
       end loop;
 
       Write_Eol;
@@ -2507,7 +2379,7 @@  package body Atree is
       Locked := False;
    end Unlock_Nodes;
 
-   Zero : constant Slot := (Field_Size => 32, Slot_32 => 0);
+   Zero : constant Slot := 0;
 
    procedure Zero_Slots (F, L : Node_Offset) is
    begin


diff --git a/gcc/ada/atree.ads b/gcc/ada/atree.ads
--- a/gcc/ada/atree.ads
+++ b/gcc/ada/atree.ads
@@ -722,57 +722,21 @@  package Atree is
          Table_Increment      => Alloc.Node_Offsets_Increment,
          Table_Name           => "Node_Offsets");
 
-      --  We define type Slot as a packed Unchecked_Union of slots with
-      --  appropriate numbers of components of appropriate size. The reason
-      --  for this (as opposed to using packed arrays) is that we are using
-      --  bit fields on the C++ side, and C++ doesn't have packed arrays.
-
-      type Field_1_Bit is mod 2**1;
-      type Slot_1_Bit is record -- 32 1-bit fields
-         F0, F1, F2, F3, F4, F5, F6, F7, F8, F9,
-         F10, F11, F12, F13, F14, F15, F16, F17, F18, F19,
-         F20, F21, F22, F23, F24, F25, F26, F27, F28, F29,
-         F30, F31 :
-           Field_1_Bit;
-      end record with Pack, Convention => C;
-      pragma Assert (Slot_1_Bit'Size = 32);
-
-      type Field_2_Bit is mod 2**2;
-      type Slot_2_Bit is record -- 16 2-bit fields
-         F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15 :
-           Field_2_Bit;
-      end record with Pack, Convention => C;
-      pragma Assert (Slot_2_Bit'Size = 32);
-
-      type Field_4_Bit is mod 2**4;
-      type Slot_4_Bit is record -- 8 4-bit fields
-         F0, F1, F2, F3, F4, F5, F6, F7 :
-           Field_4_Bit;
-      end record with Pack, Convention => C;
-      pragma Assert (Slot_4_Bit'Size = 32);
-
-      type Field_8_Bit is mod 2**8;
-      type Slot_8_Bit is record -- 4 8-bit fields
-         F0, F1, F2, F3 :
-           Field_8_Bit;
-      end record with Pack, Convention => C;
-      pragma Assert (Slot_8_Bit'Size = 32);
-
+      --  We define the type Slot as a 32-bit modular integer. It is logically
+      --  split into the appropriate numbers of components of appropriate size,
+      --  but this splitting is not explicit because packed arrays cannot be
+      --  properly interfaced in C/C++ and packed records are way too slow.
+
+      Slot_Size : constant := 32;
+      type Slot is mod 2**Slot_Size;
+      for Slot'Size use Slot_Size;
+      pragma Provide_Shift_Operators (Slot);
+
+      type Field_1_Bit  is mod 2**1;
+      type Field_2_Bit  is mod 2**2;
+      type Field_4_Bit  is mod 2**4;
+      type Field_8_Bit  is mod 2**8;
       type Field_32_Bit is mod 2**32;
-      subtype Slot_32_Bit is Field_32_Bit; -- 1 32-bit field
-      pragma Assert (Slot_32_Bit'Size = 32);
-
-      type Slot (Field_Size : Field_Size_In_Bits := 9999) is record
-         case Field_Size is
-            when 1 => Slot_1 : Slot_1_Bit;
-            when 2 => Slot_2 : Slot_2_Bit;
-            when 4 => Slot_4 : Slot_4_Bit;
-            when 8 => Slot_8 : Slot_8_Bit;
-            when 32 => Slot_32 : Slot_32_Bit;
-            when others => null;
-         end case;
-      end record with Unchecked_Union;
-      pragma Assert (Slot'Size = 32);
 
       Slots_Low_Bound : constant Field_Offset := Field_Offset'First + 1;
 


diff --git a/gcc/ada/atree.h b/gcc/ada/atree.h
--- a/gcc/ada/atree.h
+++ b/gcc/ada/atree.h
@@ -72,144 +72,60 @@  extern Node_Id Current_Error_Node;
 extern Field_Offset *Node_Offsets_Ptr;
 extern any_slot *Slots_Ptr;
 
-INLINE Union_Id Get_1_Bit_Field (Node_Id N, Field_Offset Offset);
-INLINE Union_Id Get_2_Bit_Field (Node_Id N, Field_Offset Offset);
-INLINE Union_Id Get_4_Bit_Field (Node_Id N, Field_Offset Offset);
-INLINE Union_Id Get_8_Bit_Field (Node_Id N, Field_Offset Offset);
-INLINE Union_Id Get_32_Bit_Field (Node_Id N, Field_Offset Offset);
-INLINE Union_Id Get_32_Bit_Field_With_Default (Node_Id N, Field_Offset Offset,
-					       Union_Id Default_Value);
-
-INLINE Union_Id
+INLINE unsigned int Get_1_Bit_Field (Node_Id, Field_Offset);
+INLINE unsigned int Get_2_Bit_Field (Node_Id, Field_Offset);
+INLINE unsigned int Get_4_Bit_Field (Node_Id, Field_Offset);
+INLINE unsigned int Get_8_Bit_Field (Node_Id, Field_Offset);
+INLINE unsigned int Get_32_Bit_Field (Node_Id, Field_Offset);
+INLINE unsigned int Get_32_Bit_Field_With_Default (Node_Id, Field_Offset,
+						   unsigned int);
+
+INLINE unsigned int
 Get_1_Bit_Field (Node_Id N, Field_Offset Offset)
 {
-  const Field_Offset L = 32;
-
-  slot_1_bit slot = (Slots_Ptr + (Node_Offsets_Ptr[N] + Offset / L))->slot_1;
-
-  switch (Offset % L)
-    {
-    case 0: return slot.f0;
-    case 1: return slot.f1;
-    case 2: return slot.f2;
-    case 3: return slot.f3;
-    case 4: return slot.f4;
-    case 5: return slot.f5;
-    case 6: return slot.f6;
-    case 7: return slot.f7;
-    case 8: return slot.f8;
-    case 9: return slot.f9;
-    case 10: return slot.f10;
-    case 11: return slot.f11;
-    case 12: return slot.f12;
-    case 13: return slot.f13;
-    case 14: return slot.f14;
-    case 15: return slot.f15;
-    case 16: return slot.f16;
-    case 17: return slot.f17;
-    case 18: return slot.f18;
-    case 19: return slot.f19;
-    case 20: return slot.f20;
-    case 21: return slot.f21;
-    case 22: return slot.f22;
-    case 23: return slot.f23;
-    case 24: return slot.f24;
-    case 25: return slot.f25;
-    case 26: return slot.f26;
-    case 27: return slot.f27;
-    case 28: return slot.f28;
-    case 29: return slot.f29;
-    case 30: return slot.f30;
-    case 31: return slot.f31;
-    default: gcc_unreachable ();
-    }
+  const Field_Offset L = Slot_Size / 1;
+  any_slot slot = *(Slots_Ptr + Node_Offsets_Ptr[N] + Offset / L);
+  return (slot >> (Offset % L) * (Slot_Size / L)) & 1;
 }
 
-INLINE Union_Id
+INLINE unsigned int
 Get_2_Bit_Field (Node_Id N, Field_Offset Offset)
 {
-  const Field_Offset L = 16;
-
-  slot_2_bit slot = (Slots_Ptr + (Node_Offsets_Ptr[N] + Offset / L))->slot_2;
-
-  switch (Offset % L)
-    {
-    case 0: return slot.f0;
-    case 1: return slot.f1;
-    case 2: return slot.f2;
-    case 3: return slot.f3;
-    case 4: return slot.f4;
-    case 5: return slot.f5;
-    case 6: return slot.f6;
-    case 7: return slot.f7;
-    case 8: return slot.f8;
-    case 9: return slot.f9;
-    case 10: return slot.f10;
-    case 11: return slot.f11;
-    case 12: return slot.f12;
-    case 13: return slot.f13;
-    case 14: return slot.f14;
-    case 15: return slot.f15;
-    default: gcc_unreachable ();
-    }
+  const Field_Offset L = Slot_Size / 2;
+  any_slot slot = *(Slots_Ptr + Node_Offsets_Ptr[N] + Offset / L);
+  return (slot >> (Offset % L) * (Slot_Size / L)) & 3;
 }
 
-INLINE Union_Id
+INLINE unsigned int
 Get_4_Bit_Field (Node_Id N, Field_Offset Offset)
 {
-  const Field_Offset L = 8;
-
-  slot_4_bit slot = (Slots_Ptr + (Node_Offsets_Ptr[N] + Offset / L))->slot_4;
-
-  switch (Offset % L)
-    {
-    case 0: return slot.f0;
-    case 1: return slot.f1;
-    case 2: return slot.f2;
-    case 3: return slot.f3;
-    case 4: return slot.f4;
-    case 5: return slot.f5;
-    case 6: return slot.f6;
-    case 7: return slot.f7;
-    default: gcc_unreachable ();
-    }
+  const Field_Offset L = Slot_Size / 4;
+  any_slot slot = *(Slots_Ptr + Node_Offsets_Ptr[N] + Offset / L);
+  return (slot >> (Offset % L) * (Slot_Size / L)) & 15;
 }
 
-INLINE Union_Id
+INLINE unsigned int
 Get_8_Bit_Field (Node_Id N, Field_Offset Offset)
 {
-  const Field_Offset L = 4;
-
-  slot_8_bit slot = (Slots_Ptr + (Node_Offsets_Ptr[N] + Offset / L))->slot_8;
-
-  switch (Offset % L)
-    {
-    case 0: return slot.f0;
-    case 1: return slot.f1;
-    case 2: return slot.f2;
-    case 3: return slot.f3;
-    default: gcc_unreachable ();
-    }
+  const Field_Offset L = Slot_Size / 8;
+  any_slot slot = *(Slots_Ptr + Node_Offsets_Ptr[N] + Offset / L);
+  return (slot >> (Offset % L) * (Slot_Size / L)) & 255;
 }
 
-INLINE Union_Id
+INLINE unsigned int
 Get_32_Bit_Field (Node_Id N, Field_Offset Offset)
 {
   const Field_Offset L = 1;
-
-  slot_32_bit slot = (Slots_Ptr + (Node_Offsets_Ptr[N] + Offset / L))->slot_32;
-
+  any_slot slot = *(Slots_Ptr + Node_Offsets_Ptr[N] + Offset / L);
   return slot;
 }
 
-INLINE Union_Id
+INLINE unsigned int
 Get_32_Bit_Field_With_Default (Node_Id N, Field_Offset Offset,
-			       Union_Id Default_Value)
+			       unsigned int Default_Value)
 {
   const Field_Offset L = 1;
-
-  slot_32_bit slot = (Slots_Ptr + (Node_Offsets_Ptr[N] + Offset / L))->slot_32;
-
+  any_slot slot = *(Slots_Ptr + Node_Offsets_Ptr[N] + Offset / L);
   return slot == Empty ? Default_Value : slot;
 }
 


diff --git a/gcc/ada/types.h b/gcc/ada/types.h
--- a/gcc/ada/types.h
+++ b/gcc/ada/types.h
@@ -374,103 +374,15 @@  typedef Nat Small_Paren_Count_Type;
 
 typedef Nat Field_Offset;
 
-typedef struct
-{
-  unsigned f0 : 1;
-  unsigned f1 : 1;
-  unsigned f2 : 1;
-  unsigned f3 : 1;
-  unsigned f4 : 1;
-  unsigned f5 : 1;
-  unsigned f6 : 1;
-  unsigned f7 : 1;
-  unsigned f8 : 1;
-  unsigned f9 : 1;
-  unsigned f10 : 1;
-  unsigned f11 : 1;
-  unsigned f12 : 1;
-  unsigned f13 : 1;
-  unsigned f14 : 1;
-  unsigned f15 : 1;
-  unsigned f16 : 1;
-  unsigned f17 : 1;
-  unsigned f18 : 1;
-  unsigned f19 : 1;
-  unsigned f20 : 1;
-  unsigned f21 : 1;
-  unsigned f22 : 1;
-  unsigned f23 : 1;
-  unsigned f24 : 1;
-  unsigned f25 : 1;
-  unsigned f26 : 1;
-  unsigned f27 : 1;
-  unsigned f28 : 1;
-  unsigned f29 : 1;
-  unsigned f30 : 1;
-  unsigned f31 : 1;
-} slot_1_bit;
-
-typedef struct
-{
-  unsigned f0 : 2;
-  unsigned f1 : 2;
-  unsigned f2 : 2;
-  unsigned f3 : 2;
-  unsigned f4 : 2;
-  unsigned f5 : 2;
-  unsigned f6 : 2;
-  unsigned f7 : 2;
-  unsigned f8 : 2;
-  unsigned f9 : 2;
-  unsigned f10 : 2;
-  unsigned f11 : 2;
-  unsigned f12 : 2;
-  unsigned f13 : 2;
-  unsigned f14 : 2;
-  unsigned f15 : 2;
-} slot_2_bit;
-
-typedef struct
-{
-  unsigned f0 : 4;
-  unsigned f1 : 4;
-  unsigned f2 : 4;
-  unsigned f3 : 4;
-  unsigned f4 : 4;
-  unsigned f5 : 4;
-  unsigned f6 : 4;
-  unsigned f7 : 4;
-} slot_4_bit;
-
-typedef struct
-{
-  unsigned f0 : 8;
-  unsigned f1 : 8;
-  unsigned f2 : 8;
-  unsigned f3 : 8;
-} slot_8_bit;
-
-typedef Union_Id slot_32_bit;
+typedef unsigned int any_slot;
 
-typedef union
-{
-  slot_1_bit slot_1;
-  slot_2_bit slot_2;
-  slot_4_bit slot_4;
-  slot_8_bit slot_8;
-  slot_32_bit slot_32;
-} any_slot;
+#define Slot_Size (sizeof (any_slot) * 8)
 
 /* Slots are 32 bits (for now, but we might want to make that 64).
    The first bootstrap stage uses -std=gnu++98, so we cannot use
    static_assert in that case.  */
 #if __cplusplus >= 201402L
-static_assert (sizeof (slot_1_bit) == 4);
-static_assert (sizeof (slot_2_bit) == 4);
-static_assert (sizeof (slot_4_bit) == 4);
-static_assert (sizeof (slot_8_bit) == 4);
-static_assert (sizeof (slot_32_bit) == 4);
-static_assert (sizeof (any_slot) == 4);
+static_assert (Slot_Size == 32);
 #endif
 
 /* Definitions of Reason codes for Raise_xxx_Error nodes.  */