Loading Variables

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;

                                                                                                                             {
 
 
 
© 2017 Turbo Pascal | Privacy Policy