Browse Source

* add support for creating non-address-only procvars to
cprocvar.getreusableprocaddr()

git-svn-id: trunk@44516 -

Jonas Maebe 5 years ago
parent
commit
4ba19f5418

+ 1 - 1
compiler/aasmcnst.pas

@@ -1840,7 +1840,7 @@ implementation
 
 
    procedure ttai_typedconstbuilder.emit_procdef_const(pd: tprocdef);
    procedure ttai_typedconstbuilder.emit_procdef_const(pd: tprocdef);
      begin
      begin
-       emit_tai(Tai_const.Createname(pd.mangledname,AT_FUNCTION,0),cprocvardef.getreusableprocaddr(pd));
+       emit_tai(Tai_const.Createname(pd.mangledname,AT_FUNCTION,0),cprocvardef.getreusableprocaddr(pd,pc_address_only));
      end;
      end;
 
 
 
 

+ 1 - 1
compiler/llvm/hlcgllvm.pas

@@ -567,7 +567,7 @@ implementation
     { if this is a complex procvar, get the non-tmethod-like equivalent }
     { if this is a complex procvar, get the non-tmethod-like equivalent }
     if (pd.typ=procvardef) and
     if (pd.typ=procvardef) and
        not pd.is_addressonly then
        not pd.is_addressonly then
-      pd:=tprocvardef(cprocvardef.getreusableprocaddr(pd));
+      pd:=tprocvardef(cprocvardef.getreusableprocaddr(pd,pc_address_only));
   end;
   end;
 
 
 
 

+ 1 - 1
compiler/llvm/nllvmld.pas

@@ -117,7 +117,7 @@ procedure tllvmloadnode.pass_generate_code;
                 selfdef:=cpointerdef.getreusable(left.resultdef);
                 selfdef:=cpointerdef.getreusable(left.resultdef);
               mpref:=href;
               mpref:=href;
               hlcg.g_ptrtypecast_ref(current_asmdata.CurrAsmList,cpointerdef.getreusable(pvdef),cpointerdef.getreusable(methodpointertype),mpref);
               hlcg.g_ptrtypecast_ref(current_asmdata.CurrAsmList,cpointerdef.getreusable(pvdef),cpointerdef.getreusable(methodpointertype),mpref);
-              hlcg.g_load_reg_field_by_name(current_asmdata.CurrAsmList,cprocvardef.getreusableprocaddr(procdef),trecorddef(methodpointertype),procreg,'proc',mpref);
+              hlcg.g_load_reg_field_by_name(current_asmdata.CurrAsmList,cprocvardef.getreusableprocaddr(procdef,pc_address_only),trecorddef(methodpointertype),procreg,'proc',mpref);
               hlcg.g_load_reg_field_by_name(current_asmdata.CurrAsmList,selfdef,trecorddef(methodpointertype),selfreg,'self',mpref);
               hlcg.g_load_reg_field_by_name(current_asmdata.CurrAsmList,selfdef,trecorddef(methodpointertype),selfreg,'self',mpref);
               location_reset_ref(location,LOC_REFERENCE,location.size,href.alignment,href.volatility);
               location_reset_ref(location,LOC_REFERENCE,location.size,href.alignment,href.volatility);
               location.reference:=href;
               location.reference:=href;

+ 3 - 3
compiler/llvm/nllvmtcon.pas

@@ -408,7 +408,7 @@ implementation
   procedure tllvmtai_typedconstbuilder.emit_tai_procvar2procdef(p: tai; pvdef: tprocvardef);
   procedure tllvmtai_typedconstbuilder.emit_tai_procvar2procdef(p: tai; pvdef: tprocvardef);
     begin
     begin
       if not pvdef.is_addressonly then
       if not pvdef.is_addressonly then
-        pvdef:=cprocvardef.getreusableprocaddr(pvdef);
+        pvdef:=cprocvardef.getreusableprocaddr(pvdef,pc_address_only);
       emit_tai(p,pvdef);
       emit_tai(p,pvdef);
     end;
     end;
 
 
@@ -731,7 +731,7 @@ implementation
         the procdef }
         the procdef }
       if (fromdef.typ=procdef) and
       if (fromdef.typ=procdef) and
          (todef.typ<>procdef) then
          (todef.typ<>procdef) then
