Browse Source

To correctly generate the import library for a package we need to resolve the dangling external symbols of all units. For this each unit now stores which symbols it exported from another unit and it also stores all global and external assembler symbols it has (maybe this can be streamlined later on, but for now this works).

entfile.pas:
  + new entry for the imported unit symbols; for the global assembler symbols a deprecated entry is revived
fmodule.pas, tmodule:
  + new field globalasmsyms which holds all global/external assembler symbols of a unit
  + new field unitimportsyms which holds all symbols imported by a unit from another unit
  + new method to extract all global/external assembler symbols of a unit
  * create, destroy & reset: correctly instantiate/free the two new lists
fppu.pas, tppumodule:
  + new field unitimportsymsderefs to hold the derefs during loading from/storing to PPU
  + new method buildderefunitimportsyms to generate the derefs for each imported symbol
  + new method derefunitimportsyms to resolve each imported symbol deref
  + new method readunitimportsyms to read the imported symbols from the PPU
  + new method writeunitimportsyms to write all imported symbols to the PPU
  + new method writeasmsymbols to write all global/external assembler symbols to the PPU
  + new method readasmsymbols to read all global/external assembler symbols from the PPU
  * load_implementation: read the assembler symbols and the imported symbols if their respective entry is encountered
  * writeppu: generate the derefs and write them and the assembler symbols to PPU
  * load_usedunits: resolve the imported symbols once all derefs are known
pmoudles.pas:
  * finish_unit: extract all global/external assembler symbols before writing the PPU
symtable.pas:
  * addsymref: if the symbol is not from the current unit than mark it as imported
ppu.pas:
  * increase PPU version

git-svn-id: branches/svenbarth/packages@28846 -
svenbarth 10 years ago
parent
commit
6f15aef215
6 changed files with 163 additions and 11 deletions
  1. 1 0
      compiler/entfile.pas
  2. 27 0
      compiler/fmodule.pas
  3. 114 2
      compiler/fppu.pas
  4. 6 1
      compiler/pmodules.pas
  5. 1 1
      compiler/ppu.pas
  6. 14 7
      compiler/symtable.pas

+ 1 - 0
compiler/entfile.pas

@@ -113,6 +113,7 @@ interface
     ibcreatedobjtypes = 83;
     ibcreatedobjtypes = 83;
     ibwpofile         = 84;
     ibwpofile         = 84;
     ibmoduleoptions   = 85;
     ibmoduleoptions   = 85;
+    ibunitimportsyms  = 86;
 
 
     ibmainname            = 90;
     ibmainname            = 90;
     ibsymtableoptions     = 91;
     ibsymtableoptions     = 91;

+ 27 - 0
compiler/fmodule.pas

@@ -153,6 +153,9 @@ interface
         scanner       : TObject;  { scanner object used }
         scanner       : TObject;  { scanner object used }
         procinfo      : TObject;  { current procedure being compiled }
         procinfo      : TObject;  { current procedure being compiled }
         asmdata       : TObject;  { Assembler data }
         asmdata       : TObject;  { Assembler data }
+        globalasmsyms : TFPHashObjectList; { contains the assembler symbols which can potentially be exported for e.g. packages;
+                                             it's filled either by loading from a ppu or after parsing the unit has finished }
+        unitimportsyms: tfpobjectlist;
         asmprefix     : pshortstring;  { prefix for the smartlink asmfiles }
         asmprefix     : pshortstring;  { prefix for the smartlink asmfiles }
         debuginfo     : TObject;
         debuginfo     : TObject;
         loaded_from   : tmodule;
         loaded_from   : tmodule;
@@ -225,6 +228,7 @@ interface
         function  resolve_unit(id:longint):tmodule;
         function  resolve_unit(id:longint):tmodule;
         procedure allunitsused;
         procedure allunitsused;
         procedure end_of_parsing;virtual;
         procedure end_of_parsing;virtual;
+        procedure extractexportasmsyms;
         procedure setmodulename(const s:string);
         procedure setmodulename(const s:string);
         procedure AddExternalImport(const libname,symname,symmangledname:string;OrdNr: longint;isvar:boolean;ImportByOrdinalOnly:boolean);
         procedure AddExternalImport(const libname,symname,symmangledname:string;OrdNr: longint;isvar:boolean;ImportByOrdinalOnly:boolean);
         property ImportLibraryList : TFPHashObjectList read FImportLibraryList;
         property ImportLibraryList : TFPHashObjectList read FImportLibraryList;
@@ -510,6 +514,21 @@ implementation
                                   TMODULE
                                   TMODULE
  ****************************************************************************}
  ****************************************************************************}
 
 
