Resolving References
Once the offsets of code blocks, variables and typed constants are known, the compiler can resolve references. This procedure calculates all references (displacements, offsets, near and far pointers) to code or data.
Procedure ResolveReferences (Block: TSymbolTable; DataBlockSegment, ReferencesBlockSegment: Word);
Var CodeConstBlock: PCodeConstBlockRecord;
CodeConstBlockRec: PtrRec absolute CodeConstBlock;
ReferenceRecord: PReferencesBlockRecord;
ReferenceRec: PtrRec absolute ReferenceRecord;
ReferencedUnitRecord: PReferencedModulesBlockRecord;
CurrentBlockOffset: Word;
Procedure ResolveReferencesForUsedBlock;
Var EndOffset: Word;
TempUnit: PUnitHeader;
BlockRecord: Word;
ReferenceFlags: TReferenceFlagSet;
ReferencePosition: Word;
ReferencePointer: PPtrRec;
ReferencePointerRec: PtrRec absolute ReferencePointer;
ProcedureRecordPtr: PProceduresBlockRecord;
Reference: PtrRec;
begin
EndOffset := ReferenceRec.Ofs + CodeConstBlock^.ReferencesSize;
While ReferenceRec.Ofs <> EndOffset do
begin
TempUnit := Ptr (CurrentUnitForProcessing, 0);
ReferencedUnitRecord := Ptr (CurrentUnitForProcessing,
TempUnit^.BlockOffset [stReferencedModules] +
ReferenceRecord^.ReferencedUnitRecord and $0FFF);
TempUnit := Ptr (ReferencedUnitRecord^.ModuleSegment, 0);
With ReferenceRecord^ do
begin
ReferenceFlags := Flags;
BlockRecord := ReferencedBlockRecordOffset;
Reference.Ofs := ReferencedOffset;
ReferencePosition := PositionOfReference;
end;
If rfDataSegment in ReferenceFlags then
begin
Case rfConstant in ReferenceFlags of
True: Inc (BlockRecord, TempUnit^.BlockOffset [stTypedConstantsBlocks]);
else Inc (BlockRecord, TempUnit^.BlockOffset [stVariablesBlocks]);
end;
Inc (Reference.Ofs, PConstVarBlockRecord (PChar (TempUnit) + BlockRecord)^.Offset);
Reference.Seg := DataSegment;
end else begin
If rfConstant in ReferenceFlags then
begin
Inc (BlockRecord, TempUnit^.BlockOffset [stCodeBlocks]);
Inc (Reference.Ofs, PProgramCodeBlockRecord (PChar (TempUnit) + BlockRecord)^.Offset);
Reference.Seg := TempUnit^.CodeSegment;
end else begin
Inc (BlockRecord, TempUnit^.BlockOffset [stProcedures]);
ProcedureRecordPtr := Ptr (Seg (TempUnit^), BlockRecord);
If Lo (ProcedureRecordPtr^.prW2) and $08 <> 0 then
begin
Inc (Reference.Ofs, ProcedureRecordPtr^.SizeOfConstants);
BlockRecord := ProcedureRecordPtr^.ProgramCodeBlockRecordOffset;
Inc (BlockRecord, TempUnit^.BlockOffset [stTypedConstantsBlocks]);
Inc (Reference.Ofs, PWord (PChar (TempUnit) + BlockRecord)^);
Reference.Seg := DataSegment;
end else begin
If (ReferenceFlags * [rfSegment, rfOffset] = []) or
(UnitPtr^.OverlayedUnitCodeSize = 0) then
begin
Inc (Reference.Ofs, ProcedureRecordPtr^.SizeOfConstants);
BlockRecord := ProcedureRecordPtr^.ProgramCodeBlockRecordOffset;
Inc (BlockRecord, TempUnit^.BlockOffset [stCodeBlocks]);
Inc (Reference.Ofs, PWord (PChar (TempUnit) + BlockRecord)^);
Reference.Seg := TempUnit^.CodeSegment;
end else begin
Inc (Reference.Ofs, ProcedureRecordPtr^.OverlayedProcedureOffset);
Reference.Seg := TempUnit^.CodeSegment;
end;
end;
end;
end;
ReferencePointer := DataBlockPointer.Ptr;
Inc (ReferencePointerRec.Ofs, ReferencePosition);
Case rfOffset in ReferenceFlags of
True: begin
ReferencePointer^.Ofs := Reference.Ofs;
If rfSegment in ReferenceFlags then ReferencePointer^.Seg := Reference.Seg;
end;
else If rfSegment in ReferenceFlags then ReferencePointer^.Word := Reference.Seg
else ReferencePointer^.Word := Reference.Ofs - ReferencePosition - UsedBlockOffset - 2;
end;
Inc (ReferenceRecord);
end;
end;
begin
CurrentUnitForProcessing := UnitPtrRec.Seg;
ReferenceRecordsSegment := ReferencesBlockSegment;
DataBlockPointer.Seg := DataBlockSegment;
CodeConstBlock := Ptr (UnitPtrRec.Seg, UnitPtr^.BlockOffset [Block]);
CurrentBlockOffset := 0;
ReferenceRecord := Ptr (ReferenceRecordsSegment, 0);
While CodeConstBlockRec.Ofs <> UnitPtr^.BlockOffset [Succ (Block)] do
begin
If CodeConstBlock^.Offset <> BlockUnused then
begin
UsedBlockOffset := CodeConstBlock^.Offset;
DataBlockPointer.Ofs := CurrentBlockOffset;
ResolveReferencesForUsedBlock;
end else Inc (ReferenceRec.Ofs, CodeConstBlock^.ReferencesSize);
Inc (CurrentBlockOffset, CodeConstBlock^.Size);
Inc (CodeConstBlock);
end;
end;