* converted threadvar loading to high level code generator and updated/added

comments

git-svn-id: trunk@31644 -
This commit is contained in:
Jonas Maebe 2015-09-12 23:33:10 +00:00
parent 83ae160057
commit 19882aea7e

View File

@ -255,12 +255,19 @@ implementation
procedure tcgloadnode.generate_threadvar_access(gvs: tstaticvarsym); procedure tcgloadnode.generate_threadvar_access(gvs: tstaticvarsym);
var var
respara,
paraloc1 : tcgpara; paraloc1 : tcgpara;
fieldptrdef,
pvd : tdef; pvd : tdef;
endrelocatelab, endrelocatelab,
norelocatelab : tasmlabel; norelocatelab : tasmlabel;
tvref,
href : treference; href : treference;
hregister : tregister; hregister : tregister;
tv_rec : trecorddef;
tv_index_field,
tv_non_mt_data_field: tsym;
tmpresloc: tlocation;
begin begin
if (tf_section_threadvars in target_info.flags) then if (tf_section_threadvars in target_info.flags) then
begin begin
@ -279,51 +286,63 @@ implementation
a relocate function is available. When the function a relocate function is available. When the function
is available it is called to retrieve the address. is available it is called to retrieve the address.
Otherwise the address is loaded with the symbol Otherwise the address is loaded with the symbol
The code needs to be in the order to first handle the
call and then the address load to be sure that the
register that is used for returning is the same (PFV)
} }
tv_rec:=get_threadvar_record(resultdef,tv_index_field,tv_non_mt_data_field);
fieldptrdef:=cpointerdef.getreusable(resultdef);
current_asmdata.getjumplabel(norelocatelab); current_asmdata.getjumplabel(norelocatelab);
current_asmdata.getjumplabel(endrelocatelab); current_asmdata.getjumplabel(endrelocatelab);
{ make sure hregister can't allocate the register necessary for the parameter } { make sure hregister can't allocate the register necessary for the parameter }
pvd:=search_system_type('TRELOCATETHREADVARHANDLER').typedef; pvd:=search_system_type('TRELOCATETHREADVARHANDLER').typedef;
if pvd.typ<>procvardef then if pvd.typ<>procvardef then
internalerror(2012120901); internalerror(2012120901);
{ FPC_THREADVAR_RELOCATE is nil? }
paraloc1.init; paraloc1.init;
paramanager.getintparaloc(current_asmdata.CurrAsmList,tprocvardef(pvd),1,paraloc1); paramanager.getintparaloc(current_asmdata.CurrAsmList,tprocvardef(pvd),1,paraloc1);
hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,pvd); hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,pvd);
reference_reset_symbol(href,current_asmdata.RefAsmSymbol('FPC_THREADVAR_RELOCATE'),0,pvd.size); reference_reset_symbol(href,current_asmdata.RefAsmSymbol('FPC_THREADVAR_RELOCATE'),0,pvd.size);
hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,pvd,pvd,href,hregister); hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,pvd,pvd,href,hregister);
hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,pvd,OC_EQ,0,hregister,norelocatelab); hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,pvd,OC_EQ,0,hregister,norelocatelab);
{ don't save the allocated register else the result will be destroyed later } { no, call it with the index of the threadvar as parameter }
if not(vo_is_weak_external in gvs.varoptions) then if not(vo_is_weak_external in gvs.varoptions) then
reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname),0,sizeof(pint)) reference_reset_symbol(tvref,current_asmdata.RefAsmSymbol(gvs.mangledname),0,sizeof(pint))
else else
reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0,sizeof(pint)); reference_reset_symbol(tvref,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0,sizeof(pint));
cg.a_load_ref_cgpara(current_asmdata.CurrAsmList,OS_32,href,paraloc1); href:=tvref;
hlcg.g_set_addr_nonbitpacked_record_field_ref(current_asmdata.CurrAsmList,
tv_rec,
tfieldvarsym(tv_index_field),href);
hlcg.a_load_ref_cgpara(current_asmdata.CurrAsmList,tfieldvarsym(tv_index_field).vardef,href,paraloc1);
paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1); paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
paraloc1.done;
cg.allocallcpuregisters(current_asmdata.CurrAsmList); cg.allocallcpuregisters(current_asmdata.CurrAsmList);
cg.a_call_reg(current_asmdata.CurrAsmList,hregister); { result is the address of the threadvar }
respara:=hlcg.a_call_reg(current_asmdata.CurrAsmList,tprocvardef(pvd),hregister,[@paraloc1]);
paraloc1.done;
cg.deallocallcpuregisters(current_asmdata.CurrAsmList); cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
cg.getcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG); { load the address of the result in hregister }
hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,voidpointertype); hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,fieldptrdef);
cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_ADDR,NR_FUNCTION_RESULT_REG,hregister); location_reset(tmpresloc,LOC_REGISTER,OS_ADDR);
cg.a_jmp_always(current_asmdata.CurrAsmList,endrelocatelab); tmpresloc.register:=hregister;
cg.a_label(current_asmdata.CurrAsmList,norelocatelab); hlcg.gen_load_cgpara_loc(current_asmdata.CurrAsmList,fieldptrdef,respara,tmpresloc,true);
respara.resetiftemp;
hlcg.a_jmp_always(current_asmdata.CurrAsmList,endrelocatelab);
{ no relocation needed, load the address of the variable only, the { no relocation needed, load the address of the variable only, the
layout of a threadvar is (4 bytes pointer): layout of a threadvar is:
0 - Threadvar index 0 - Threadvar index
sizeof(pint) - Threadvar value in single threading } sizeof(pint) - Threadvar value in single threading }
if not(vo_is_weak_external in gvs.varoptions) then hlcg.a_label(current_asmdata.CurrAsmList,norelocatelab);
reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname),sizeof(pint),sizeof(pint)) href:=tvref;
else hlcg.g_set_addr_nonbitpacked_record_field_ref(current_asmdata.CurrAsmList,
reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),sizeof(pint),sizeof(pint)); tv_rec,
hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,resultdef,voidpointertype,href,hregister); tfieldvarsym(tv_non_mt_data_field),href);
cg.a_label(current_asmdata.CurrAsmList,endrelocatelab); { load in the same "hregister" as above, so after this sequence
hlcg.reference_reset_base(location.reference,voidpointertype,hregister,0,location.reference.alignment); the address of the threadvar is always in hregister }
hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,resultdef,fieldptrdef,href,hregister);
hlcg.a_label(current_asmdata.CurrAsmList,endrelocatelab);
hlcg.reference_reset_base(location.reference,fieldptrdef,hregister,0,location.reference.alignment);
end; end;
end; end;