Browse Source

+ initial implementation of the RTTI for parameter locations (not *yet* used by anything)

The parameter manager converts from the internal compiler representation of
a parameter's location to an RTTI representation. As the general implementation
more or less directly uses the compiler structures for this a platform specific
parameter manager may override this functionality in case some parameter
information changed in a non-backwards compatible way.
The RTTI parameter location has a layout that allows for an easy enumeration
as the size is fixed for all locations. Additionally there are properties that
allow for easy access to the information stored in them.

git-svn-id: trunk@35250 -
svenbarth 8 years ago
parent
commit
417f1cd49d
4 changed files with 213 additions and 2 deletions
  1. 25 2
      compiler/ncgrtti.pas
  2. 13 0
      compiler/parabase.pas
  3. 74 0
      compiler/paramgr.pas
  4. 101 0
      rtl/objpas/typinfo.pp

+ 25 - 2
compiler/ncgrtti.pas

@@ -28,7 +28,7 @@ interface
     uses
     uses
       cclasses,constexp,
       cclasses,constexp,
       aasmbase,aasmcnst,
       aasmbase,aasmcnst,
-      symbase,symconst,symtype,symdef;
+      symbase,symconst,symtype,symdef,symsym;
 
 
     type
     type
 
 
@@ -60,6 +60,7 @@ interface
         procedure write_header(tcb: ttai_typedconstbuilder; def: tdef; typekind: byte);
         procedure write_header(tcb: ttai_typedconstbuilder; def: tdef; typekind: byte);
         function write_methodkind(tcb:ttai_typedconstbuilder;def:tabstractprocdef):byte;
         function write_methodkind(tcb:ttai_typedconstbuilder;def:tabstractprocdef):byte;
         procedure write_callconv(tcb:ttai_typedconstbuilder;def:tabstractprocdef);
         procedure write_callconv(tcb:ttai_typedconstbuilder;def:tabstractprocdef);
+        procedure write_paralocs(tcb:ttai_typedconstbuilder;parasym:tparavarsym);
       public
       public
         constructor create;
         constructor create;
         procedure write_rtti(def:tdef;rt:trttitype);
         procedure write_rtti(def:tdef;rt:trttitype);
@@ -81,9 +82,10 @@ implementation
        cutils,
        cutils,
        globals,globtype,verbose,systems,
        globals,globtype,verbose,systems,
        fmodule, procinfo,
        fmodule, procinfo,
-       symtable,symsym,
+       symtable,
        aasmtai,aasmdata,
        aasmtai,aasmdata,
        defutil,
        defutil,
+       parabase,paramgr,
        wpobase
        wpobase
        ;
        ;
 
 
@@ -237,6 +239,27 @@ implementation
         tcb.emit_ord_const(ProcCallOptionToCallConv[def.proccalloption],u8inttype);
         tcb.emit_ord_const(ProcCallOptionToCallConv[def.proccalloption],u8inttype);
       end;
       end;
 
 
+
+    procedure TRTTIWriter.write_paralocs(tcb:ttai_typedconstbuilder;parasym:tparavarsym);
+      var
+        locs : trttiparalocs;
+        i : longint;
+      begin
+        locs:=paramanager.cgparalocs_to_rttiparalocs(parasym.paraloc[callerside].location);
+        if length(locs)>high(byte) then
+          internalerror(2017010601);
+        tcb.emit_ord_const(length(locs),u8inttype);
+        for i:=low(locs) to high(locs) do
+          begin
+            tcb.emit_ord_const(locs[i].loctype,u8inttype);
+            tcb.emit_ord_const(locs[i].regsub,u8inttype);
+            tcb.emit_ord_const(locs[i].regindex,u16inttype);
+            { the corresponding type for aint is alusinttype }
+            tcb.emit_ord_const(locs[i].offset,alusinttype);
+          end;
+      end;
+
+
     procedure TRTTIWriter.write_rtti_name(tcb: ttai_typedconstbuilder; def: tdef);
     procedure TRTTIWriter.write_rtti_name(tcb: ttai_typedconstbuilder; def: tdef);
       begin
       begin
          if is_open_array(def) then
          if is_open_array(def) then

