[fpc-devel] RTTI interface & variant late binding issue (mORMot)

Steve Hildebrandt Steve.Kassel at web.de
Sun Apr 12 16:07:52 CEST 2015



Am 11.04.2015 um 18:39 schrieb Florian Klämpfl:
> Am 20.02.2015 um 19:21 schrieb Steve Hildebrandt:
>> Here ist the current state of affairs for i386 only right now.
>>
>> The Patches are currently based on http://svn.freepascal.org/svn/fpc/trunk@29760
> I've created an svn branch for the patches: http://svn.freepascal.org/svn/fpc/branches/interfacertti
> (if anybody is interested to contribute, just drop me a note so I can create an account with write
> access to it). I plan to commit the patches Steve submitted so far to this branch. However, I am
> missing the 0004-... .patch. Did I overlook something or is there simply no patch with number 0004?
>
> _______________________________________________
> fpc-devel maillist  -  fpc-devel at lists.freepascal.org
> http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
>
Here are all changes I made again.
I would like to have an account.

mfg Steve
-------------- next part --------------
>From 246c22ea591d056d74cd89da79e55bae7ee95154 Mon Sep 17 00:00:00 2001
From: Steve Hildebrandt <Steve.Kassel at web.de>
Date: Fri, 20 Feb 2015 17:00:33 +0100
Subject: [PATCH 1/6] Added Base Structure for delphi compatible interface RTTI

---
 compiler/ncgrtti.pas  | 197 +++++++++++++++++++++++++++++++++++---------------
 rtl/objpas/typinfo.pp |  56 +++++++++++++-
 2 files changed, 195 insertions(+), 58 deletions(-)

diff --git a/compiler/ncgrtti.pas b/compiler/ncgrtti.pas
index 9d8e618..890c235 100644
--- a/compiler/ncgrtti.pas
+++ b/compiler/ncgrtti.pas
@@ -28,7 +28,7 @@ interface
     uses
       cclasses,constexp,
       aasmbase,
-      symbase,symconst,symtype,symdef;
+      symbase,symconst,symtype,symdef,symsym;
 
     type
 
@@ -43,6 +43,8 @@ interface
         procedure published_write_rtti(st:tsymtable;rt:trttitype);
         function  published_properties_count(st:tsymtable):longint;
         procedure published_properties_write_rtti_data(propnamelist:TFPHashObjectList;st:tsymtable);
+        procedure write_param_flag(parasym:tparavarsym);
+        procedure methods_write_rtti(st:tsymtable);
         procedure collect_propnamelist(propnamelist:TFPHashObjectList;objdef:tobjectdef);
         function  ref_rtti(def:tdef;rt:trttitype):tasmsymbol;
         procedure write_rtti_name(def:tdef);
@@ -69,7 +71,6 @@ implementation
        cutils,
        globals,globtype,verbose,systems,
        fmodule, procinfo,
-       symsym,
        aasmtai,aasmdata,
        defutil,
        wpobase
@@ -83,6 +84,23 @@ implementation
          symconst.ds_none,symconst.ds_none,
          symconst.ds_none,symconst.ds_none);
 
+       ProcCallOptionToCallConv: array[tproccalloption] of byte = (
+        { pocall_none       } 0,
+        { pocall_cdecl      } 1,
+        { pocall_cppdecl    } 5,
+        { pocall_far16      } 6,
+        { pocall_oldfpccall } 7,
+        { pocall_internproc } 8,
+        { pocall_syscall    } 9,
+        { pocall_pascal     } 2,
+        { pocall_register   } 0,
+        { pocall_safecall   } 4,
+        { pocall_stdcall    } 3,
+        { pocall_softfloat  } 10,
+        { pocall_mwpascal   } 11,
+        { pocall_interrupt  } 12
+       );
+
     type
        TPropNameListItem = class(TFPHashObject)
          propindex : longint;
@@ -414,6 +432,96 @@ implementation
           end;
       end;
 