+    procedure tmodule.extractexportasmsyms;
+      var
+        symold,symnew : tasmsymbol;
+        i : longint;
+        n : string;
+      begin
+        for i:=0 to tasmdata(asmdata).AsmSymbolDict.Count-1 do
+          begin
+            symold:=tasmsymbol(tasmdata(asmdata).asmsymboldict[i]);
+            n:=symold.name;
+            if (symold.classtype=tasmsymbol) and (symold.bind in [AB_GLOBAL,AB_EXTERNAL,AB_WEAK_EXTERNAL]) then
+              symnew:=tasmsymbol.create(globalasmsyms,symold.name,symold.bind,symold.typ);
+          end;
+      end;
+
     constructor tmodule.create(LoadedFrom:TModule;const amodulename: string; const afilename:TPathStr;_is_unit:boolean);
     constructor tmodule.create(LoadedFrom:TModule;const amodulename: string; const afilename:TPathStr;_is_unit:boolean);
       var
       var
         n:string;
         n:string;
@@ -602,6 +621,8 @@ implementation
         _exports:=TLinkedList.Create;
         _exports:=TLinkedList.Create;
         dllscannerinputlist:=TFPHashList.Create;
         dllscannerinputlist:=TFPHashList.Create;
         asmdata:=casmdata.create(modulename);
         asmdata:=casmdata.create(modulename);
+        globalasmsyms:=tfphashobjectlist.create(true);
+        unitimportsyms:=tfpobjectlist.create(false);
         InitDebugInfo(self,false);
         InitDebugInfo(self,false);
       end;
       end;
 
 
@@ -661,6 +682,8 @@ implementation
         linkothersharedlibs.Free;
         linkothersharedlibs.Free;
         linkotherframeworks.Free;
         linkotherframeworks.Free;
         stringdispose(mainname);
         stringdispose(mainname);
+        globalasmsyms.free;
+        unitimportsyms.free;
         FImportLibraryList.Free;
         FImportLibraryList.Free;
         extendeddefs.Free;
         extendeddefs.Free;
         genericdummysyms.free;
         genericdummysyms.free;
@@ -751,6 +774,10 @@ implementation
         wpoinfo:=nil;
         wpoinfo:=nil;
         checkforwarddefs.free;
         checkforwarddefs.free;
         checkforwarddefs:=TFPObjectList.Create(false);
         checkforwarddefs:=TFPObjectList.Create(false);
+        globalasmsyms.free;
+        globalasmsyms:=tfphashobjectlist.create(true);
+        unitimportsyms.free;
+        unitimportsyms:=tfpobjectlist.create(false);
         derefdata.free;
         derefdata.free;
         derefdata:=TDynamicArray.Create(1024);
         derefdata:=TDynamicArray.Create(1024);
         if assigned(unitmap) then
         if assigned(unitmap) then

+ 114 - 2
compiler/fppu.pas

@@ -66,6 +66,7 @@ interface
           procedure reload_flagged_units;
           procedure reload_flagged_units;
           procedure end_of_parsing;override;
           procedure end_of_parsing;override;
        private
        private