+ 13 - 0
compiler/parabase.pas

@@ -140,6 +140,19 @@ unit parabase;
        end;
        end;
 
 
 
 
+       trttiparaloc = record
+         { contains the regtype in bits 0-6 and whether it's reference or not
+           in bit 7 }
+         loctype : byte;
+         regsub : byte;
+         regindex : word;
+         { either stack offset or shiftval }
+         offset : aint;
+       end;
+
+
+       trttiparalocs = array of trttiparaloc;
+
 
 
 implementation
 implementation
 
 

+ 74 - 0
compiler/paramgr.pas

@@ -137,6 +137,10 @@ unit paramgr;
           function parseparaloc(parasym : tparavarsym;const s : string) : boolean;virtual;
           function parseparaloc(parasym : tparavarsym;const s : string) : boolean;virtual;
           function parsefuncretloc(p : tabstractprocdef; const s : string) : boolean;virtual;
           function parsefuncretloc(p : tabstractprocdef; const s : string) : boolean;virtual;
 
 
+          { Convert a list of CGParaLocation entries to a RTTIParaLoc array that
+            can be written by ncgrtti }
+          function cgparalocs_to_rttiparalocs(paralocs:pcgparalocation):trttiparalocs;
+
           { allocate room for parameters on the stack in the entry code? }
           { allocate room for parameters on the stack in the entry code? }
           function use_fixed_stack: boolean;
           function use_fixed_stack: boolean;
           { whether stack pointer can be changed in the middle of procedure }
           { whether stack pointer can be changed in the middle of procedure }
@@ -155,6 +159,11 @@ unit paramgr;
             for which the def is paradef and the integer length is restlen.
             for which the def is paradef and the integer length is restlen.
             fullsize is true if restlen equals the full paradef size }
             fullsize is true if restlen equals the full paradef size }
           function get_paraloc_def(paradef: tdef; restlen: aint; fullsize: boolean): tdef;
           function get_paraloc_def(paradef: tdef; restlen: aint; fullsize: boolean): tdef;
+
+          { convert a single CGParaLocation to a RTTIParaLoc; the method *might*
+            be overriden by targets to provide backwards compatibility with
+            older versions in case register indices changed }
+          function cgparaloc_to_rttiparaloc(paraloc:pcgparalocation):trttiparaloc;virtual;
        end;
        end;
 
 
 
 
@@ -662,6 +671,71 @@ implementation
       end;
       end;
 
 
 
 
+    function tparamanager.cgparalocs_to_rttiparalocs(paralocs:pcgparalocation):trttiparalocs;
+      var
+        c : longint;
+        tmploc : pcgparalocation;
+      begin
+        c:=0;
+        tmploc:=paralocs;
+        while assigned(tmploc) do
+          begin
+            inc(c);
+            tmploc:=tmploc^.next;
+          end;
+
+        setlength(result,c);
+
+        c:=0;
+        tmploc:=paralocs;
+        while assigned(tmploc) do
+          begin
+            result[c]:=cgparaloc_to_rttiparaloc(tmploc);
+            inc(c);
+            tmploc:=tmploc^.next;
+          end;
+      end;
+
+
+    function tparamanager.cgparaloc_to_rttiparaloc(paraloc:pcgparalocation):trttiparaloc;
+      var
+        reg : tregisterrec;
+      begin
+        if paraloc^.Loc=LOC_REFERENCE then
+          begin
+            reg:=tregisterrec(paraloc^.reference.index);
+            result.offset:=paraloc^.reference.offset;
+            result.loctype:=$80;
+          end
+        else
+          begin
+            reg:=tregisterrec(paraloc^.register);
+            { use sign extension }
+            result.offset:=paraloc^.shiftval;
+            result.loctype:=$00;
+          end;
+        case reg.regtype of
+          R_INTREGISTER,
+          R_FPUREGISTER,
+          R_MMXREGISTER,
+          R_MMREGISTER,
+          R_SPECIALREGISTER,
+          R_ADDRESSREGISTER:
+            begin
+              result.loctype:=result.loctype or ord(reg.regtype);
+              result.regsub:=ord(reg.subreg);
+              result.regindex:=reg.supreg;
+            end;
+          else
+            begin
+              { no need to adjust loctype }
+              result.regsub:=0;
+              result.regindex:=0;
+            end;
+        end;
+      end;
+
+
 initialization
 initialization
   ;
   ;
 finalization
 finalization