+    procedure TRTTIWriter.write_param_flag(parasym:tparavarsym);
+    var
+      paraspec : byte;
+    begin
+      case parasym.varspez of
+        vs_value   : paraspec := 0;
+        vs_const   : paraspec := pfConst;
+        vs_var     : paraspec := pfVar;
+        vs_out     : paraspec := pfOut;
+        vs_constref: paraspec := pfConstRef;
+      else
+        internalerror(2013112904);
+      end;
+      { Kylix also seems to always add both pfArray and pfReference
+      in this case
+      }
+      if is_open_array(parasym.vardef) then
+        paraspec:=paraspec or pfArray or pfReference;
+      { and these for classes and interfaces (maybe because they
+      are themselves addresses?)
+      }
+      if is_class_or_interface(parasym.vardef) then
+        paraspec:=paraspec or pfAddress;
+      { set bits run from the highest to the lowest bit on
+      big endian systems
+      }
+      if (target_info.endian = endian_big) then
+        paraspec:=reverse_byte(paraspec);
+      { write flags for current parameter }
+      current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(paraspec));
+    end;
+
+    procedure TRTTIWriter.methods_write_rtti(st: tsymtable);
+    var
+      count: Word;
+      i,j,k: LongInt;
+
+      sym : tprocsym;
+      def : tabstractprocdef;
+      para : tparavarsym;
+
+      reg: Byte;
+      off: LongInt;
+    begin
+      count:=0;
+      for i:=0 to st.SymList.Count-1 do
+        if (tsym(st.SymList[i]).typ=procsym) then
+          inc(count);
+
+      current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(count));
+      current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(count));
+
+      for i:=0 to st.SymList.Count-1 do
+        if (tsym(st.SymList[i]).typ=procsym) then
+          begin
+            sym:=tprocsym(st.SymList[i]);
+            for j:=0 to sym.ProcdefList.count-1 do
+              begin
+                def:=tabstractprocdef(sym.ProcdefList[j]);
+                def.init_paraloc_info(callerside);
+
+                write_string(sym.realname);
+                current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(3));
+                current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(ProcCallOptionToCallConv[def.proccalloption]));
+                write_rtti_reference(def.returndef,fullrtti);
+                current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(def.callerargareasize));
+                current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(def.maxparacount + 1));
+
+                for k:=0 to def.paras.count-1 do
+                  begin
+                    para:=tparavarsym(def.paras[k]);
+
+                    { write flags for current parameter }
+                    write_param_flag(para);
+                    maybe_write_align;
+                    { write param type }
+                    write_rtti_reference(para.vardef,fullrtti);
+
+                    reg:=0;
+                    off:=0;
+                    current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(reg));
+                    current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(off));
+
+                    { write name of current parameter }
+                    write_string(para.realname);
+                  end;
+              end;
+          end;
+    end;
+
 
     procedure TRTTIWriter.write_rtti_data(def:tdef;rt:trttitype);
 
@@ -686,55 +794,6 @@ implementation
 
 
         procedure procvardef_rtti(def:tprocvardef);
-           const
-             ProcCallOptionToCallConv: array[tproccalloption] of byte = (
-              { pocall_none       } 0,
-              { pocall_cdecl      } 1,
-              { pocall_cppdecl    } 5,
-              { pocall_far16      } 6,
-              { pocall_oldfpccall } 7,
-              { pocall_internproc } 8,
-              { pocall_syscall    } 9,
-              { pocall_pascal     } 2,
-              { pocall_register   } 0,
-              { pocall_safecall   } 4,
-              { pocall_stdcall    } 3,
-              { pocall_softfloat  } 10,
-              { pocall_mwpascal   } 11,
-              { pocall_interrupt  } 12
-             );
-
-           procedure write_param_flag(parasym:tparavarsym);
-             var
-               paraspec : byte;
-             begin
-               case parasym.varspez of
-                 vs_value   : paraspec := 0;
-                 vs_const   : paraspec := pfConst;
-                 vs_var     : paraspec := pfVar;
-                 vs_out     : paraspec := pfOut;
-                 vs_constref: paraspec := pfConstRef;
-                 else
-                   internalerror(2013112904);
-               end;
-               { Kylix also seems to always add both pfArray and pfReference
-                 in this case
-               }
-               if is_open_array(parasym.vardef) then
-                 paraspec:=paraspec or pfArray or pfReference;
-               { and these for classes and interfaces (maybe because they
-                 are themselves addresses?)
-               }
-               if is_class_or_interface(parasym.vardef) then
-                 paraspec:=paraspec or pfAddress;
-               { set bits run from the highest to the lowest bit on
-                 big endian systems
-               }
-               if (target_info.endian = endian_big) then
-                 paraspec:=reverse_byte(paraspec);
-               { write flags for current parameter }
-               current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(paraspec));
-             end;
 
            procedure write_para(parasym:tparavarsym);
              begin
