Browse Source

o based on a patch by Rika, resolves #39401:
* use Base64 (62=_, 63=$) encoded FNV hash (instead of CR-32) to shorted identifiers
* renamed fpccrc to fpchash
+ test

florian 3 years ago
parent
commit
a4672fbd1c

+ 1 - 1
compiler/aasmbase.pas

@@ -265,7 +265,7 @@ interface
 implementation
 implementation
 
 
     uses
     uses
-      verbose,fpccrc;
+      verbose,fpchash;
 
 
 
 
     function create_smartlink_sections:boolean;inline;
     function create_smartlink_sections:boolean;inline;

+ 66 - 2
compiler/fpccrc.pas → compiler/fpchash.pas

@@ -1,7 +1,7 @@
 {
 {
     Copyright (c) 2000-2002 by Free Pascal Development Team
     Copyright (c) 2000-2002 by Free Pascal Development Team
 
 
-    Routines to compute CRC values
+    Routines to compute hash values
 
 
     This program is free software; you can redistribute it and/or modify
     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
     it under the terms of the GNU General Public License as published by
@@ -19,7 +19,7 @@
 
 
  ****************************************************************************
  ****************************************************************************
 }
 }
-Unit fpccrc;
+Unit fpchash;
 
 
 {$i fpcdefs.inc}
 {$i fpcdefs.inc}
 
 
@@ -30,6 +30,16 @@ Function UpdateCrc32(InitCrc:cardinal;const InBuf;InLen:integer):cardinal;
   The resulting string is guaranteed to be not longer than maxlen. }
   The resulting string is guaranteed to be not longer than maxlen. }
 function TrimStrCRC32(const s: ansistring; maxlen: longint): ansistring;
 function TrimStrCRC32(const s: ansistring; maxlen: longint): ansistring;
 
 