-        fromdef:=cprocvardef.getreusableprocaddr(tprocdef(fromdef));
+        fromdef:=cprocvardef.getreusableprocaddr(tprocdef(fromdef),pc_address_only);
       { typecasting a pointer-sized entity to a complex procvardef -> convert
       { typecasting a pointer-sized entity to a complex procvardef -> convert
         to the pointer-component of the complex procvardef (not always, because
         to the pointer-component of the complex procvardef (not always, because
         e.g. a tmethod to complex procvar initialises the entire complex
         e.g. a tmethod to complex procvar initialises the entire complex
@@ -739,7 +739,7 @@ implementation
       if (todef.typ=procvardef) and
       if (todef.typ=procvardef) and
          not tprocvardef(todef).is_addressonly and
          not tprocvardef(todef).is_addressonly and
          (fromdef.size<todef.size) then
          (fromdef.size<todef.size) then
-        todef:=cprocvardef.getreusableprocaddr(tprocvardef(todef));
+        todef:=cprocvardef.getreusableprocaddr(tprocvardef(todef),pc_address_only);
       op:=llvmconvop(fromdef,todef,false);
       op:=llvmconvop(fromdef,todef,false);
       case op of
       case op of
         la_ptrtoint_to_x,
         la_ptrtoint_to_x,

+ 2 - 2
compiler/ncgcal.pas

@@ -501,7 +501,7 @@ implementation
         hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,cpointerdef.getreusable(literaldef),true);
         hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,cpointerdef.getreusable(literaldef),true);
         { load the invoke pointer }
         { load the invoke pointer }
         hlcg.reference_reset_base(href,right.resultdef,right.location.register,0,ctempposinvalid,right.resultdef.alignment,[]);
         hlcg.reference_reset_base(href,right.resultdef,right.location.register,0,ctempposinvalid,right.resultdef.alignment,[]);
-        callprocdef:=cprocvardef.getreusableprocaddr(procdefinition);
+        callprocdef:=cprocvardef.getreusableprocaddr(procdefinition,pc_address_only);
         toreg:=hlcg.getaddressregister(current_asmdata.CurrAsmList,callprocdef);
         toreg:=hlcg.getaddressregister(current_asmdata.CurrAsmList,callprocdef);
         hlcg.g_load_field_reg_by_name(current_asmdata.CurrAsmList,literaldef,callprocdef,'INVOKE',href,toreg);
         hlcg.g_load_field_reg_by_name(current_asmdata.CurrAsmList,literaldef,callprocdef,'INVOKE',href,toreg);
      end;
      end;
@@ -851,7 +851,7 @@ implementation
            of far calls where the procvardef was defined does not matter,
            of far calls where the procvardef was defined does not matter,
            even though the procvardef constructor called by getcopyas looks at
            even though the procvardef constructor called by getcopyas looks at
            it) }
            it) }