@@ -944,15 +1003,24 @@ implementation
             maybe_write_align;
 
             { write iidstr }
-            if assigned(def.iidstr) then
-              write_string(def.iidstr^)
-            else
-              current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(0));
-            maybe_write_align;
+            if def.objecttype = odt_interfacecorba then
+              begin
+                if assigned(def.iidstr) then
+                  write_string(def.iidstr^)
+                else
+                  current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(0));
+
+                maybe_write_align;
+              end;
 
             { write published properties for this object }
+            current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(published_properties_count(def.symtable)));
+            maybe_write_align;
             published_properties_write_rtti_data(propnamelist,def.symtable);
 
+            { write methods for this object }
+            methods_write_rtti(def.symtable);
+
             propnamelist.free;
           end;
 
@@ -1283,6 +1351,8 @@ implementation
     end;
 
     procedure TRTTIWriter.write_child_rtti_data(def:tdef;rt:trttitype);
+    var
+      i,j: SizeInt;
       begin
         case def.typ of
           enumdef :
@@ -1304,7 +1374,20 @@ implementation
               if (rt=initrtti) or (tobjectdef(def).objecttype=odt_object) then
                 fields_write_rtti(tobjectdef(def).symtable,rt)
               else
-                published_write_rtti(tobjectdef(def).symtable,rt);
+                begin
+                  published_write_rtti(tobjectdef(def).symtable,rt);
+
+                  if is_any_interface_kind(def) then
+                    with tobjectdef(def).symtable do
+                      for i := 0 to SymList.Count-1 do
+                        if (tsym(SymList[i]).typ=procsym) then
+                          with tprocsym(tobjectdef(def).symtable.SymList[i]) do
+                            for j := 0 to ProcdefList.Count - 1 do
+                              begin
+                                write_rtti(tabstractprocdef(ProcdefList[j]).returndef,rt);
+                                params_write_rtti(tabstractprocdef(ProcdefList[j]),rt);
+                              end;
+                end;
             end;
           classrefdef,
           pointerdef:
diff --git a/rtl/objpas/typinfo.pp b/rtl/objpas/typinfo.pp
index f37b45b..7ba025a 100644
--- a/rtl/objpas/typinfo.pp
+++ b/rtl/objpas/typinfo.pp
@@ -54,7 +54,7 @@ unit typinfo;
        TMethodKind = (mkProcedure,mkFunction,mkConstructor,mkDestructor,
                       mkClassProcedure,mkClassFunction,mkClassConstructor, 
                       mkClassDestructor,mkOperatorOverload);
-       TParamFlag     = (pfVar,pfConst,pfArray,pfAddress,pfReference,pfOut);
+       TParamFlag     = (pfVar,pfConst,pfArray,pfAddress,pfReference,pfOut,pfConstRef);
        TParamFlags    = set of TParamFlag;
        TIntfFlag      = (ifHasGuid,ifDispInterface,ifDispatch,ifHasStrGUID);
        TIntfFlags     = set of TIntfFlag;
@@ -63,6 +63,7 @@ unit typinfo;
        // don't rely on integer values of TCallConv since it includes all conventions
        // which both delphi and fpc support. In the future delphi can support more and
        // fpc own conventions will be shifted/reordered accordinly
+       PCallConv = ^TCallConv;
        TCallConv = (ccReg, ccCdecl, ccPascal, ccStdCall, ccSafeCall,
                     ccCppdecl, ccFar16, ccOldFPCCall, ccInternProc,
                     ccSysCall, ccSoftFloat, ccMWPascal);
@@ -161,6 +162,49 @@ unit typinfo;
         function GetParam(ParamIndex: Integer): PProcedureParam;
       end;
 
