* add support for creating non-address-only procvars to

cprocvar.getreusableprocaddr()

git-svn-id: trunk@44516 -
This commit is contained in:
Jonas Maebe 2020-04-02 21:21:36 +00:00
parent b033ccbddb
commit 4ba19f5418
11 changed files with 32 additions and 24 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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));

View File

@ -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);

View File

@ -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);

View File

@ -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;