Creating References
Whenever Turbo Pascal needs to reference anything that doesn’t have fixed location, i.e. its address is not known yet like variables, typed constants or procedures, the compiler generates intermediate code reference record which contains all information to later resolve the reference.
Procedure GenerateReference (Segment, BlockRecord, RefOfs: Word; RefFlags: TReferenceFlagSet);
Var ReferencedUnitRecord: Word;
begin
ReferencedUnitRecord := AddReferencedModule (Segment);
With PIntermediateCodeRecord (IncreaseSymbolTable (stIntermediateCode, 7))^ do
begin
RecordType := icReference;
ReferencedUnitRecordOfs := ReferencedUnitRecord or Word (RefFlags);
ReferencedBlockRecordOfs := BlockRecord;
ReferencedOfs := RefOfs;
end;
end;
All referenced modules are kept in a symbol table.
Function AddReferencedModule (ReferencedModuleSegment: Word): Word;
Var ReferencedModuleRecord: PReferencedModulesBlockRecord;
ReferencedModuleRecordOfs: Word absolute ReferencedModuleRecord;
UnitNameIdentifier: PIdentifier;
begin
ReferencedModuleRecord := Ptr (SymbolTable [stReferencedModules].Segment, 0);
While ReferencedModuleRecordOfs <> SymbolTable [stReferencedModules].NextRecordOffset do
begin
If ReferencedModuleRecord^.ModuleSegment = ReferencedModuleSegment then
begin
AddReferencedModule := ReferencedModuleRecordOfs;
Exit;
end;
Inc (ReferencedModuleRecordOfs, ReferencedModuleRecord^.UnitName.Len + 5);
end;
If ReferencedModuleRecordOfs >= $1000 then Error (TooManySymbols);
UnitNameIdentifier := { ReferencedModuleRecord Offset must be < $1000 to add flags in highest nibble }
PIdentifier (Ptr (ReferencedModuleSegment, PUnitHeader (Ptr (ReferencedModuleSegment, 0))^.UnitNameIdentifierOffset));
ReferencedModuleRecord := IncreaseSymbolTable (stReferencedModules, UnitNameIdentifier^.Name.Len + 5);
With ReferencedModuleRecord^ do
begin
ModuleSegment := ReferencedModuleSegment;
rmrW2 := 0;
UnitName.Str := UnitNameIdentifier^.Name.Str;
end;
AddReferencedModule := Ofs (ReferencedModuleRecord^);
end;