mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-10-31 12:11:34 +01:00 
			
		
		
		
	* add support for creating non-address-only procvars to
cprocvar.getreusableprocaddr() git-svn-id: trunk@44516 -
This commit is contained in:
		
							parent
							
								
									b033ccbddb
								
							
						
					
					
						commit
						4ba19f5418
					
				| @ -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; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -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; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -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; | ||||||
|  | |||||||
| @ -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, | ||||||
|  | |||||||
| @ -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 | ||||||
|  | |||||||
| @ -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)); |                          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),href,location.register); |                          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 | ||||||
|  | |||||||
| @ -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; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -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)); | ||||||
|  | |||||||
| @ -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); | ||||||
|  | |||||||
| @ -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); | ||||||
|  | |||||||
| @ -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, |                        pc_bareproc | ||||||
|                        { creates a procvardef describing only the code pointer |  | ||||||
|                          of a method/netsted function/... } |  | ||||||
|                        pc_address_only |  | ||||||
|                        ); |                        ); | ||||||
|  |        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; | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Jonas Maebe
						Jonas Maebe