Pārlūkot izejas kodu

* Do not write the DWARF abbrev sections direclty, but use a searchtree to
search for an existing section with the same content first. This reduces the
generated executable size, compilation time and memory usage of the compiler

git-svn-id: trunk@15103 -

joost 15 gadi atpakaļ
vecāks
revīzija
95620e8774
1 mainītis faili ar 208 papildinājumiem un 36 dzēšanām
  1. 208 36
      compiler/dbgdwarf.pas

+ 208 - 36
compiler/dbgdwarf.pas

@@ -213,6 +213,19 @@ interface
         );
       tdwarfvarsymflags = set of tdwarfvarsymflag;
 
+      pAbbrevSearchTreeItem = ^tAbbrevSearchTreeItem;
+      tAbbrevSearchTreeItem = record
+        value: QWord;
+        Abbrev: longint;
+        // When this item does not match the abbrev-value, look for it
+        // in the next SearchItem
+        SearchItem: pAbbrevSearchTreeItem;
+        // Next and prior item of the abbrev-section
+        NextItem: pAbbrevSearchTreeItem;
+        PriorItem: pAbbrevSearchTreeItem;
+        bit8: boolean;
+      end;
+
       { TDebugInfoDwarf }
 
       TDebugInfoDwarf = class(TDebugInfo)
@@ -234,6 +247,20 @@ interface
         loclist: tdynamicarray;
         asmline: TAsmList;
 
+        // The current entry in dwarf_info with the link to the abbrev-section
+        dwarf_info_abbref_tai: tai_const;
+        // Empty start-item of the abbrev-searchtree
+        AbbrevSearchTree: pAbbrevSearchTreeItem;
+        // The current abbrev-item
+        CurrentSearchTreeItem: pAbbrevSearchTreeItem;
+        // Is true when the abbrev-section is newly created
+        NewAbbrev: boolean;
+        procedure StartAbbrevSearch;
+        procedure AddConstToAbbrev(Value: QWord; bit8:boolean=false);
+        procedure StartAbbrevSectionFromSearchtree;
+        procedure WriteSearchItemToAbbrevSection(SI: pAbbrevSearchTreeItem);
+        function FinishAbbrevSearch: longint;
+
         function def_dwarf_lab(def:tdef) : tasmsymbol;
         function def_dwarf_ref_lab(def:tdef) : tasmsymbol;
         function def_dwarf_class_struct_lab(def:tobjectdef) : tasmsymbol;
@@ -618,6 +645,21 @@ implementation
       end;
 
 
+    function AllocateNewAiSearchItem: pAbbrevSearchTreeItem;
+      begin
+        new(result);
+        FillChar(result^,sizeof(result^),#0);
+      end;
+
+    procedure FreeSearchItem(SI: pAbbrevSearchTreeItem);
+      begin
+        if assigned(SI^.NextItem) then
+          FreeSearchItem(SI^.NextItem);
+        if assigned(SI^.SearchItem) then
+          FreeSearchItem(SI^.SearchItem);
+        Dispose(SI);
+      end;
+
 {****************************************************************************
                               TDirIndexItem
 ****************************************************************************}
@@ -653,6 +695,134 @@ implementation
                               TDebugInfoDwarf
 ****************************************************************************}
 
