mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-13 05:40:20 +02:00
+ finished the internal omf library writer (implementing writing of the library
dictionary at the and of the file) and enabled it for the i8086 internal asm git-svn-id: trunk@30701 -
This commit is contained in:
parent
dbe1081389
commit
7923b6142e
@ -858,7 +858,7 @@ implementation
|
|||||||
asmbin : '';
|
asmbin : '';
|
||||||
asmcmd : '';
|
asmcmd : '';
|
||||||
supported_targets : [system_i8086_msdos];
|
supported_targets : [system_i8086_msdos];
|
||||||
flags : [af_outputbinary,af_needar,af_no_debug];
|
flags : [af_outputbinary,af_no_debug];
|
||||||
labelprefix : '..@';
|
labelprefix : '..@';
|
||||||
comment : '; ';
|
comment : '; ';
|
||||||
dollarsign: '$';
|
dollarsign: '$';
|
||||||
|
@ -504,6 +504,15 @@ interface
|
|||||||
property PaddingBytes: Word read FPaddingBytes write FPaddingBytes;
|
property PaddingBytes: Word read FPaddingBytes write FPaddingBytes;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
const
|
||||||
|
{ list of all the possible omf library dictionary block counts - contains
|
||||||
|
all the prime numbers less than 255 }
|
||||||
|
OmfLibDictionaryBlockCounts: array [0..53] of Byte =
|
||||||
|
(2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,
|
||||||
|
101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,
|
||||||
|
193,197,199,211,223,227,229,233,239,241,251);
|
||||||
|
|
||||||
|
type
|
||||||
TOmfLibHash = record
|
TOmfLibHash = record
|
||||||
block_x: Integer;
|
block_x: Integer;
|
||||||
block_d: Integer;
|
block_d: Integer;
|
||||||
|
@ -30,10 +30,21 @@ interface
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
cclasses,
|
cclasses,
|
||||||
|
globtype,
|
||||||
owbase;
|
owbase;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
|
{ TOmfLibDictionaryEntry }
|
||||||
|
|
||||||
|
TOmfLibDictionaryEntry=class(TFPHashObject)
|
||||||
|
private
|
||||||
|
FPageNum: Word;
|
||||||
|
public
|
||||||
|
constructor Create(HashObjectList:TFPHashObjectList;const aName:TSymStr;aPageNum:Word);
|
||||||
|
property PageNum: Word read FPageNum write FPageNum;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TOmfLibObjectWriter }
|
{ TOmfLibObjectWriter }
|
||||||
|
|
||||||
TOmfLibObjectWriter=class(TObjectWriter)
|
TOmfLibObjectWriter=class(TObjectWriter)
|
||||||
@ -44,10 +55,13 @@ type
|
|||||||
FObjFileName: string;
|
FObjFileName: string;
|
||||||
FObjData: TDynamicArray;
|
FObjData: TDynamicArray;
|
||||||
FObjStartPage: Word;
|
FObjStartPage: Word;
|
||||||
|
FDictionary: TFPHashObjectList;
|
||||||
|
|
||||||
procedure WriteHeader(DictStart: DWord; DictBlocks: Word);
|
procedure WriteHeader(DictStart: DWord; DictBlocks: Word);
|
||||||
procedure WriteFooter;
|
procedure WriteFooter;
|
||||||
procedure WriteLib;
|
procedure WriteLib;
|
||||||
|
function WriteDictionary: byte;
|
||||||
|
function TryWriteDictionaryWithSize(nblocks: Byte): Boolean;
|
||||||
public
|
public
|
||||||
constructor createAr(const Aarfn:string);override;
|
constructor createAr(const Aarfn:string);override;
|
||||||
destructor destroy;override;
|
destructor destroy;override;
|
||||||
@ -70,6 +84,28 @@ implementation
|
|||||||
libbufsize = 65536;
|
libbufsize = 65536;
|
||||||
objbufsize = 65536;
|
objbufsize = 65536;
|
||||||
|
|
||||||
|
{*****************************************************************************
|
||||||
|
Helpers
|
||||||
|
*****************************************************************************}
|
||||||
|
|
||||||
|
function ModName2DictEntry(const modnm: string): string;
|
||||||
|
begin
|
||||||
|
if Copy(modnm,Length(modnm)-1,2)='.o' then
|
||||||
|
Result:=Copy(modnm,1,Length(modnm)-2)+'!'
|
||||||
|
else
|
||||||
|
Result:=modnm;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{*****************************************************************************
|
||||||
|
TOmfLibDictionaryEntry
|
||||||
|
*****************************************************************************}
|
||||||
|
|
||||||
|
constructor TOmfLibDictionaryEntry.Create(HashObjectList: TFPHashObjectList; const aName: TSymStr; aPageNum: Word);
|
||||||
|
begin
|
||||||
|
inherited Create(HashObjectList,aName);
|
||||||
|
PageNum:=aPageNum;
|
||||||
|
end;
|
||||||
|
|
||||||
{*****************************************************************************
|
{*****************************************************************************
|
||||||
TOmfLibObjectWriter
|
TOmfLibObjectWriter
|
||||||
*****************************************************************************}
|
*****************************************************************************}
|
||||||
@ -79,6 +115,7 @@ implementation
|
|||||||
FPageSize:=512;
|
FPageSize:=512;
|
||||||
FLibName:=Aarfn;
|
FLibName:=Aarfn;
|
||||||
FLibData:=TDynamicArray.Create(libbufsize);
|
FLibData:=TDynamicArray.Create(libbufsize);
|
||||||
|
FDictionary:=TFPHashObjectList.Create;
|
||||||
{ header is at page 0, so first module starts at page 1 }
|
{ header is at page 0, so first module starts at page 1 }
|
||||||
FObjStartPage:=1;
|
FObjStartPage:=1;
|
||||||
end;
|
end;
|
||||||
@ -90,6 +127,7 @@ implementation
|
|||||||
WriteLib;
|
WriteLib;
|
||||||
FLibData.Free;
|
FLibData.Free;
|
||||||
FObjData.Free;
|
FObjData.Free;
|
||||||
|
FDictionary.Free;
|
||||||
inherited destroy;
|
inherited destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -107,12 +145,21 @@ implementation
|
|||||||
procedure TOmfLibObjectWriter.closefile;
|
procedure TOmfLibObjectWriter.closefile;
|
||||||
var
|
var
|
||||||
RawRec: TOmfRawRecord;
|
RawRec: TOmfRawRecord;
|
||||||
|
ObjHeader: TOmfRecord_THEADR;
|
||||||
begin
|
begin
|
||||||
FLibData.seek(FObjStartPage*FPageSize);
|
FLibData.seek(FObjStartPage*FPageSize);
|
||||||
FObjData.seek(0);
|
FObjData.seek(0);
|
||||||
RawRec:=TOmfRawRecord.Create;
|
RawRec:=TOmfRawRecord.Create;
|
||||||
repeat
|
repeat
|
||||||
RawRec.ReadFrom(FObjData);
|
RawRec.ReadFrom(FObjData);
|
||||||
|
if RawRec.RecordType=RT_THEADR then
|
||||||
|
begin
|
||||||
|
ObjHeader:=TOmfRecord_THEADR.Create;
|
||||||
|
ObjHeader.DecodeFrom(RawRec);
|
||||||
|
{ create a dictionary entry with the module name }
|
||||||
|
TOmfLibDictionaryEntry.Create(FDictionary,ModName2DictEntry(ObjHeader.ModuleName),FObjStartPage);
|
||||||
|
ObjHeader.Free;
|
||||||
|
end;
|
||||||
RawRec.WriteTo(FLibData);
|
RawRec.WriteTo(FLibData);
|
||||||
until RawRec.RecordType in [RT_MODEND,RT_MODEND32];
|
until RawRec.RecordType in [RT_MODEND,RT_MODEND32];
|
||||||
RawRec.Free;
|
RawRec.Free;
|
||||||
@ -124,7 +171,7 @@ implementation
|
|||||||
|
|
||||||
procedure TOmfLibObjectWriter.writesym(const sym: string);
|
procedure TOmfLibObjectWriter.writesym(const sym: string);
|
||||||
begin
|
begin
|
||||||
inherited writesym(sym);
|
TOmfLibDictionaryEntry.Create(FDictionary,sym,FObjStartPage);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -174,6 +221,8 @@ implementation
|
|||||||
procedure TOmfLibObjectWriter.WriteLib;
|
procedure TOmfLibObjectWriter.WriteLib;
|
||||||
var
|
var
|
||||||
libf: TCCustomFileStream;
|
libf: TCCustomFileStream;
|
||||||
|
DictStart: LongWord;
|
||||||
|
DictBlocks: Byte;
|
||||||
begin
|
begin
|
||||||
libf:=CFileStreamClass.Create(FLibName,fmCreate);
|
libf:=CFileStreamClass.Create(FLibName,fmCreate);
|
||||||
if CStreamError<>0 then
|
if CStreamError<>0 then
|
||||||
@ -182,9 +231,95 @@ implementation
|
|||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
WriteFooter;
|
WriteFooter;
|
||||||
WriteHeader(FLibData.Pos,2);
|
DictStart:=FLibData.Pos;
|
||||||
|
DictBlocks:=WriteDictionary;
|
||||||
|
WriteHeader(DictStart,DictBlocks);
|
||||||
FLibData.WriteStream(libf);
|
FLibData.WriteStream(libf);
|
||||||
libf.Free;
|
libf.Free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TOmfLibObjectWriter.WriteDictionary: Byte;
|
||||||
|
var
|
||||||
|
nb: Byte;
|
||||||
|
begin
|
||||||
|
for nb in OmfLibDictionaryBlockCounts do
|
||||||
|
if TryWriteDictionaryWithSize(nb) then
|
||||||
|
exit(nb);
|
||||||
|
{ could not write dictionary, even with the largest number of blocks }
|
||||||
|
internalerror(2015042201);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TOmfLibObjectWriter.TryWriteDictionaryWithSize(nblocks: Byte): Boolean;
|
||||||
|
const
|
||||||
|
nbuckets=37;
|
||||||
|
freespace=nbuckets;
|
||||||
|
type
|
||||||
|
PBlock=^TBlock;
|
||||||
|
TBlock=array[0..511] of byte;
|
||||||
|
var
|
||||||
|
blocks: array of TBlock;
|
||||||
|
i: Integer;
|
||||||
|
N: TSymStr;
|
||||||
|
length_of_string: Integer;
|
||||||
|
h: TOmfLibHash;
|
||||||
|
start_block,start_bucket: Integer;
|
||||||
|
space_required: Integer;
|
||||||
|
pb: PBlock;
|
||||||
|
success: Boolean;
|
||||||
|
store_at: Integer;
|
||||||
|
PageNum: Word;
|
||||||
|
begin
|
||||||
|
SetLength(blocks,nblocks);
|
||||||
|
for i:=0 to nblocks-1 do
|
||||||
|
begin
|
||||||
|
FillChar(blocks[i],SizeOf(blocks[i]),0);
|
||||||
|
blocks[i][freespace]:=(freespace+1) div 2;
|
||||||
|
end;
|
||||||
|
|
||||||
|
for i:=0 to FDictionary.Count-1 do
|
||||||
|
begin
|
||||||
|
N:=TOmfLibDictionaryEntry(FDictionary[i]).Name;
|
||||||
|
PageNum:=TOmfLibDictionaryEntry(FDictionary[i]).PageNum;
|
||||||
|
length_of_string:=Length(N);
|
||||||
|
h:=compute_omf_lib_hash(N,nblocks);
|
||||||
|
start_block:=h.block_x;
|
||||||
|
start_bucket:=h.bucket_x;
|
||||||
|
space_required:=1+length_of_string+2;
|
||||||
|
if odd(space_required) then
|
||||||
|
Inc(space_required);
|
||||||
|
repeat
|
||||||
|
pb:=@blocks[h.block_x];
|
||||||
|
success:=false;
|
||||||
|
repeat
|
||||||
|
if pb^[h.bucket_x]=0 then
|
||||||
|
begin
|
||||||
|
if (512-pb^[freespace]*2)<space_required then
|
||||||
|
break;
|
||||||
|
pb^[h.bucket_x]:=pb^[freespace];
|
||||||
|
store_at:=2*pb^[h.bucket_x];
|
||||||
|
pb^[store_at]:=length_of_string;
|
||||||
|
Move(N[1],pb^[store_at+1],length_of_string);
|
||||||
|
pb^[store_at+1+length_of_string]:=Byte(PageNum);
|
||||||
|
pb^[store_at+1+length_of_string+1]:=Byte(PageNum shr 8);
|
||||||
|
Inc(pb^[freespace],space_required div 2);
|
||||||
|
if pb^[freespace]=0 then
|
||||||
|
pb^[freespace]:=255;
|
||||||
|
success:=true;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
h.bucket_x:=(h.bucket_x+h.bucket_d) mod nbuckets;
|
||||||
|
until h.bucket_x=start_bucket;
|
||||||
|
if not success then
|
||||||
|
begin
|
||||||
|
h.block_x:=(h.block_x+h.block_d) mod nblocks;
|
||||||
|
if h.block_x=start_block then
|
||||||
|
exit(false); // not enough blocks
|
||||||
|
pb^[freespace]:=255;
|
||||||
|
end;
|
||||||
|
until success;
|
||||||
|
end;
|
||||||
|
FLibData.write(blocks[0],nblocks*SizeOf(TBlock));
|
||||||
|
Result:=true;
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
Loading…
Reference in New Issue
Block a user