diff options
| author | Tristan Gingold <tgingold@free.fr> | 2017-11-11 09:43:30 +0100 | 
|---|---|---|
| committer | Tristan Gingold <tgingold@free.fr> | 2017-11-11 09:43:30 +0100 | 
| commit | 8e1372ff23dc77e94bd4c7b52544a4873fab261b (patch) | |
| tree | 107a9938be105ecfab44827cf9de11989b008d5a /src | |
| parent | f589c5c13fb533aa3c29453a2916d1da6fec8e11 (diff) | |
| download | ghdl-8e1372ff23dc77e94bd4c7b52544a4873fab261b.tar.gz ghdl-8e1372ff23dc77e94bd4c7b52544a4873fab261b.tar.bz2 ghdl-8e1372ff23dc77e94bd4c7b52544a4873fab261b.zip  | |
Rewrite list implementation
Diffstat (limited to 'src')
| -rw-r--r-- | src/lists.adb | 236 | ||||
| -rw-r--r-- | src/lists.ads | 26 | ||||
| -rw-r--r-- | src/vhdl/disp_vhdl.adb | 6 | ||||
| -rw-r--r-- | src/vhdl/iirs.ads | 2 | 
4 files changed, 115 insertions, 155 deletions
diff --git a/src/lists.adb b/src/lists.adb index 37a5f74da..cccfb76db 100644 --- a/src/lists.adb +++ b/src/lists.adb @@ -15,18 +15,14 @@  --  along with GHDL; see the file COPYING.  If not, write to the Free  --  Software Foundation, 59 Temple Place - Suite 330, Boston, MA  --  02111-1307, USA. -with System;  with Tables;  package body Lists is -   type Node_Array_Fat is array (Natural) of Node_Type; -   type Node_Array_Fat_Acc is access Node_Array_Fat; -     type List_Record is record -      Max : Natural; +      First : Chunk_Index_Type; +      Last : Chunk_Index_Type; +      Chunk_Idx : Nat32;        Nbr : Natural; -      Next : List_Type; -      Els : Node_Array_Fat_Acc;     end record;     package Listt is new Tables @@ -35,227 +31,183 @@ package body Lists is        Table_Low_Bound => 2,        Table_Initial => 128); -   --function Get_Max_Nbr_Elements (List : List_Type) return Natural; -   --pragma Inline (Get_Max_Nbr_Elements); +   package Chunkt is new Tables +     (Table_Component_Type => Chunk_Type, +      Table_Index_Type => Chunk_Index_Type, +      Table_Low_Bound => 1, +      Table_Initial => 128); + +   Chunk_Free_List : Chunk_Index_Type := No_Chunk_Index; -   --procedure Set_Max_Nbr_Elements (List : List_Type; Max : Natural); -   --pragma Inline (Set_Max_Nbr_Elements); +   procedure Free_Chunk (Idx : Chunk_Index_Type) is +   begin +      Chunkt.Table (Idx).Next := Chunk_Free_List; +      Chunk_Free_List := Idx; +   end Free_Chunk; -   procedure List_Set_Nbr_Elements (List : List_Type; Nbr : Natural); -   pragma Inline (List_Set_Nbr_Elements); +   function Get_Free_Chunk return Chunk_Index_Type +   is +      Res : Chunk_Index_Type; +   begin +      if Chunk_Free_List /= No_Chunk_Index then +         Res := Chunk_Free_List; +         Chunk_Free_List := Chunkt.Table (Res).Next; +         return Res; +      else +         return Chunkt.Allocate; +      end if; +   end Get_Free_Chunk;     function Get_Nbr_Elements (List: List_Type) return Natural is     begin        return Listt.Table (List).Nbr;     end Get_Nbr_Elements; -   procedure List_Set_Nbr_Elements (List : List_Type; Nbr : Natural) is -   begin -      Listt.Table (List).Nbr := Nbr; -   end List_Set_Nbr_Elements; -     function Is_Empty (List : List_Type) return Boolean is     begin        return Listt.Table (List).Nbr = 0;     end Is_Empty; -   --function Get_Max_Nbr_Elements (List : List_Type) return Natural is -   --begin -   --   return Listt.Table (List).Max; -   --end Get_Max_Nbr_Elements; - -   --procedure Set_Max_Nbr_Elements (List : List_Type; Max : Natural) is -   --begin -   --   Listt.Table (List).Max := Max; -   --end Set_Max_Nbr_Elements; - -   function Get_Nth_Element (List: List_Type; N: Natural) -     return Node_Type -   is -   begin -      if N >= Listt.Table (List).Nbr then -         return Null_Node; -      end if; -      return Listt.Table (List).Els (N); -   end Get_Nth_Element; - -   -- Replace an element selected by position. -   procedure Replace_Nth_Element (List: List_Type; N: Natural; El: Node_Type) -   is -   begin -      if N >= Listt.Table (List).Nbr then -         raise Program_Error; -      end if; -      Listt.Table (List).Els (N) := El; -   end Replace_Nth_Element; - -   -- Be sure an element can be added to LIST. -   -- It doesn't change the number of elements. -   procedure List_Grow (List: List_Type) -   is -      L : List_Record renames Listt.Table (List); - -      --  Be careful: size in bytes. -      function Alloc (Size : Natural) return Node_Array_Fat_Acc; -      pragma Import (C, Alloc, "malloc"); - -      function Realloc (Ptr : Node_Array_Fat_Acc; Size : Natural) -        return Node_Array_Fat_Acc; -      pragma Import (C, Realloc, "realloc"); - -      Tmp : Node_Array_Fat_Acc; -      N : Natural; -   begin -      if L.Nbr < L.Max then -         return; -      end if; -      if L.Max = 0 then -         N := 8; -         Tmp := Alloc (N * Node_Type'Size / System.Storage_Unit); -      else -         N := L.Max * 2; -         Tmp := Realloc (L.Els, N * Node_Type'Size / System.Storage_Unit); -      end if; -      L.Els := Tmp; -      L.Max := N; -   end List_Grow; -     procedure Append_Element (List: List_Type; Element: Node_Type)     is        L : List_Record renames Listt.Table (List); +      C : Chunk_Index_Type;     begin -      if L.Nbr >= L.Max then -         List_Grow (List); +      L.Chunk_Idx := L.Chunk_Idx + 1; +      if L.Chunk_Idx < Chunk_Len then +         Chunkt.Table (L.Last).Els (L.Chunk_Idx) := Element; +      else +         C := Get_Free_Chunk; +         Chunkt.Table (C).Next := No_Chunk_Index; +         Chunkt.Table (C).Els (0) := Element; +         L.Chunk_Idx := 0; +         if L.Nbr = 0 then +            L.First := C; +         else +            Chunkt.Table (L.Last).Next := C; +         end if; +         L.Last := C;        end if; -      L.Els (L.Nbr) := Element;        L.Nbr := L.Nbr + 1;     end Append_Element; -   -- Return the last element of the list, or null. -   -- Return the first element of the list, or null. -   function Get_First_Element (List: List_Type) return Node_Type is +   function Get_First_Element (List: List_Type) return Node_Type +   is +      L : List_Record renames Listt.Table (List);     begin -      if Listt.Table (List).Nbr = 0 then -         return Null_Node; -      else -         return Listt.Table (List).Els (0); -      end if; +      pragma Assert (L.Nbr > 0); +      return Chunkt.Table (L.First).Els (0);     end Get_First_Element;     -- Add (append) an element only if it was not already present in the list.     procedure Add_Element (List: List_Type; El: Node_Type)     is -      Nbr : constant Natural := Get_Nbr_Elements (List); +      It : Iterator;     begin -      for I in 0 .. Nbr - 1 loop -         if Listt.Table (List).Els (I) = El then +      It := Iterate (List); +      while Is_Valid (It) loop +         if Get_Element (It) = El then              return;           end if; +         Next (It);        end loop;        Append_Element (List, El);     end Add_Element; -   procedure Set_Nbr_Elements (List: List_Type; N: Natural) is -   begin -      if N > Get_Nbr_Elements (List) then -         raise Program_Error; -      end if; -      List_Set_Nbr_Elements (List, N); -   end Set_Nbr_Elements; -     --  Chain of unused lists. -   Free_Chain : List_Type := Null_List; +   List_Free_Chain : List_Type := Null_List;     function Create_List return List_Type     is        Res : List_Type;     begin -      if Free_Chain = Null_List then +      if List_Free_Chain = Null_List then           Listt.Increment_Last;           Res := Listt.Last;        else -         Res := Free_Chain; -         Free_Chain := Listt.Table (Res).Next; +         Res := List_Free_Chain; +         List_Free_Chain := List_Type (Listt.Table (Res).Chunk_Idx);        end if; -      Listt.Table (Res) := List_Record'(Max => 0, Nbr => 0, -                                        Next => Null_List, Els => null); +      Listt.Table (Res) := List_Record'(First => No_Chunk_Index, +                                        Last => No_Chunk_Index, +                                        Chunk_Idx => Chunk_Len, +                                        Nbr => 0);        return Res;     end Create_List; -   procedure Free (Ptr : Node_Array_Fat_Acc); -   pragma Import (C, Free, "free"); -     procedure Destroy_List (List : in out List_Type)     is +      C, Next_C : Chunk_Index_Type;     begin        if List = Null_List then           return;        end if; -      if Listt.Table (List).Max > 0 then -         Free (Listt.Table (List).Els); -         Listt.Table (List).Els := null; -      end if; -      Listt.Table (List).Next := Free_Chain; -      Free_Chain := List; + +      C := Listt.Table (List).First; +      while C /= No_Chunk_Index loop +         Next_C := Chunkt.Table (C).Next; +         Free_Chunk (C); +         C := Next_C; +      end loop; + +      Listt.Table (List).Chunk_Idx := Nat32 (List_Free_Chain); +      List_Free_Chain := List; +        List := Null_List;     end Destroy_List;     procedure Initialize is     begin -      for I in Listt.First .. Listt.Last loop -         if Listt.Table (I).Els /= null then -            Free (Listt.Table (I).Els); -         end if; -      end loop;        Listt.Free;        Listt.Init; +      Chunkt.Free; +      Chunkt.Init; +      List_Free_Chain := Null_List; +      Chunk_Free_List := No_Chunk_Index;     end Initialize; -   function Iterate (List : List_Type) return Iterator is +   function Iterate (List : List_Type) return Iterator +   is +      L : List_Record renames Listt.Table (List);     begin -      return Iterator'(List => List, -                       Len => Get_Nbr_Elements (List), -                       Idx => 0); +      return Iterator'(Chunk => L.First, +                       Chunk_Idx => 0, +                       Remains => L.Nbr);     end Iterate;     function Iterate_Safe (List : List_Type) return Iterator is     begin        if List = Null_List then -         return Iterator'(List => Null_List, -                          Len => 0, -                          Idx => 0); +         return Iterator'(Chunk => No_Chunk_Index, +                          Chunk_Idx => 0, +                          Remains => 0);        end if;        return Iterate (List);     end Iterate_Safe;     function Is_Valid (It : Iterator) return Boolean is     begin -      return It.Idx < It.Len; +      return It.Remains > 0;     end Is_Valid; -   function Is_First (It : Iterator) return Boolean is -   begin -      return It.Idx = 0; -   end Is_First; -     procedure Next (It : in out Iterator) is     begin -      It.Idx := It.Idx + 1; +      It.Chunk_Idx := It.Chunk_Idx + 1; +      if It.Chunk_Idx = Chunk_Len then +         It.Chunk := Chunkt.Table (It.Chunk).Next; +         It.Chunk_Idx := 0; +      end if; +      It.Remains := It.Remains - 1;     end Next;     function Get_Element (It : Iterator) return Node_Type is     begin -      return Get_Nth_Element (It.List, It.Idx); +      return Chunkt.Table (It.Chunk).Els (It.Chunk_Idx);     end Get_Element;     procedure Set_Element (It : Iterator; El : Node_Type) is     begin -      Replace_Nth_Element (It.List, It.Idx, El); +      Chunkt.Table (It.Chunk).Els (It.Chunk_Idx) := El;     end Set_Element; - -   procedure Truncate (It : Iterator) is -   begin -      Set_Nbr_Elements (It.List, It.Idx); -   end Truncate;  end Lists; diff --git a/src/lists.ads b/src/lists.ads index 9f5729e9b..07e319d9f 100644 --- a/src/lists.ads +++ b/src/lists.ads @@ -88,10 +88,6 @@ package Lists is     --  True if LIST is empty.     function Is_Empty (List : List_Type) return Boolean; -   -- Set the number of elements in the list. -   -- Can be used only to shrink the list. -   procedure Set_Nbr_Elements (List: List_Type; N: Natural); -     --  Iterator.  The idiomatic way to iterate is:     --  It := Iterate (List);     --  while Is_Valid (It) loop @@ -103,21 +99,31 @@ package Lists is     function Iterate (List : List_Type) return Iterator;     function Is_Valid (It : Iterator) return Boolean; -   function Is_First (It : Iterator) return Boolean;     procedure Next (It : in out Iterator);     function Get_Element (It : Iterator) return Node_Type;     procedure Set_Element (It : Iterator; El : Node_Type); -   procedure Truncate (It : Iterator); -     --  Like Iterate, but if LIST is Null_List, it returns an iterator that is     --  never valid.     function Iterate_Safe (List : List_Type) return Iterator;  private +   type Chunk_Index_Type is new Int32; +   No_Chunk_Index : constant Chunk_Index_Type := 0; + +   Chunk_Len : constant := 7; + +   type Node_Type_Array is +     array (Nat32 range 0 .. Chunk_Len - 1) of Node_Type; + +   type Chunk_Type is record +      Next : Chunk_Index_Type; +      Els : Node_Type_Array; +   end record; +     type Iterator is record -      List : List_Type; -      Len : Natural; -      Idx : Natural; +      Chunk : Chunk_Index_Type; +      Chunk_Idx : Nat32; +      Remains : Natural;     end record;     pragma Inline (Is_Valid); diff --git a/src/vhdl/disp_vhdl.adb b/src/vhdl/disp_vhdl.adb index 744e1f9a2..c35dcfd50 100644 --- a/src/vhdl/disp_vhdl.adb +++ b/src/vhdl/disp_vhdl.adb @@ -794,6 +794,7 @@ package body Disp_Vhdl is     is        El : Iir;        It : List_Iterator; +      Is_First : Boolean;     begin        case List is           when Null_Iir_List => @@ -802,10 +803,13 @@ package body Disp_Vhdl is              Put ("all");           when others =>              It := List_Iterate (List); +            Is_First := True;              while Is_Valid (It) loop                 El := Get_Element (It); -               if not Is_First (It) then +               if not Is_First then                    Put (", "); +               else +                  Is_First := False;                 end if;                 Disp_Expression (El);                 Next (It); diff --git a/src/vhdl/iirs.ads b/src/vhdl/iirs.ads index 4d18f3f88..6b5de4661 100644 --- a/src/vhdl/iirs.ads +++ b/src/vhdl/iirs.ads @@ -5396,8 +5396,6 @@ package Iirs is       renames Lists.Iterate_Safe;     function Is_Valid (It : List_Iterator) return Boolean       renames Lists.Is_Valid; -   function Is_First (It : List_Iterator) return Boolean -     renames Lists.Is_First;     procedure Next (It : in out List_Iterator)       renames Lists.Next;     function Get_Element (It : List_Iterator) return Iir  | 