+      PVmtMethodParam = ^TVmtMethodParam;
+      TVmtMethodParam =
+      {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
+      packed
+      {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
+      record
+        Flags: TParamFlags;
+        ParamType: PTypeInfo;
+        ParReg: Byte;
+        ParOff: LongInt;
+        Name: ShortString;
+        {Attribute data TODO}
+      end;
+
+      PIntfMethodEntry = ^TIntfMethodEntry;
+      TIntfMethodEntry =
+      {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
+      packed
+      {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
+      record
+        Name: ShortString;
+        {
+        Version: Byte;
+        CC: TCallConv;
+        ResultType: PTypeInfo;
+        StackSize: Word;
+        ParamCount: Byte;
+        Params: array[0..ParamCount - 1] of TVmtMethodParam;
+        }
+        {Attribute data TODO}
+      end;
+
+      PIntfMethodTable = ^TIntfMethodTable;
+      TIntfMethodTable =
+      {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
+      packed
+      {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
+      record
+        Count: Word;
+        RTTICount: Word;//$FFFF if there is no further info, or the value of Count
+        {Entry: array[0..Count - 1] of TIntfMethodEntry}
+      end;
+
       PTypeData = ^TTypeData;
       TTypeData =
 {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
@@ -241,6 +285,11 @@ unit typinfo;
                IntfFlags : TIntfFlagsBase;
                GUID: TGUID;
                IntfUnit: ShortString;
+               {
+               IntfPropCount: Word;
+               IntfProps: array[0..IntfPropCount-1] of TPropInfo;
+               IntfMethTable : TIntfMethodTable;
+               }
               );
             tkInterfaceRaw:
               (
@@ -249,6 +298,11 @@ unit typinfo;
                IID: TGUID;
                RawIntfUnit: ShortString;
                IIDStr: ShortString;
+               {
+               RawIntfPropCount: Word;
+               RawIntfProps: array[0..IntfPropCount-1] of TPropInfo;
+               IntfMethTable : TIntfMethodTable;
+               }
               );
             tkArray:
               (ArrayData: TArrayTypeData);
-- 
1.9.5.msysgit.0

-------------- next part --------------
>From 91d2c2ceccb4ce59caa9645e03e82b162306b4bf Mon Sep 17 00:00:00 2001
From: Steve Hildebrandt <Steve.Kassel at web.de>
Date: Fri, 20 Feb 2015 19:12:34 +0100
Subject: [PATCH 2/6] Added base for Reg/Off calculation to paramgr

---
 compiler/ncgrtti.pas | 11 ++++++++---
 compiler/paramgr.pas |  8 ++++++++
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/compiler/ncgrtti.pas b/compiler/ncgrtti.pas
index 890c235..9c2c9a2 100644
--- a/compiler/ncgrtti.pas
+++ b/compiler/ncgrtti.pas
@@ -73,7 +73,8 @@ implementation
        fmodule, procinfo,
        aasmtai,aasmdata,
        defutil,
-       wpobase
+       wpobase,
+       paramgr
        ;
 
 
@@ -504,14 +505,18 @@ implementation
                   begin
                     para:=tparavarsym(def.paras[k]);
 
+                    if (vo_is_hidden_para in para.varoptions) and not
+                       (vo_is_self in para.varoptions) then
+                      continue;
+
                     { write flags for current parameter }
                     write_param_flag(para);
                     maybe_write_align;
                     { write param type }
                     write_rtti_reference(para.vardef,fullrtti);
 
-                    reg:=0;
-                    off:=0;
+                    paramanager.get_para_regoff(def.proccalloption, para.paraloc[callerside].location,reg,off);
+
                     current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(reg));
                     current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(off));
 
diff --git a/compiler/paramgr.pas b/compiler/paramgr.pas
index bb63456..44f767c 100644
--- a/compiler/paramgr.pas
+++ b/compiler/paramgr.pas
@@ -81,6 +81,8 @@ unit paramgr;
           function get_volatile_registers_flags(calloption : tproccalloption):tcpuregisterset;virtual;
           function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;virtual;
 
+          procedure get_para_regoff(proccalloption: tproccalloption; paraloc: pcgparalocation; out reg: Byte; out off: LongInt);virtual;
+
           procedure getintparaloc(pd: tabstractprocdef; nr : longint; var cgpara: tcgpara);virtual;
 
           {# allocate an individual pcgparalocation that's part of a tcgpara
@@ -278,6 +280,12 @@ implementation
         result:=[];
       end;
 
+    procedure tparamanager.get_para_regoff(proccalloption: tproccalloption; paraloc: pcgparalocation; out reg: Byte; out off: LongInt);
+    begin
+      reg:=0;
+      off:=0;
+    end;
+
 {$if first_mm_imreg = 0}
   {$WARN 4044 OFF} { Comparison might be always false ... }
 {$endif}
-- 
1.9.5.msysgit.0

-------------- next part --------------
>From 477886c9ed8c98ff247a0e070aa303dd5dde9530 Mon Sep 17 00:00:00 2001
From: Steve Hildebrandt <Steve.Kassel at web.de>
Date: Fri, 20 Feb 2015 19:12:47 +0100
Subject: [PATCH 3/6] Updated paramgr implementation for i386

---
 compiler/i386/cpupara.pas | 29 +++++++++++++++++++++++++++--
 1 file changed, 27 insertions(+), 2 deletions(-)

diff --git a/compiler/i386/cpupara.pas b/compiler/i386/cpupara.pas
index f33c2ff..a599e3f 100644
--- a/compiler/i386/cpupara.pas
+++ b/compiler/i386/cpupara.pas
@@ -32,6 +32,9 @@ unit cpupara;
        parabase,paramgr;
 
     type
+
+       { ti386paramanager }
+
        ti386paramanager = class(tparamanager)
           function param_use_paraloc(const cgpara:tcgpara):boolean;override;
           function ret_in_param(def:tdef;pd:tabstractprocdef):boolean;override;
@@ -40,6 +43,7 @@ unit cpupara;
           function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override;
+          procedure get_para_regoff(proccalloption: tproccalloption; paraloc: pcgparalocation; out reg: Byte; out off: LongInt);override;
           function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
           function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
           procedure createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);override;
@@ -285,8 +289,29 @@ unit cpupara;
         result:=[0..first_mm_imreg-1];
       end;
 
-
-
+    procedure ti386paramanager.get_para_regoff(proccalloption: tproccalloption; paraloc: pcgparalocation; out reg: Byte; out off: LongInt);
+    var
+      I : SizeInt;
+    begin
+      with paraloc^ do
+        case loc of
+          LOC_REGISTER:
+            begin
+              for I := 0 to high(parasupregs) do
+                if getsupreg(register)=parasupregs[I] then
+                  begin
+                    reg:=I;
+                    break;
+                  end;
+              off:=0;
+            end;
+          LOC_REFERENCE:
+            begin
+              reg:=255;
+              off:=reference.offset;
+            end;
+        end;
+    end;
 
     function  ti386paramanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): TCGPara;
       var
-- 
1.9.5.msysgit.0

-------------- next part --------------
>From cba8d94e928d8c2156afdb464dfb355c9662d337 Mon Sep 17 00:00:00 2001
From: Steve Hildebrandt <Steve.Kassel at web.de>
Date: Fri, 20 Feb 2015 23:16:33 +0100
Subject: [PATCH 4/6] Fixed interface method rtti bug for methods with the same
 signature.

---
 compiler/ncgrtti.pas | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler/ncgrtti.pas b/compiler/ncgrtti.pas
index 9c2c9a2..33a6fda 100644
--- a/compiler/ncgrtti.pas
+++ b/compiler/ncgrtti.pas
@@ -480,7 +480,7 @@ implementation
       count:=0;
       for i:=0 to st.SymList.Count-1 do
         if (tsym(st.SymList[i]).typ=procsym) then
-          inc(count);
+          inc(count, tprocsym(st.SymList[i]).ProcdefList.count);
 
       current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(count));
       current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(count));
-- 
1.9.5.msysgit.0

-------------- next part --------------
>From 5e99deff39531e46b6bdfb814e3198da82de63cb Mon Sep 17 00:00:00 2001
From: Steve Hildebrandt <Steve.Kassel at web.de>
Date: Wed, 25 Feb 2015 21:10:03 +0100
Subject: [PATCH 5/6] Updated paramgr implementation for arm

---
 compiler/arm/cpupara.pas | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/compiler/arm/cpupara.pas b/compiler/arm/cpupara.pas
index a917850..de7a1c6 100644
--- a/compiler/arm/cpupara.pas
+++ b/compiler/arm/cpupara.pas
@@ -36,6 +36,7 @@ unit cpupara;
           function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override;
+          procedure get_para_regoff(proccalloption: tproccalloption; paraloc: pcgparalocation; out reg: Byte; out off: LongInt);override;
           function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
           function ret_in_param(def:tdef;pd:tabstractprocdef):boolean;override;
           procedure getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);override;