+    procedure TDebugInfoDwarf.StartAbbrevSearch;
+      begin
+        CurrentSearchTreeItem:=AbbrevSearchTree;
+      end;
+
+
+    procedure TDebugInfoDwarf.WriteSearchItemToAbbrevSection(SI: pAbbrevSearchTreeItem);
+      begin
+        if SI^.bit8 then
+          current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.Create_8bit(SI^.value))
+        else
+          current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.Create_uleb128bit(SI^.value));
+      end;
+
+
+    procedure TDebugInfoDwarf.StartAbbrevSectionFromSearchtree;
+
+      procedure AddCurrentAndPriorItemsToAbrev(SI: pAbbrevSearchTreeItem);
+        begin
+          if assigned(SI^.PriorItem) then
+            AddCurrentAndPriorItemsToAbrev(SI^.PriorItem);
+          WriteSearchItemToAbbrevSection(SI);
+        end;
+
+      begin
+        NewAbbrev:=true;
+        inc(currabbrevnumber);
+        current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_comment.Create(strpnew('Abbrev '+tostr(currabbrevnumber))));
+        current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(currabbrevnumber));
+
+        if CurrentSearchTreeItem<>AbbrevSearchTree then
+          AddCurrentAndPriorItemsToAbrev(CurrentSearchTreeItem);
+      end;
+
+
+    function TDebugInfoDwarf.FinishAbbrevSearch: longint;
+
+      procedure FinalizeAbbrevSection;
+        begin
+          current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_8bit(0));
+          current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_8bit(0));
+          CurrentSearchTreeItem^.Abbrev:=currabbrevnumber;
+          NewAbbrev := false;
+        end;
+
+      begin
+        if NewAbbrev then
+          FinalizeAbbrevSection;
+        result := CurrentSearchTreeItem^.Abbrev;
+        if result=0 then
+          begin
+            // In this case the abbrev-section equals an existing longer abbrev section.
+            // So a new abbrev-section has to be made which ends on the current
+            // searchtree item
+            StartAbbrevSectionFromSearchtree;
+            FinalizeAbbrevSection;
+            result := CurrentSearchTreeItem^.Abbrev;
+          end;
+      end;
+
+
+    procedure TDebugInfoDwarf.AddConstToAbbrev(Value: QWord; bit8:boolean);
+
+        procedure AddCurrentItemToAbbrev;
+          begin
+            CurrentSearchTreeItem^.value:=value;
+            CurrentSearchTreeItem^.bit8:=bit8;
+            WriteSearchItemToAbbrevSection(CurrentSearchTreeItem);
+          end;
+
+      var si: pAbbrevSearchTreeItem;
+      begin
+        // Instead of adding this value directly to the ai-tree, search if an
+        // abbrev section with the same values already exist, and use the existing
+        // one or create one.
+        if NewAbbrev then
+          begin
+          // The current abbrev-section is new, so add the value to the abbrev-section
+          // and add it to the search-list.
+          CurrentSearchTreeItem^.NextItem:=AllocateNewAiSearchItem;
+          CurrentSearchTreeItem^.NextItem^.PriorItem:=CurrentSearchTreeItem;
+          CurrentSearchTreeItem := CurrentSearchTreeItem^.NextItem;
+          AddCurrentItemToAbbrev;
+          end
+        else
+          begin
+          // Search for the value which is added in the next sections of the
+          // searchtree for a match
+          si := CurrentSearchTreeItem^.NextItem;
+          while assigned(si) do
+            begin
+              if (SI^.value=Value) and (si^.bit8=bit8) then
+                begin
+                // If a match is found, set the current searchtree item to the next item
+                CurrentSearchTreeItem:=SI;
+                Exit;
+                end
+              else if si^.SearchItem=nil then
+                begin
+                // If no match is found, add a new item to the searchtree and write
+                // a new abbrev-section.
+                StartAbbrevSectionFromSearchtree;
+
+                si^.SearchItem:=AllocateNewAiSearchItem;
+                if currentsearchtreeitem<>AbbrevSearchTree then
+                  si^.SearchItem^.PriorItem:=CurrentSearchTreeItem;
+                CurrentSearchTreeItem := si^.SearchItem;
+
+                AddCurrentItemToAbbrev;
+                Exit;
+                end;
+              Si := SI^.SearchItem;
+            end;
+          // The abbrev section we are looking for is longer than the one
+          // which is already in the search-tree. So expand the searchtree with
+          // the new value and write a new abbrev section
+          StartAbbrevSectionFromSearchtree;
+
+          CurrentSearchTreeItem^.NextItem:=AllocateNewAiSearchItem;
+          if currentsearchtreeitem^.PriorItem<>AbbrevSearchTree then
+            CurrentSearchTreeItem^.NextItem^.PriorItem:=CurrentSearchTreeItem;
+          CurrentSearchTreeItem := CurrentSearchTreeItem^.NextItem;
+
+          AddCurrentItemToAbbrev;
+          end;
+      end;
+
+
     function TDebugInfoDwarf.relative_dwarf_path(const s:tcmdstr):tcmdstr;
       begin
         { Make a clean path for gdb. Remove trailing / and ./ prefixes and
@@ -780,12 +950,16 @@ implementation
         TDirIndexItem.Create(dirlist,'.', 0);
         asmline := TAsmList.create;
         loclist := tdynamicarray.Create(4096);
+
+        AbbrevSearchTree:=AllocateNewAiSearchItem;
       end;
 
 
     destructor TDebugInfoDwarf.Destroy;
       begin
         dirlist.Free;
+        if assigned(AbbrevSearchTree) then
+          FreeSearchItem(AbbrevSearchTree);
         dirlist := nil;
         asmline.free;
         asmline:=nil;
@@ -849,10 +1023,10 @@ implementation
     procedure TDebugInfoDwarf.append_attribute(attr: tdwarf_attribute; form: tdwarf_form; const value: tvarrec);
       begin
         { attribute }
-        current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(cardinal(attr)));
+        AddConstToAbbrev(cardinal(attr));
 
         { form }
