This procedure loads variable data from symbol table and sets all expression fields accordingly. Absolute variables are loaded from the target variable which is in memory and for record or object fields base address is loaded.
Procedure TExpression.LoadVariable;
Var IdentifierDataPtr: PVariableIdentifierData;
begin
GetNextToken;
IdentifierDataPtr := CurrentVariableIdentifierData;
TypeDefPtr := PointerFromOffsets (IdentifierDataPtr^.UnitTypeOffsets);
DataType := TypeDefPtr^.DataType;
Location := elMemory;
UsedRegisters := [];
IdentifierDataPtr := CurrentVariableIdentifierData;
While vfAbsoluteVar in IdentifierDataPtr^.Flags do
IdentifierDataPtr := PVariableIdentifierData (PointerFromOffsets (IdentifierDataPtr^.AbsoluteVarDataOffsets));
If Field in IdentifierDataPtr^.Flags then
begin
LoadSelfAddress;
Inc (Value.VarOffset, IdentifierDataPtr^.W1.Ofs);
Exit;
end;
Value.VarOffset := IdentifierDataPtr^.W1.Ofs;
If IdentifierDataPtr^.Flags * VariableTypeMask = GlobalVariable then
begin
LocationData.Flags := [segDS];
Value.VarSegment := IdentifierDataPtr^.W1.Seg;
Value.W14 := Seg (IdentifierDataPtr^);
end else If IdentifierDataPtr^.Flags * VariableTypeMask = TypedConstant then
begin
LocationData.Flags := [efTypedConstant, segDS];
Value.VarSegment := IdentifierDataPtr^.W1.Seg;
Value.W14 := Seg (IdentifierDataPtr^);
end else If IdentifierDataPtr^.Flags * VariableTypeMask = LocalStackVariable then
begin
Value.IdentifierDataPointer := IdentifierDataPtr;
LoadAddressOfLocalVariable (IdentifierDataPtr^.Flags, IdentifierDataPtr^.W1.Seg);
end else begin
Value.VarSegment := IdentifierDataPtr^.W1.Seg;
LocationData.Flags := [];
end;
If vfConst in IdentifierDataPtr^.Flags then Include (LocationData.Flags, efReadOnly);
EndIntermediateCodeSubroutine;
end;
This procedure generates code to load the address of local variable (on stack). Procedure TExpression.LoadAddressOfLocalVariable (Flags: TVarFlagsSet; ProcIdentifier: Word);
begin
If Flags * [vfOpenParameter, vfVar] <> [] then
begin
LocationData.Flags := [ofsDI, segES];
Load_ES_DI (ProcIdentifier, Value.Offset, 0);
Value.Offset := 0;
end else begin
LocationData.Flags := [ofsBP, segSS];
If ProcIdentifier <> CurrentProcedureIdentifier then
begin
LocationData.Flags := [ofsDI, segSS];
Load_ES_DI (ProcIdentifier, 0, 0);
end;
end;
end;
This procedure loads the address of Record or Object field variable. MethodIdentifierData: PProcedureIdentifierData;
WithRecord: PWithRecord;
begin
Case CurrentWithRecord = 0 of
True: begin
FindCurrentMethod (MethodIdentifier, MethodIdentifierData);
Load_ES_DI (Ofs (MethodIdentifier^), 6, 0);
LocationData.Flags := [ofsDI, segES];
Value.Word := 0;
end;
else begin
WithRecord := Ptr (SSeg, CurrentWithRecord);
Location := elMemory;
LocationData.Flags := WithRecord^.ExpressionFlags;
Case WithRecord^.RecordType of
1: begin
Value.Offset := WithRecord^.AddressOffset;
Value.BlockRecord := WithRecord^.BlockRecord;
Value.Segment := WithRecord^.AddressSegment;
end;
2: begin { Save Address }
Load_ES_DI (CurrentProcedureIdentifier, WithRecord^.AddressOffset, WithRecord^.BlockRecord);
Value.Word := 0;
end;
end;
end;
end;
EndIntermediateCodeSubroutine;
end;
{
This procedure finds current method. It jumps out of nested procedures until it finds a method. If method is found it returns True and method's identifier and data address, otherwise it returns False. MethodIdentifierDataOfs: Word absolute MethodIdentifierData;
begin
MethodIdentifier := Ptr (MainSymbolTable.Segment, CurrentProcedureIdentifier);
MethodIdentifierData := Ptr (MainSymbolTable.Segment, CurrentProcedureIdentifier);
FindCurrentMethod := True;
While MethodIdentifierOfs <> 0 do
begin
MethodIdentifierDataOfs := MethodIdentifierOfs + MethodIdentifier^.Name.Len + 4;
If pfMethod in MethodIdentifierData^.Flags then Exit;
MethodIdentifierOfs := MethodIdentifierData^.OuterBlockProcedureIdentifier;
end;
FindCurrentMethod := False;
end;
{
|