+          unitimportsymsderefs : tfplist;
          { Each time a unit's defs are (re)created, its defsgeneration is
          { Each time a unit's defs are (re)created, its defsgeneration is
            set to the value of a global counter, and the global counter is
            set to the value of a global counter, and the global counter is
            increased. We only reresolve its dependent units' defs in case
            increased. We only reresolve its dependent units' defs in case
@@ -80,12 +81,17 @@ interface
           procedure load_usedunits;
           procedure load_usedunits;
           procedure printcomments;
           procedure printcomments;
           procedure queuecomment(const s:TMsgStr;v,w:longint);
           procedure queuecomment(const s:TMsgStr;v,w:longint);
+          procedure buildderefunitimportsyms;
+          procedure derefunitimportsyms;
+          procedure readunitimportsyms;
+          procedure writeunitimportsyms;
           procedure writesourcefiles;
           procedure writesourcefiles;
           procedure writeusedunit(intf:boolean);
           procedure writeusedunit(intf:boolean);
           procedure writelinkcontainer(var p:tlinkcontainer;id:byte;strippath:boolean);
           procedure writelinkcontainer(var p:tlinkcontainer;id:byte;strippath:boolean);
           procedure writederefmap;
           procedure writederefmap;
           procedure writederefdata;
           procedure writederefdata;
           procedure writeImportSymbols;
           procedure writeImportSymbols;
+          procedure writeasmsymbols;
           procedure writeResources;
           procedure writeResources;
           procedure readsourcefiles;
           procedure readsourcefiles;
           procedure readloadunit;
           procedure readloadunit;
@@ -94,6 +100,7 @@ interface
           procedure readderefdata;
           procedure readderefdata;
           procedure readImportSymbols;
           procedure readImportSymbols;
           procedure readResources;
           procedure readResources;
+          procedure readasmsymbols;
           procedure readwpofile;
           procedure readwpofile;
 {$IFDEF MACRO_DIFF_HINT}
 {$IFDEF MACRO_DIFF_HINT}
           procedure writeusedmacro(p:TNamedIndexItem;arg:pointer);
           procedure writeusedmacro(p:TNamedIndexItem;arg:pointer);
@@ -132,6 +139,7 @@ var
         inherited create(LoadedFrom,amodulename,afilename,_is_unit);
         inherited create(LoadedFrom,amodulename,afilename,_is_unit);
         ppufile:=nil;
         ppufile:=nil;
         sourcefn:=afilename;
         sourcefn:=afilename;
+        unitimportsymsderefs:=tfplist.create;
       end;
       end;
 
 
 
 
@@ -142,6 +150,8 @@ var
         ppufile:=nil;
         ppufile:=nil;
         comments.free;
         comments.free;
         comments:=nil;
         comments:=nil;
+        unitimportsymsderefs.free;
+        unitimportsymsderefs:=nil;
         inherited Destroy;
         inherited Destroy;
       end;
       end;
 
 
@@ -677,6 +687,22 @@ var
         ppufile.writeentry(ibImportSymbols);
         ppufile.writeentry(ibImportSymbols);
       end;
       end;
 
 
+    procedure tppumodule.writeasmsymbols;
+      var
+        sym : tasmsymbol;
+        i : longint;
+      begin
+        ppufile.putlongint(globalasmsyms.count);
+        for i:=0 to globalasmsyms.count-1 do
+          begin
+            sym:=tasmsymbol(globalasmsyms[i]);
+            ppufile.putstring(sym.name);
+            ppufile.putbyte(ord(sym.bind));
+            ppufile.putbyte(ord(sym.typ));
+          end;
+        ppufile.writeentry(ibasmsymbols);
+      end;
+
 
 
     procedure tppumodule.writeResources;
     procedure tppumodule.writeResources;
       var
       var
@@ -692,6 +718,63 @@ var
       end;
       end;
 
 
 
 
+    procedure tppumodule.buildderefunitimportsyms;
+      var
+        deref : pderef;
+        i : longint;
+      begin
+        for i:=0 to unitimportsyms.count-1 do
+          begin
+            new(deref);
+            deref^.build(unitimportsyms[i]);
+            unitimportsymsderefs.add(deref);
+          end;
+      end;
+
+
+    procedure tppumodule.derefunitimportsyms;
+      var
+        i : longint;
+        sym : tsym;
+      begin
+        { since this list can get quite large we clear it immediately after we derefd it }
+        for i:=0 to unitimportsymsderefs.count-1 do
+          begin
+            sym:=tsym(pderef(unitimportsymsderefs[i])^.resolve);
+            unitimportsyms.add(sym);
+            dispose(pderef(unitimportsymsderefs[i]));
+          end;
+        unitimportsymsderefs.clear;
+      end;
+
+
+    procedure tppumodule.readunitimportsyms;
+      var
+        c,i : longint;
+        deref : pderef;
+      begin
+        c:=ppufile.getlongint;
+        writeln('loading: unit ', modulename^, ' has ', c, ' imported symbols');
+        for i:=0 to c-1 do
+          begin
+            new(deref);
+            ppufile.getderef(deref^);
+            unitimportsymsderefs.add(deref);
+          end;
+      end;
+
+
+    procedure tppumodule.writeunitimportsyms;
+      var
+        i : longint;
+      begin
+        writeln('writing: unit ', modulename^, ' has ', unitimportsymsderefs.Count, ' imported symbols');
+        ppufile.putlongint(unitimportsymsderefs.count);
+        for i:=0 to unitimportsymsderefs.count-1 do
+          ppufile.putderef(pderef(unitimportsymsderefs[i])^);
+        ppufile.writeentry(ibunitimportsyms);
+      end;
+
 {$IFDEF MACRO_DIFF_HINT}
 {$IFDEF MACRO_DIFF_HINT}
 
 
 {
 {
@@ -963,6 +1046,25 @@ var
       end;
       end;
 
 
 
 
+    procedure tppumodule.readasmsymbols;
+      var
+        cnt : longint;
+        s : string;
+        bind : tasmsymbind;
+        typ : tasmsymtype;
+      begin
+        cnt:=ppufile.getlongint;
+        writeln('loading: unit ', modulename^, ' has ', cnt, ' imported asm symbols');
+        while not ppufile.endofentry and not ppufile.error do
+          begin
+            s:=ppufile.getstring;
+            bind:=tasmsymbind(ppufile.getbyte);
+            typ:=tasmsymtype(ppufile.getbyte);
+            tasmsymbol.create(globalasmsyms,s,bind,typ);
+          end;
+      end;
+
+
     procedure tppumodule.readwpofile;
     procedure tppumodule.readwpofile;
       var
       var
         orgwpofilename: string;
         orgwpofilename: string;
@@ -1077,8 +1179,9 @@ var
              ibloadunit :
              ibloadunit :
                readloadunit;
                readloadunit;
              ibasmsymbols :
              ibasmsymbols :
-{ TODO: Remove ibasmsymbols}
-               ;
+               readasmsymbols;
+             ibunitimportsyms :
+               readunitimportsyms;
              ibendimplementation :
              ibendimplementation :
                break;
                break;
            else
            else
@@ -1197,6 +1300,7 @@ var
            end;
            end;
          tunitwpoinfo(wpoinfo).buildderef;
          tunitwpoinfo(wpoinfo).buildderef;
          tunitwpoinfo(wpoinfo).buildderefimpl;
          tunitwpoinfo(wpoinfo).buildderefimpl;
+         buildderefunitimportsyms;
          writederefmap;
          writederefmap;
          writederefdata;
          writederefdata;
 
 
@@ -1223,6 +1327,12 @@ var
          { write implementation uses }
          { write implementation uses }
          writeusedunit(false);
          writeusedunit(false);
 
 
+         { write global assembler symbols }
+         writeasmsymbols;
+
+         { write all symbols imported from another unit }
+         writeunitimportsyms;
+
          { end of implementation }
          { end of implementation }
          ppufile.writeentry(ibendimplementation);
          ppufile.writeentry(ibendimplementation);
 
 
@@ -1474,6 +1584,8 @@ var
         if assigned(localsymtable) then
         if assigned(localsymtable) then
           tstoredsymtable(localsymtable).derefimpl;
           tstoredsymtable(localsymtable).derefimpl;
 
 
+        derefunitimportsyms;
+
          { read whole program optimisation-related information }
          { read whole program optimisation-related information }
          wpoinfo:=tunitwpoinfo.ppuload(ppufile);
          wpoinfo:=tunitwpoinfo.ppuload(ppufile);
          tunitwpoinfo(wpoinfo).deref;
          tunitwpoinfo(wpoinfo).deref;

+ 6 - 1
compiler/pmodules.pas

@@ -1216,7 +1216,12 @@ type
          store_crc:=current_module.crc;
          store_crc:=current_module.crc;
 {$endif EXTDEBUG}
 {$endif EXTDEBUG}
          if (Errorcount=0) then
          if (Errorcount=0) then
-           tppumodule(current_module).writeppu;
+           begin
+             { ensure that all asm symbols that can potentially be exported are
+               available in the ppu }
+             current_module.extractexportasmsyms;
+             tppumodule(current_module).writeppu;
+           end;
 
 
          if not(cs_compilesystem in current_settings.moduleswitches) then
          if not(cs_compilesystem in current_settings.moduleswitches) then
            begin
            begin

+ 1 - 1
compiler/ppu.pas

@@ -43,7 +43,7 @@ type
 {$endif Test_Double_checksum}
 {$endif Test_Double_checksum}
 
 
 const
 const
-  CurrentPPUVersion = 170;
+  CurrentPPUVersion = 172;
 
 
   ppubufsize   = 16384;
   ppubufsize   = 16384;
 
 

+ 14 - 7
compiler/symtable.pas

@@ -2116,13 +2116,20 @@ implementation
          owner:=sym.owner;
          owner:=sym.owner;
          while owner.symtabletype in [objectsymtable,recordsymtable,enumsymtable] do
          while owner.symtabletype in [objectsymtable,recordsymtable,enumsymtable] do
            owner:=tdef(owner.defowner).owner;
            owner:=tdef(owner.defowner).owner;
-         if assigned(current_module) and
-            (owner.symtabletype=globalsymtable) then
-             begin
-               if tglobalsymtable(owner).moduleid>=current_module.unitmapsize then
-                 internalerror(200501152);
-               inc(current_module.unitmap[tglobalsymtable(owner).moduleid].refs);
-             end;
+         if assigned(current_module) then
+           begin
+             if (owner.symtabletype=globalsymtable) then
+               begin
+                 if tglobalsymtable(owner).moduleid>=current_module.unitmapsize then
+                   internalerror(200501152);
+                 inc(current_module.unitmap[tglobalsymtable(owner).moduleid].refs);
+               end;
+             if (owner.symtabletype=globalsymtable) and (current_module.globalsymtable<>owner) then
+               begin
+                 if current_module.unitimportsyms.indexof(sym)<0 then
+                   current_module.unitimportsyms.add(sym);
+               end;
+           end;
        end;
        end;