+ 101 - 0
rtl/objpas/typinfo.pp

@@ -80,6 +80,72 @@ unit typinfo;
       TTypeKinds = set of TTypeKind;
       TTypeKinds = set of TTypeKind;
       ShortStringBase = string[255];
       ShortStringBase = string[255];
 
 
+{$push}
+{$scopedenums on}
+      TSubRegister = (
+        None,
+        Lo,
+        Hi,
+        Word,
+        DWord,
+        QWord,
+        FloatSingle,
+        FloatDouble,
+        FloatQuad,
+        MultiMediaSingle,
+        MultiMediaDouble,
+        MultiMediaWhole,
+        MultiMediaX,
+        MultiMediaY
+      );
+
+      TRegisterType = (
+        Invalid,
+        Int,
+        FP,
+        MMX,
+        MultiMedia,
+        Special,
+        Address
+      );
+{$pop}
+
+      TParameterLocation =
+{$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
+      packed
+{$endif FPC_REQUIRES_PROPER_ALIGNMENT}
+      record
+      private
+        LocType: Byte;
+        function GetRegType: TRegisterType; inline;
+        function GetReference: Boolean; inline;
+        function GetShiftVal: Int8; inline;
+      public
+        RegSub: TSubRegister;
+        RegNumber: Word;
+        { Stack offset if Reference, ShiftVal if not }
+        Offset: SizeInt;
+        { if Reference then the register is the index register otherwise the
+          register in wihch (part of) the parameter resides }
+        property Reference: Boolean read GetReference;
+        property RegType: TRegisterType read GetRegType;
+        { if Reference, otherwise 0 }
+        property ShiftVal: Int8 read GetShiftVal;
+      end;
+      PParameterLocation = ^TParameterLocation;
+
+      TParameterLocations =
+{$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
+      packed
+{$endif FPC_REQUIRES_PROPER_ALIGNMENT}
+      record
+      private
+        function GetLocation(aIndex: Byte): PParameterLocation; inline;
+      public
+        Count: Byte;
+        property Location[Index: Byte]: PParameterLocation read GetLocation;
+      end;
+
       PVmtFieldEntry = ^TVmtFieldEntry;
       PVmtFieldEntry = ^TVmtFieldEntry;
       TVmtFieldEntry =
       TVmtFieldEntry =
 {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
 {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
@@ -2298,6 +2364,41 @@ begin
   Result:=IsStoredProp(instance,FindPropInfo(Instance,PropName));
   Result:=IsStoredProp(instance,FindPropInfo(Instance,PropName));
 end;
 end;
 
 
+{ TParameterLocation }
+
+function TParameterLocation.GetReference: Boolean;
+begin
+  Result := (LocType and $80) <> 0;
+end;
+
+function TParameterLocation.GetRegType: TRegisterType;
+begin
+  Result := TRegisterType(LocType and $7F);
+end;
+
+function TParameterLocation.GetShiftVal: Int8;
+begin
+  if GetReference then begin
+    if Offset < Low(Int8) then
+      Result := Low(Int8)
+    else if Offset > High(Int8) then
+      Result := High(Int8)
+    else
+      Result := Offset;
+  end else
+    Result := 0;
+end;
+
+{ TParameterLocations }
+
+function TParameterLocations.GetLocation(aIndex: Byte): PParameterLocation;
+begin
+  if aIndex >= Count then
+    Result := Nil
+  else
+    Result := PParameterLocation(@Count + SizeOf(Count) + SizeOf(TParameterLocation) * Count);
+end;
+
 { TProcedureParam }
 { TProcedureParam }
 
 
 function TProcedureParam.GetParamType: PTypeInfo;
 function TProcedureParam.GetParamType: PTypeInfo;