@@ -79,6 +80,44 @@ unit cpupara;
         result:=VOLATILE_MMREGISTERS;
       end;
 
+    procedure tarmparamanager.get_para_regoff(proccalloption: tproccalloption; paraloc: pcgparalocation; out reg: Byte; out off: LongInt);
+    var
+      I : SizeInt;
+    begin
+      with paraloc^ do
+        case loc of
+          LOC_REGISTER:
+            begin
+              reg:=getsupreg(register)-RS_R0;
+              off:=0;
+            end;
+          LOC_FPUREGISTER:
+            begin
+              reg:=getsupreg(register)-RS_F0;
+              off:=0;
+            end;
+          LOC_MMREGISTER:
+            begin
+              reg:=getsupreg(register);
+              if reg < RS_S1 then
+                begin
+                  reg:=reg-RS_D0;
+                  off:=0;
+                end
+              else
+                begin
+                  reg:=reg-RS_S1;
+                  off:=4;
+                end;
+            end;
+          LOC_REFERENCE:
+            begin
+              reg:=255;
+              off:=reference.offset;
+            end;
+        end;
+    end;
+
 
     procedure tarmparamanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
       var
-- 
1.9.5.msysgit.0

-------------- next part --------------
>From c44d8201e40587ca18d97a46a476d5fd670de236 Mon Sep 17 00:00:00 2001
From: Steve Hildebrandt <Steve.Kassel at web.de>
Date: Thu, 26 Feb 2015 13:05:47 +0100
Subject: [PATCH 6/6] Updated paramgr implementation for x86_64