+{ calculate string hash using FNV Hash:
+  http://www.isthe.com/chongo/tech/comp/fnv/
+}
+function UpdateFnv64(const InitFnv: uint64; const InBuf; InLen: Integer): uint64;
+
+type
+  Base64OfUint64String = string[11];
+
+function Base64Mangle(const x: uint64): Base64OfUint64String;
+
 Implementation
 Implementation
 
 
 {*****************************************************************************
 {*****************************************************************************
@@ -92,4 +102,58 @@ begin
    end;
    end;
 end;
 end;
 
 
+{ calculate string hash using FNV Hash:
+  http://www.isthe.com/chongo/tech/comp/fnv/
+}
+{$push} {$rangechecks off} {$overflowchecks off}
+function UpdateFnv64(const InitFnv: uint64; const InBuf; InLen: Integer): uint64;
+const
+  M = uint64(1099511628211);
+  { Compiler yells at you for overflows in constants, even with disabled range checks,
+    so there are precalculated values for unrolled loop: M^2, M^3, M^4. }
+  Mp2 = uint64(956575116354345);
+  Mp3 = uint64(624165263380053675);
+  Mp4 = uint64(11527715348014283921);
+var
+  pp: pByte;
+begin
+  result := InitFnv;
+  pp := @InBuf;
+  while InLen >= 4 do
+   begin
+     result := (result + pp[0]) * Mp4 + pp[1] * Mp3 + pp[2] * Mp2 + pp[3] * M;
+     pp := pp + 4;
+     InLen := InLen - 4;
+   end;
+  while InLen > 0 do
+   begin
+     result := (result + pp^) * M;
+     pp := pp + 1;
+     InLen := InLen - 1;
+   end;
+end;
+{$pop}
+
+const
+  Base64Chars: array[0 .. 63] of char = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$';
+
+function Base64Mangle(const x: uint64): Base64OfUint64String;
+var
+  b64chars: pChar;
+begin
+  b64chars := pChar(Base64Chars);
+  result[0] := #11;
+  result[1] := b64chars[x and $3f];
+  result[2] := b64chars[uint32(x) shr 6 and $3f];
+  result[3] := b64chars[uint32(x) shr 12 and $3f];
+  result[4] := b64chars[uint32(x) shr 18 and $3f];
+  result[5] := b64chars[uint32(x) shr 24 and $3f];
+  result[6] := b64chars[x shr 30 and $3f];
+  result[7] := b64chars[x shr 36 and $3f];
+  result[8] := b64chars[x shr 42 and $3f];
+  result[9] := b64chars[x shr 48 and $3f];
+  result[10] := b64chars[x shr 54 and $3f];
+  result[11] := b64chars[x shr 60];
+end;
+
 end.
 end.

+ 1 - 1
compiler/link.pas

@@ -170,7 +170,7 @@ Implementation
 {$ifdef hasUnix}
 {$ifdef hasUnix}
       baseunix,
       baseunix,
 {$endif hasUnix}
 {$endif hasUnix}
-      cscript,globals,verbose,comphook,ppu,fpccrc,
+      cscript,globals,verbose,comphook,ppu,fpchash,
       aasmbase,aasmcpu,
       aasmbase,aasmcpu,
       ogmap;
       ogmap;
 
 

+ 1 - 1
compiler/ncgvmt.pas

@@ -99,7 +99,7 @@ implementation
 
 
     uses
     uses
       cutils,cclasses,
       cutils,cclasses,
-      fpccrc,
+      fpchash,
       globtype,globals,verbose,constexp,
       globtype,globals,verbose,constexp,
       systems,fmodule,
       systems,fmodule,
       symsym,symtable,symcreat,
       symsym,symtable,symcreat,

+ 1 - 1
compiler/pcp.pas

@@ -73,7 +73,7 @@ interface
 implementation
 implementation
 
 
 uses
 uses
-  fpccrc;
+  fpchash;
 
 
   { tpcpfile }
   { tpcpfile }
 
 

+ 1 - 1
compiler/pgenutil.pas

@@ -63,7 +63,7 @@ implementation
 
 
 uses
 uses
   { common }
   { common }
-  cutils,fpccrc,
+  cutils,fpchash,
   { global }
   { global }
   globals,tokens,verbose,finput,constexp,
   globals,tokens,verbose,finput,constexp,
   { symtable }
   { symtable }

+ 1 - 1
compiler/ppu.pas

@@ -175,7 +175,7 @@ implementation
 {$ifdef Test_Double_checksum}
 {$ifdef Test_Double_checksum}
     comphook,
     comphook,
 {$endif def Test_Double_checksum}
 {$endif def Test_Double_checksum}
-    fpccrc;
+    fpchash;
 
 
 {$ifdef Test_Double_checksum}
 {$ifdef Test_Double_checksum}
 {$ifdef TEST_CRC_ERROR}
 {$ifdef TEST_CRC_ERROR}

+ 11 - 11
compiler/symdef.pas

@@ -1363,7 +1363,7 @@ implementation
       { other }
       { other }
       aasmbase,
       aasmbase,
       gendef,
       gendef,
-      fpccrc,
+      fpchash,
       entfile
       entfile
       ;
       ;
 
 
@@ -1533,7 +1533,7 @@ implementation
       var
       var
         s,
         s,
         prefix : TSymStr;
         prefix : TSymStr;
-        crc : dword;
+        hash : qword;
       begin
       begin
         prefix:='';
         prefix:='';
         if not assigned(st) then
         if not assigned(st) then
@@ -1555,9 +1555,9 @@ implementation
                prefix:=s;
                prefix:=s;
              if length(prefix)>100 then
              if length(prefix)>100 then
                begin
                begin
-                 crc:=0;
-                 crc:=UpdateCrc32(crc,prefix[1],length(prefix));
-                 prefix:='$CRC'+hexstr(crc,8);
+                 hash:=0;
+                 hash:=UpdateFnv64(hash,prefix[1],length(prefix));
+                 prefix:='$H'+Base64Mangle(hash);
                end;
                end;
              st:=st.defowner.owner;
              st:=st.defowner.owner;
            end;
            end;
@@ -5454,7 +5454,7 @@ implementation
 
 
     function tabstractprocdef.mangledprocparanames(oldlen : longint) : string;
     function tabstractprocdef.mangledprocparanames(oldlen : longint) : string;
       var
       var
-        crc  : dword;
+        hash  : qword;
         hp   : TParavarsym;
         hp   : TParavarsym;
         hs   : TSymStr;
         hs   : TSymStr;
         newlen,
         newlen,
@@ -5474,27 +5474,27 @@ implementation
         if not is_void(returndef) then
         if not is_void(returndef) then
           result:=result+'$$'+returndef.mangledparaname;
           result:=result+'$$'+returndef.mangledparaname;
         newlen:=length(result)+oldlen;
         newlen:=length(result)+oldlen;
-        { Replace with CRC if the parameter line is very long }
+        { Replace with hash if the parameter line is very long }
         if (newlen-oldlen>12) and
         if (newlen-oldlen>12) and
            ((newlen>100) or (newlen-oldlen>64)) then
            ((newlen>100) or (newlen-oldlen>64)) then
           begin
           begin
-            crc:=0;
+            hash:=0;
             for i:=0 to paras.count-1 do
             for i:=0 to paras.count-1 do
               begin
               begin
                 hp:=tparavarsym(paras[i]);
                 hp:=tparavarsym(paras[i]);
                 if not(vo_is_hidden_para in hp.varoptions) then
                 if not(vo_is_hidden_para in hp.varoptions) then
                   begin
                   begin
                     hs:=hp.vardef.mangledparaname;
                     hs:=hp.vardef.mangledparaname;
-                    crc:=UpdateCrc32(crc,hs[1],length(hs));
+                    hash:=UpdateFnv64(hash,hs[1],length(hs));
                   end;
                   end;
               end;
               end;
             if not is_void(returndef) then
             if not is_void(returndef) then
               begin
               begin
                 { add a little prefix so that x(integer; integer) is different from x(integer):integer }
                 { add a little prefix so that x(integer; integer) is different from x(integer):integer }
                 hs:='$$'+returndef.mangledparaname;
                 hs:='$$'+returndef.mangledparaname;
-                crc:=UpdateCrc32(crc,hs[1],length(hs));
+                hash:=UpdateFnv64(hash,hs[1],length(hs));
               end;
               end;
-            result:='$crc'+hexstr(crc,8);
+            result:='$h'+Base64Mangle(hash);
           end;
           end;
       end;
       end;
 
 

+ 27 - 0
tests/webtbs/tw39401.pp

@@ -0,0 +1,27 @@
+{ %norun }
+{$mode objfpc}
+type
+	Collide29685295 = type uint32;
+	Collide32060020 = type uint32;
+
+	SomeType = class
+	type
+		SomeNestedType = class
+		type
+			YetAnotherNestedType = class
+				class procedure Hello(arg: YetAnotherNestedType; arg2: Collide29685295); static;
+				class procedure Hello(arg: YetAnotherNestedType; arg2: Collide32060020); static;
+			end;
+		end;
+	end;
+
+	class procedure SomeType.SomeNestedType.YetAnotherNestedType.Hello(arg: YetAnotherNestedType; arg2: Collide29685295);
+	begin
+	end;
+
+	class procedure SomeType.SomeNestedType.YetAnotherNestedType.Hello(arg: YetAnotherNestedType; arg2: Collide32060020);
+	begin
+	end;
+
+begin
+end.