-        current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(cardinal(form)));
+        AddConstToAbbrev(cardinal(form));
 
         { info itself }
         case form of
@@ -967,19 +1141,18 @@ implementation
       var
         i : longint;
       begin
-        { todo: store defined abbrevs, so you have to define tehm only once (for this unit) (MWE) }
-        inc(currabbrevnumber);
-
-        current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_comment.Create(strpnew('Abbrev '+tostr(currabbrevnumber))));
-
         { abbrev number }
-        current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_uleb128bit(currabbrevnumber));
-        current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(currabbrevnumber));
+        // Store the ai with the reference to the abbrev number and start a search
+        // to find the right abbrev-section. (Or create one)
+        dwarf_info_abbref_tai := tai_const.create_uleb128bit(currabbrevnumber);
+        current_asmdata.asmlists[al_dwarf_info].concat(dwarf_info_abbref_tai);
+        StartAbbrevSearch;
+
         { tag }
-        current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(ord(tag)));
+        AddConstToAbbrev(ord(tag));
 
         { children? }
-        current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_8bit(ord(has_children)));
+        AddConstToAbbrev(ord(has_children),true);
 
         i:=0;
         while i<=high(data) do
@@ -998,33 +1171,33 @@ implementation
 
     procedure TDebugInfoDwarf.append_block1(attr: tdwarf_attribute; size: aint);
       begin
-        current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(ord(attr)));
-        current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(ord(DW_FORM_block1)));
+        AddConstToAbbrev(ord(attr));
+        AddConstToAbbrev(ord(DW_FORM_block1));
         current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(size));
       end;
 
 
     procedure TDebugInfoDwarf.append_labelentry(attr : tdwarf_attribute;sym : tasmsymbol);
       begin
-        current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(ord(attr)));
-        current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(ord(DW_FORM_addr)));
+        AddConstToAbbrev(ord(attr));
+        AddConstToAbbrev(ord(DW_FORM_addr));
         current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_sym(sym));
       end;
 
     procedure TDebugInfoDwarf.append_labelentry_addr_ref(attr : tdwarf_attribute;sym : tasmsymbol);
       begin
-        current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(ord(DW_FORM_ref_addr)));
+        AddConstToAbbrev(ord(DW_FORM_ref_addr));
         current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_sym(sym))
       end;
 
     procedure TDebugInfoDwarf.append_labelentry_ref(attr : tdwarf_attribute;sym : tasmsymbol);
       begin
-        current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(ord(attr)));
+        AddConstToAbbrev(ord(attr));
         if not(tf_dwarf_only_local_labels in target_info.flags) then
           append_labelentry_addr_ref(attr, sym)
         else
           begin
-            current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(ord(DW_FORM_ref4)));
+            AddConstToAbbrev(ord(DW_FORM_ref4));
             current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_rel_sym(offsetreltype,current_asmdata.RefAsmSymbol(target_asm.labelprefix+'debug_info0'),sym));
           end;
       end;
@@ -1032,11 +1205,11 @@ implementation
 
     procedure TDebugInfoDwarf.append_labelentry_dataptr_common(attr : tdwarf_attribute);
       begin
-        current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(ord(attr)));
+        AddConstToAbbrev(ord(attr));
         if use_64bit_headers then
-          current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(ord(DW_FORM_data8)))
+          AddConstToAbbrev(ord(DW_FORM_data8))
         else
-          current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(ord(DW_FORM_data4)));
+          AddConstToAbbrev(ord(DW_FORM_data4));
       end;
 
 
@@ -1071,8 +1244,7 @@ implementation
 
     procedure TDebugInfoDwarf.finish_entry;
       begin