---
 compiler/x86_64/cpupara.pas | 62 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 62 insertions(+)

diff --git a/compiler/x86_64/cpupara.pas b/compiler/x86_64/cpupara.pas
index 30b1acb..53805c3 100644
--- a/compiler/x86_64/cpupara.pas
+++ b/compiler/x86_64/cpupara.pas
@@ -33,6 +33,9 @@ unit cpupara;
       parabase,paramgr;
 
     type
+
+       { tx86_64paramanager }
+
        tx86_64paramanager = class(tparamanager)
        private
           procedure create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee;paras:tparalist;
@@ -44,6 +47,7 @@ unit cpupara;
           function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override;
           function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
+          procedure get_para_regoff(proccalloption: tproccalloption; paraloc: pcgparalocation; out reg: Byte; out off: LongInt);override;
           function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
           function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
           function get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;override;
@@ -909,6 +913,64 @@ unit cpupara;
         result:=[RS_ST0..RS_ST7];
       end;
 
+    procedure tx86_64paramanager.get_para_regoff(proccalloption: tproccalloption; paraloc: pcgparalocation; out reg: Byte; out off: LongInt);
+    var
+      I : SizeInt;
+    begin
+      with paraloc^ do
+        case loc of
+          LOC_REGISTER:
+            begin
+              reg:=getsupreg(register);
+              { winx64 uses different registers }
+              if target_info.system=system_x86_64_win64 then
+                begin
+                  for I := 0 to high(paraintsupregs_winx64) do
+                    if reg=paraintsupregs_winx64[I] then
+                      begin
+                        reg:=I;
+                        break;
+                      end;
+                end
+              else
+                for I := 0 to high(paraintsupregs) do
+                  if reg=paraintsupregs[I] then
+                    begin
+                      reg:=I;
+                      break;
+                    end;
+              off:=0;
+            end;
+          LOC_MMREGISTER:
+            begin
+              reg:=getsupreg(register);
+              { winx64 uses different registers }
+              if target_info.system=system_x86_64_win64 then
+                begin
+                  for I := 0 to high(parammsupregs_winx64) do
+                    if reg=parammsupregs_winx64[I] then
+                      begin
+                        reg:=I;
+                        break;
+                      end;
+                end
+              else
+                for I := 0 to high(parammsupregs) do
+                  if reg=parammsupregs[I] then
+                    begin
+                      reg:=I;
+                      break;
+                    end;
+              off:=0;
+            end;
+          LOC_REFERENCE:
+            begin
+              reg:=255;
+              off:=reference.offset;
+            end;
+        end;
+    end;
+
 
     function tx86_64paramanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; forcetempdef: tdef): tcgpara;
       const
-- 
1.9.5.msysgit.0



More information about the fpc-devel mailing list