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

View File

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

View File

@ -117,7 +117,7 @@ procedure tllvmloadnode.pass_generate_code;
selfdef:=cpointerdef.getreusable(left.resultdef);
mpref:=href;
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);
location_reset_ref(location,LOC_REFERENCE,location.size,href.alignment,href.volatility);
location.reference:=href;

View File

@ -408,7 +408,7 @@ implementation
procedure tllvmtai_typedconstbuilder.emit_tai_procvar2procdef(p: tai; pvdef: tprocvardef);
begin
if not pvdef.is_addressonly then
pvdef:=cprocvardef.getreusableprocaddr(pvdef);
pvdef:=cprocvardef.getreusableprocaddr(pvdef,pc_address_only);
emit_tai(p,pvdef);
end;
@ -731,7 +731,7 @@ implementation
the procdef }
if (fromdef.typ=procdef) and
(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
to the pointer-component of the complex procvardef (not always, because
e.g. a tmethod to complex procvar initialises the entire complex
@ -739,7 +739,7 @@ implementation
if (todef.typ=procvardef) and
not tprocvardef(todef).is_addressonly and
(fromdef.size<todef.size) then
todef:=cprocvardef.getreusableprocaddr(tprocvardef(todef));
todef:=cprocvardef.getreusableprocaddr(tprocvardef(todef),pc_address_only);
op:=llvmconvop(fromdef,todef,false);
case op of
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);
{ load the invoke pointer }
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);
hlcg.g_load_field_reg_by_name(current_asmdata.CurrAsmList,literaldef,callprocdef,'INVOKE',href,toreg);
end;
@ -851,7 +851,7 @@ implementation
of far calls where the procvardef was defined does not matter,
even though the procvardef constructor called by getcopyas looks at
it) }
callprocdef:=cprocvardef.getreusableprocaddr(procdefinition);
callprocdef:=cprocvardef.getreusableprocaddr(procdefinition,pc_address_only);
reg:=hlcg.getaddressregister(current_asmdata.CurrAsmList,callprocdef);
{ 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

View File

@ -646,8 +646,8 @@ implementation
begin
{ load address of the function }
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;
{ to get methodpointers stored correctly, code and self register must be swapped on

View File

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

View File

@ -733,7 +733,7 @@ implementation
pd:=tprocdef(AImplIntf.procdefs[i]);
hs:=CreateWrapperName(_Class,AImplIntf,i,pd);
{ 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
else
@ -992,7 +992,7 @@ implementation
if current_module.moduleid<>vmtpd.owner.moduleid then
current_module.addimportedsym(vmtpd.procsym);
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}
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));

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
we will end up with a record that represents the C-block) }
if not is_block(def) then
procaddrdef:=cprocvardef.getreusableprocaddr(def)
procaddrdef:=cprocvardef.getreusableprocaddr(def,pc_address_only)
else
procaddrdef:=def;
ftcb.queue_init(procaddrdef);

View File

@ -889,7 +889,7 @@ implementation
{ now add the methods }
for i:=0 to _class.vmtentries.count-1 do
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 }
vmtdef.add_field_by_def('',voidcodepointertype);

View File

@ -640,15 +640,16 @@ interface
pno_mangledname, pno_noparams);
tprocnameoptions = set of tprocnameoption;
tproccopytyp = (pc_normal,
{ creates a procvardef describing only the code pointer
of a method/netsted function/... }
pc_address_only,
{ everything except for hidden parameters }
pc_normal_no_hidden,
{ always creates a top-level function, removes all
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)
{ saves a definition to the return type }
@ -703,7 +704,7 @@ interface
tprocvardef = class(tabstractprocdef)
constructor create(level:byte);virtual;
{ 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
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
@ -6958,14 +6959,21 @@ implementation
end;
class function tprocvardef.getreusableprocaddr(def: tabstractprocdef): tprocvardef;
class function tprocvardef.getreusableprocaddr(def: tabstractprocdef; copytyp: tcacheableproccopytyp): tprocvardef;
var
res: PHashSetItem;
oldsymtablestack: tsymtablestack;
key: packed record
def: tabstractprocdef;
copytyp: tcacheableproccopytyp;
end;
begin
if not assigned(current_module) then
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
begin
{ since these pointerdefs can be reused anywhere in the current
@ -6977,7 +6985,7 @@ implementation
{ do not simply push/pop current_module.localsymtable, because
that can have side-effects (e.g., it removes helpers) }
symtablestack:=nil;
result:=tprocvardef(def.getcopyas(procvardef,pc_address_only,''));
result:=tprocvardef(def.getcopyas(procvardef,copytyp,''));
setup_reusable_def(def,result,res,oldsymtablestack);
{ res^.Data may still be nil -> don't overwrite result }
exit;
@ -6988,7 +6996,7 @@ implementation
class function tprocvardef.getreusableprocaddr_no_free(def: tabstractprocdef): tprocvardef;
begin
result:=getreusableprocaddr(def);
result:=getreusableprocaddr(def,pc_address_only);
if not result.is_registered then
include(result.defoptions,df_not_registered_no_free);
end;