-        current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_8bit(0));
-        current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_8bit(0));
+        dwarf_info_abbref_tai.value:=FinishAbbrevSearch;
       end;
 
 
@@ -2319,7 +2491,7 @@ implementation
           end;
         if assigned(usedef) then
           append_labelentry_ref(DW_AT_type,def_dwarf_lab(usedef));
-        current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(ord(DW_AT_const_value)));
+        AddConstToAbbrev(ord(DW_AT_const_value));
         case sym.consttyp of
           conststring:
             begin
@@ -2327,13 +2499,13 @@ implementation
                 -> create a string using raw bytes }
               if (sym.value.len<=255) then
                 begin
-                  current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(ord(DW_FORM_block1)));
+                  AddConstToAbbrev(ord(DW_FORM_block1));
                   current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(sym.value.len+1));
                   current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(sym.value.len));
                 end
               else
                 begin
-                  current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(ord(DW_FORM_block)));
+                  AddConstToAbbrev(ord(DW_FORM_block));
                   current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_uleb128bit(sym.value.len+sizeof(pint)));
                   current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_pint(sym.value.len));
                 end;
@@ -2348,7 +2520,7 @@ implementation
           constguid,
           constset:
             begin
-              current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(ord(DW_FORM_block1)));
+              AddConstToAbbrev(ord(DW_FORM_block1));
               current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(usedef.size));
               i:=0;
               size:=sym.constdef.size;
@@ -2362,7 +2534,7 @@ implementation
           constresourcestring:
             begin
               { write dummy for now }
-              current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(ord(DW_FORM_string)));
+              AddConstToAbbrev(ord(DW_FORM_string));
               current_asmdata.asmlists[al_dwarf_info].concat(tai_string.create(''));
               current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_8bit(0));
             end;
@@ -2370,38 +2542,38 @@ implementation
             begin
               if (sym.value.valueord<0) then
                 begin
-                  current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(ord(DW_FORM_sdata)));
+                  AddConstToAbbrev(ord(DW_FORM_sdata));
                   current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_sleb128bit(sym.value.valueord.svalue));
                 end
               else
                 begin
-                  current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(ord(DW_FORM_udata)));
+                  AddConstToAbbrev(ord(DW_FORM_udata));
                   current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_uleb128bit(sym.value.valueord.uvalue));
                 end;
             end;
           constnil:
             begin
 {$ifdef cpu64bitaddr}
-              current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(ord(DW_FORM_data8)));
+              AddConstToAbbrev(ord(DW_FORM_data8));
               current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_64bit(0));
 {$else cpu64bitaddr}
-              current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(ord(DW_FORM_data4)));
+              AddConstToAbbrev(ord(DW_FORM_data4));
               current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_32bit(0));
 {$endif cpu64bitaddr}
             end;
           constpointer:
             begin
 {$ifdef cpu64bitaddr}
-              current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(ord(DW_FORM_data8)));
+              AddConstToAbbrev(ord(DW_FORM_data8));
               current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_64bit(int64(sym.value.valueordptr)));
 {$else cpu64bitaddr}
-              current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(ord(DW_FORM_data4)));
+              AddConstToAbbrev(ord(DW_FORM_data4));
               current_asmdata.asmlists[al_dwarf_info].concat(tai_const.create_32bit(longint(sym.value.valueordptr)));
 {$endif cpu64bitaddr}
             end;
           constreal:
             begin
-              current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(ord(DW_FORM_block1)));
+              AddConstToAbbrev(ord(DW_FORM_block1));
               case tfloatdef(sym.constdef).floattype of
                 s32real:
                   begin
@@ -3397,7 +3569,7 @@ implementation
 
     procedure TDebugInfoDwarf3.append_labelentry_addr_ref(attr : tdwarf_attribute;sym : tasmsymbol);
       begin
-        current_asmdata.asmlists[al_dwarf_abbrev].concat(tai_const.create_uleb128bit(ord(DW_FORM_ref_addr)));
+        AddConstToAbbrev(ord(DW_FORM_ref_addr));
         { Since Dwarf 3 the length of a DW_FORM_ref_addr entry is not dependent on the pointer size of the
           target platform, but on the used Dwarf-format (32 bit or 64 bit) for the current compilation section. }
         if use_64bit_headers then