-         callprocdef:=cprocvardef.getreusableprocaddr(procdefinition);
+         callprocdef:=cprocvardef.getreusableprocaddr(procdefinition,pc_address_only);
          reg:=hlcg.getaddressregister(current_asmdata.CurrAsmList,callprocdef);
          reg:=hlcg.getaddressregister(current_asmdata.CurrAsmList,callprocdef);
          { in case we have a method pointer on a big endian target in registers,
          { in case we have a method pointer on a big endian target in registers,
            the method address is stored in registerhi (it's the first field
            the method address is stored in registerhi (it's the first field

+ 2 - 2
compiler/ncgld.pas

@@ -646,8 +646,8 @@ implementation
                        begin
                        begin
                          { load address of the function }
                          { load address of the function }
                          reference_reset_symbol(href,current_asmdata.RefAsmSymbol(procdef.mangledname,AT_FUNCTION),0,procdef.address_type.alignment,[]);
                          reference_reset_symbol(href,current_asmdata.RefAsmSymbol(procdef.mangledname,AT_FUNCTION),0,procdef.address_type.alignment,[]);
-                         location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,cprocvardef.getreusableprocaddr(procdef));
-                         hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,procdef,cprocvardef.getreusableprocaddr(procdef),href,location.register);
+                         location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,cprocvardef.getreusableprocaddr(procdef,pc_address_only));
+                         hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,procdef,cprocvardef.getreusableprocaddr(procdef,pc_address_only),href,location.register);
                        end;
                        end;
 
 
                      { to get methodpointers stored correctly, code and self register must be swapped on
                      { to get methodpointers stored correctly, code and self register must be swapped on

+ 1 - 1
compiler/ncgrtti.pas

@@ -1385,7 +1385,7 @@ implementation
                     internalerror(201603021)
                     internalerror(201603021)
                   else
                   else
                     tcb.emit_tai(Tai_const.Createname(procdef.mangledname,AT_FUNCTION,0),
                     tcb.emit_tai(Tai_const.Createname(procdef.mangledname,AT_FUNCTION,0),
-                      cprocvardef.getreusableprocaddr(procdef));
+                      cprocvardef.getreusableprocaddr(procdef,pc_address_only));
                 end;
                 end;
             end;
             end;
 
 

+ 2 - 2
compiler/ncgvmt.pas

@@ -733,7 +733,7 @@ implementation
                 pd:=tprocdef(AImplIntf.procdefs[i]);
                 pd:=tprocdef(AImplIntf.procdefs[i]);
                 hs:=CreateWrapperName(_Class,AImplIntf,i,pd);
                 hs:=CreateWrapperName(_Class,AImplIntf,i,pd);
                 { create reference }
                 { create reference }
-                datatcb.emit_tai(Tai_const.Createname(hs,AT_FUNCTION,0),cprocvardef.getreusableprocaddr(pd));
+                datatcb.emit_tai(Tai_const.Createname(hs,AT_FUNCTION,0),cprocvardef.getreusableprocaddr(pd,pc_address_only));
               end;
               end;
            end
            end
         else
         else
@@ -992,7 +992,7 @@ implementation
                if current_module.moduleid<>vmtpd.owner.moduleid then
                if current_module.moduleid<>vmtpd.owner.moduleid then
                  current_module.addimportedsym(vmtpd.procsym);
                  current_module.addimportedsym(vmtpd.procsym);
              end;
              end;
-           tcb.emit_tai(Tai_const.Createname(procname,AT_FUNCTION,0),cprocvardef.getreusableprocaddr(vmtpd));
+           tcb.emit_tai(Tai_const.Createname(procname,AT_FUNCTION,0),cprocvardef.getreusableprocaddr(vmtpd,pc_address_only));
 {$ifdef vtentry}
 {$ifdef vtentry}
            hs:='VTENTRY'+'_'+_class.vmt_mangledname+'$$'+tostr(_class.vmtmethodoffset(i) div sizeof(pint));
            hs:='VTENTRY'+'_'+_class.vmt_mangledname+'$$'+tostr(_class.vmtmethodoffset(i) div sizeof(pint));
            current_asmdata.asmlists[al_globals].concat(tai_symbol.CreateName(hs,AT_DATA,0,voidpointerdef));
            current_asmdata.asmlists[al_globals].concat(tai_symbol.CreateName(hs,AT_DATA,0,voidpointerdef));

+ 1 - 1
compiler/ngtcon.pas

@@ -1456,7 +1456,7 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
         { get the address of the procedure, except if it's a C-block (then we
         { get the address of the procedure, except if it's a C-block (then we
           we will end up with a record that represents the C-block) }
           we will end up with a record that represents the C-block) }
         if not is_block(def) then
         if not is_block(def) then
-          procaddrdef:=cprocvardef.getreusableprocaddr(def)
+          procaddrdef:=cprocvardef.getreusableprocaddr(def,pc_address_only)
         else
         else
           procaddrdef:=def;
           procaddrdef:=def;
         ftcb.queue_init(procaddrdef);
         ftcb.queue_init(procaddrdef);

+ 1 - 1
compiler/nobj.pas

@@ -889,7 +889,7 @@ implementation
         { now add the methods }
         { now add the methods }
         for i:=0 to _class.vmtentries.count-1 do
         for i:=0 to _class.vmtentries.count-1 do
           vmtdef.add_field_by_def('',
           vmtdef.add_field_by_def('',
-            cprocvardef.getreusableprocaddr(pvmtentry(_class.vmtentries[i])^.procdef)
+            cprocvardef.getreusableprocaddr(pvmtentry(_class.vmtentries[i])^.procdef,pc_address_only)
           );
           );
         { the VMT ends with a nil pointer }
         { the VMT ends with a nil pointer }
         vmtdef.add_field_by_def('',voidcodepointertype);
         vmtdef.add_field_by_def('',voidcodepointertype);

+ 17 - 9
compiler/symdef.pas

