diff --git a/compiler/aasmcnst.pas b/compiler/aasmcnst.pas index e291f0fc44..112cdbbea8 100644 --- a/compiler/aasmcnst.pas +++ b/compiler/aasmcnst.pas @@ -1274,7 +1274,7 @@ implementation procedure ttai_typedconstbuilder.emit_procdef_const(pd: tprocdef); begin - emit_tai(Tai_const.Createname(pd.mangledname,AT_FUNCTION,0),getprocaddressprocvar(pd)); + emit_tai(Tai_const.Createname(pd.mangledname,AT_FUNCTION,0),cprocvardef.getreusableprocaddr(pd)); end; diff --git a/compiler/llvm/hlcgllvm.pas b/compiler/llvm/hlcgllvm.pas index 2f39bf99d9..89cfc699d0 100644 --- a/compiler/llvm/hlcgllvm.pas +++ b/compiler/llvm/hlcgllvm.pas @@ -319,7 +319,7 @@ implementation begin if (pd.typ=procdef) or not pd.is_addressonly then - result:=getprocaddressprocvar(pd) + result:=cprocvardef.getreusableprocaddr(pd) else result:=pd end; @@ -420,7 +420,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(getprocaddressprocvar(pd)); + pd:=tprocvardef(cprocvardef.getreusableprocaddr(pd)); { if the function returns a function pointer type or is varargs, we must specify the full function signature, otherwise we can only specify the return type } diff --git a/compiler/llvm/nllvmtcon.pas b/compiler/llvm/nllvmtcon.pas index 874be7f9c8..fb7d6e1c22 100644 --- a/compiler/llvm/nllvmtcon.pas +++ b/compiler/llvm/nllvmtcon.pas @@ -236,7 +236,7 @@ implementation procedure tllvmtai_typedconstbuilder.emit_tai_procvar2procdef(p: tai; pvdef: tprocvardef); begin if not pvdef.is_addressonly then - pvdef:=getprocaddressprocvar(pvdef); + pvdef:=cprocvardef.getreusableprocaddr(pvdef); emit_tai(p,pvdef); end; @@ -444,7 +444,7 @@ implementation the procdef } if (fromdef.typ=procdef) and (todef.typ<>procdef) then - fromdef:=getprocaddressprocvar(tprocdef(fromdef)); + fromdef:=cprocvardef.getreusableprocaddr(tprocdef(fromdef)); op:=llvmconvop(fromdef,todef); case op of la_ptrtoint_to_x, diff --git a/compiler/ncgcal.pas b/compiler/ncgcal.pas index 637cbccbb8..e53237cba5 100644 --- a/compiler/ncgcal.pas +++ b/compiler/ncgcal.pas @@ -820,7 +820,7 @@ implementation of far calls where the procvardef was defined does not matter, even though the procvardef constructor called by getcopyas looks at it) } - codeprocdef:=getprocaddressprocvar(procdefinition); + codeprocdef:=cprocvardef.getreusableprocaddr(procdefinition); result:=hlcg.getaddressregister(current_asmdata.CurrAsmList,codeprocdef); { 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 diff --git a/compiler/ncgvmt.pas b/compiler/ncgvmt.pas index d7f552f730..28e75848ea 100644 --- a/compiler/ncgvmt.pas +++ b/compiler/ncgvmt.pas @@ -722,7 +722,7 @@ implementation hs:=make_mangledname('WRPR',_class.owner,_class.objname^+'_$_'+AImplIntf.IntfDef.objname^+'_$_'+ tostr(i)+'_$_'+pd.mangledname); { create reference } - datatcb.emit_tai(Tai_const.Createname(hs,AT_FUNCTION,0),getprocaddressprocvar(pd)); + datatcb.emit_tai(Tai_const.Createname(hs,AT_FUNCTION,0),cprocvardef.getreusableprocaddr(pd)); end; end else @@ -1015,7 +1015,7 @@ implementation procname:='FPC_EMPTYMETHOD' else if not wpoinfomanager.optimized_name_for_vmt(_class,vmtpd,procname) then procname:=vmtpd.mangledname; - tcb.emit_tai(Tai_const.Createname(procname,AT_FUNCTION,0),getprocaddressprocvar(vmtpd)); + tcb.emit_tai(Tai_const.Createname(procname,AT_FUNCTION,0),cprocvardef.getreusableprocaddr(vmtpd)); {$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)); diff --git a/compiler/nobj.pas b/compiler/nobj.pas index c101578be1..5a8c9fe836 100644 --- a/compiler/nobj.pas +++ b/compiler/nobj.pas @@ -864,7 +864,7 @@ implementation { now add the methods } for i:=0 to _class.vmtentries.count-1 do vmtdef.add_field_by_def( - getprocaddressprocvar(pvmtentry(_class.vmtentries[i])^.procdef) + cprocvardef.getreusableprocaddr(pvmtentry(_class.vmtentries[i])^.procdef) ); { the VMT ends with a nil pointer } vmtdef.add_field_by_def(voidcodepointertype); diff --git a/compiler/symdef.pas b/compiler/symdef.pas index b32091c2fe..2846a53293 100644 --- a/compiler/symdef.pas +++ b/compiler/symdef.pas @@ -608,6 +608,8 @@ 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; constructor ppuload(ppufile:tcompilerppufile); function getcopy : tstoreddef;override; { do not override this routine in platform-specific subclasses, @@ -1126,9 +1128,6 @@ interface function use_vectorfpu(def : tdef) : boolean; - { returns a procvardef that represents the address of a procdef } - function getprocaddressprocvar(def: tabstractprocdef): tprocvardef; - function getansistringcodepage:tstringencoding; inline; function getansistringdef:tstringdef; function getparaencoding(def:tdef):tstringencoding; inline; @@ -5900,6 +5899,33 @@ implementation end; + class function tprocvardef.getreusableprocaddr(def: tabstractprocdef): tprocvardef; + var + res: PHashSetItem; + oldsymtablestack: tsymtablestack; + begin + if not assigned(current_module) then + internalerror(2011081301); + res:=current_module.procaddrdefs.FindOrAdd(@def,sizeof(def)); + if not assigned(res^.Data) then + begin + { since these pointerdefs can be reused anywhere in the current + unit, add them to the global/staticsymtable } + oldsymtablestack:=symtablestack; + { do not simply push/pop current_module.localsymtable, because + that can have side-effects (e.g., it removes helpers) } + symtablestack:=nil; + res^.Data:=def.getcopyas(procvardef,pc_address_only); + if assigned(current_module.localsymtable) then + current_module.localsymtable.insertdef(tdef(res^.Data)) + else + current_module.globalsymtable.insertdef(tdef(res^.Data)); + symtablestack:=oldsymtablestack; + end; + result:=tprocvardef(res^.Data); + end; + + constructor tprocvardef.ppuload(ppufile:tcompilerppufile); begin inherited ppuload(procvardef,ppufile); @@ -7661,30 +7687,4 @@ implementation end; - function getprocaddressprocvar(def: tabstractprocdef): tprocvardef; - var - res: PHashSetItem; - oldsymtablestack: tsymtablestack; - begin - if not assigned(current_module) then - internalerror(2011081301); - res:=current_module.procaddrdefs.FindOrAdd(@def,sizeof(def)); - if not assigned(res^.Data) then - begin - { since these pointerdefs can be reused anywhere in the current - unit, add them to the global/staticsymtable } - oldsymtablestack:=symtablestack; - { do not simply push/pop current_module.localsymtable, because - that can have side-effects (e.g., it removes helpers) } - symtablestack:=nil; - res^.Data:=def.getcopyas(procvardef,pc_address_only); - if assigned(current_module.localsymtable) then - current_module.localsymtable.insertdef(tdef(res^.Data)) - else - current_module.globalsymtable.insertdef(tdef(res^.Data)); - symtablestack:=oldsymtablestack; - end; - result:=tprocvardef(res^.Data); - end; - end.