@@ -640,15 +640,16 @@ interface
          pno_mangledname, pno_noparams);
          pno_mangledname, pno_noparams);
        tprocnameoptions = set of tprocnameoption;
        tprocnameoptions = set of tprocnameoption;
        tproccopytyp = (pc_normal,
        tproccopytyp = (pc_normal,
+                       { creates a procvardef describing only the code pointer
+                         of a method/netsted function/... }
+                       pc_address_only,
                        { everything except for hidden parameters }
                        { everything except for hidden parameters }
                        pc_normal_no_hidden,
                        pc_normal_no_hidden,
                        { always creates a top-level function, removes all
                        { always creates a top-level function, removes all
                          special parameters (self, vmt, parentfp, ...) }
                          special parameters (self, vmt, parentfp, ...) }
-                       pc_bareproc,
-                       { creates a procvardef describing only the code pointer
-                         of a method/netsted function/... }
-                       pc_address_only
+                       pc_bareproc
                        );
                        );
+       tcacheableproccopytyp = pc_normal..pc_address_only;
 
 
        tabstractprocdef = class(tstoreddef)
        tabstractprocdef = class(tstoreddef)
           { saves a definition to the return type }
           { saves a definition to the return type }
@@ -703,7 +704,7 @@ interface
        tprocvardef = class(tabstractprocdef)
        tprocvardef = class(tabstractprocdef)
           constructor create(level:byte);virtual;
           constructor create(level:byte);virtual;
           { returns a procvardef that represents the address of a proc(var)def }
           { returns a procvardef that represents the address of a proc(var)def }
-          class function getreusableprocaddr(def: tabstractprocdef): tprocvardef; virtual;
+          class function getreusableprocaddr(def: tabstractprocdef; copytyp: tcacheableproccopytyp): tprocvardef; virtual;
           { same as above, but in case the def must never be freed after the
           { same as above, but in case the def must never be freed after the
             current module has been compiled -- even if the def was not written
             current module has been compiled -- even if the def was not written
             to the ppu file (for defs in para locations, as we don't reset them
             to the ppu file (for defs in para locations, as we don't reset them
@@ -6958,14 +6959,21 @@ implementation
       end;
       end;
 
 
 
 
-    class function tprocvardef.getreusableprocaddr(def: tabstractprocdef): tprocvardef;
+    class function tprocvardef.getreusableprocaddr(def: tabstractprocdef; copytyp: tcacheableproccopytyp): tprocvardef;
       var
       var
         res: PHashSetItem;
         res: PHashSetItem;
         oldsymtablestack: tsymtablestack;
         oldsymtablestack: tsymtablestack;
+        key: packed record
+          def: tabstractprocdef;
+          copytyp: tcacheableproccopytyp;
+        end;
+
       begin
       begin
         if not assigned(current_module) then
         if not assigned(current_module) then
           internalerror(2011081301);
           internalerror(2011081301);
-        res:=current_module.procaddrdefs.FindOrAdd(@def,sizeof(def));
+        key.def:=def;
+        key.copytyp:=copytyp;
+        res:=current_module.procaddrdefs.FindOrAdd(@key,sizeof(key));
         if not assigned(res^.Data) then
         if not assigned(res^.Data) then
           begin
           begin
             { since these pointerdefs can be reused anywhere in the current
             { since these pointerdefs can be reused anywhere in the current
@@ -6977,7 +6985,7 @@ implementation
             { do not simply push/pop current_module.localsymtable, because
             { do not simply push/pop current_module.localsymtable, because
               that can have side-effects (e.g., it removes helpers) }
               that can have side-effects (e.g., it removes helpers) }
             symtablestack:=nil;
             symtablestack:=nil;
-            result:=tprocvardef(def.getcopyas(procvardef,pc_address_only,''));
+            result:=tprocvardef(def.getcopyas(procvardef,copytyp,''));
             setup_reusable_def(def,result,res,oldsymtablestack);
             setup_reusable_def(def,result,res,oldsymtablestack);
             { res^.Data may still be nil -> don't overwrite result }
             { res^.Data may still be nil -> don't overwrite result }
             exit;
             exit;
@@ -6988,7 +6996,7 @@ implementation
 
 
     class function tprocvardef.getreusableprocaddr_no_free(def: tabstractprocdef): tprocvardef;
     class function tprocvardef.getreusableprocaddr_no_free(def: tabstractprocdef): tprocvardef;
       begin
       begin
-        result:=getreusableprocaddr(def);
+        result:=getreusableprocaddr(def,pc_address_only);
         if not result.is_registered then
         if not result.is_registered then
           include(result.defoptions,df_not_registered_no_free);
           include(result.defoptions,df_not_registered_no_free);
       end;
       end;