* renamed thlcgobj.g_set_addr_nonbitpacked_record_field_ref() to

thlcgobj.g_set_addr_nonbitpacked_field_ref() and adjusted it so that
    it also works for objects/classes (if the incoming reference points
    to the start of the class contents)
   o factored out the related code from tllvmsubscriptnode

git-svn-id: trunk@32411 -
This commit is contained in:
Jonas Maebe 2015-11-21 12:37:01 +00:00
parent c8a5994e2e
commit eaeb9d8351
4 changed files with 54 additions and 76 deletions

View File

@ -539,9 +539,9 @@ unit hlcgobj;
reference if necessary }
procedure g_ptrtypecast_ref(list: TAsmList; fromdef, todef: tpointerdef; var ref: treference); virtual;
{ update a reference pointing to the start address of a record so it
refers to the indicated field }
procedure g_set_addr_nonbitpacked_record_field_ref(list: TAsmList; recdef: trecorddef; field: tfieldvarsym; var recref: treference); virtual;
{ update a reference pointing to the start address of a record/object/
class (contents) so it refers to the indicated field }
procedure g_set_addr_nonbitpacked_field_ref(list: TAsmList; recdef: tabstractrecorddef; field: tfieldvarsym; var recref: treference); virtual;
{ load a register/constant into a record field by name }
protected
procedure g_setup_load_field_by_name(list: TAsmList; recdef: trecorddef; const name: TIDString; const recref: treference; out fref: treference; out fielddef: tdef);
@ -3844,7 +3844,7 @@ implementation
{ nothing to do }
end;
procedure thlcgobj.g_set_addr_nonbitpacked_record_field_ref(list: TAsmList; recdef: trecorddef; field: tfieldvarsym; var recref: treference);
procedure thlcgobj.g_set_addr_nonbitpacked_field_ref(list: TAsmList; recdef: tabstractrecorddef; field: tfieldvarsym; var recref: treference);
begin
inc(recref.offset,field.fieldoffset);
recref.alignment:=newalignment(recref.alignment,field.fieldoffset);
@ -3863,7 +3863,7 @@ implementation
field:=tfieldvarsym(sym);
fref:=recref;
fielddef:=field.vardef;
g_set_addr_nonbitpacked_record_field_ref(list,recdef,field,fref);
g_set_addr_nonbitpacked_field_ref(list,recdef,field,fref);
end;

View File

@ -97,7 +97,7 @@ uses
procedure g_ptrtypecast_reg(list: TAsmList; fromdef, todef: tpointerdef; reg: tregister); override;
procedure g_ptrtypecast_ref(list: TAsmList; fromdef, todef: tpointerdef; var ref: treference); override;
procedure g_set_addr_nonbitpacked_record_field_ref(list: TAsmList; recdef: trecorddef; field: tfieldvarsym; var recref: treference); override;
procedure g_set_addr_nonbitpacked_field_ref(list: TAsmList; recdef: tabstractrecorddef; field: tfieldvarsym; var recref: treference); override;
procedure a_loadmm_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; reg: tregister; shuffle: pmmshuffle); override;
procedure a_loadmm_reg_ref(list: TAsmList; fromsize, tosize: tdef; reg: tregister; const ref: treference; shuffle: pmmshuffle); override;
@ -1224,22 +1224,54 @@ implementation
end;
procedure thlcgllvm.g_set_addr_nonbitpacked_record_field_ref(list: TAsmList; recdef: trecorddef; field: tfieldvarsym; var recref: treference);
procedure thlcgllvm.g_set_addr_nonbitpacked_field_ref(list: TAsmList; recdef: tabstractrecorddef; field: tfieldvarsym; var recref: treference);
var
llvmfielddef,
llvmfieldptrdef,
subscriptdef: tdef;
parentdef,
subscriptdef,
currentstructdef,
llvmfielddef: tdef;
newbase: tregister;
implicitpointer: boolean;
begin
implicitpointer:=is_implicit_pointer_object_type(recdef);
currentstructdef:=recdef;
{ in case the field is part of a parent of the current object,
index into the parents until we're at the parent containing the
field; if it's an implicit pointer type, these embedded parents
will be of the structure type of the class rather than of the
class time itself -> one indirection fewer }
while field.owner<>tabstractrecorddef(currentstructdef).symtable do
begin
{ only objectdefs have parents and hence the owner of the
fieldvarsym can be different from the current def's owner }
parentdef:=tobjectdef(currentstructdef).childof;
if implicitpointer then
newbase:=getaddressregister(list,parentdef)
else
newbase:=getaddressregister(list,cpointerdef.getreusable(parentdef));
recref:=make_simple_ref(list,recref,recdef);
if implicitpointer then
subscriptdef:=currentstructdef
else
subscriptdef:=cpointerdef.getreusable(currentstructdef);
{ recurse into the first field }
list.concat(taillvm.getelementptr_reg_size_ref_size_const(newbase,subscriptdef,recref,s32inttype,0,true));
reference_reset_base(recref,subscriptdef,newbase,field.offsetfromllvmfield,newalignment(recref.alignment,field.fieldoffset));
{ go to the parent }
currentstructdef:=parentdef;
end;
{ get the type of the corresponding field in the llvm shadow
definition }
llvmfielddef:=tabstractrecordsymtable(recdef.symtable).llvmst[field].def;
subscriptdef:=cpointerdef.getreusable(recdef);
llvmfielddef:=tabstractrecordsymtable(tabstractrecorddef(currentstructdef).symtable).llvmst[field].def;
if implicitpointer then
subscriptdef:=currentstructdef
else
subscriptdef:=cpointerdef.getreusable(currentstructdef);
{ load the address of that shadow field }
newbase:=hlcg.getaddressregister(list,cpointerdef.getreusable(llvmfielddef));
recref:=thlcgllvm(hlcg).make_simple_ref(list,recref,recdef);
newbase:=getaddressregister(list,cpointerdef.getreusable(llvmfielddef));
recref:=make_simple_ref(list,recref,recdef);
list.concat(taillvm.getelementptr_reg_size_ref_size_const(newbase,subscriptdef,recref,s32inttype,field.llvmfieldnr,true));
reference_reset_base(recref,cpointerdef.getreusable(field.vardef),newbase,field.offsetfromllvmfield,newalignment(recref.alignment,field.fieldoffset+field.offsetfromllvmfield));
reference_reset_base(recref,subscriptdef,newbase,field.offsetfromllvmfield,newalignment(recref.alignment,field.fieldoffset+field.offsetfromllvmfield));
{ in case of an 80 bits extended type, typecast from an array of 10
bytes (used because otherwise llvm will allocate the ABI-defined
size for extended, which is usually larger) into an extended }
@ -1250,7 +1282,7 @@ implementation
adjust the type of the pointer }
if (field.offsetfromllvmfield<>0) or
(llvmfielddef<>field.vardef) then
hlcg.g_ptrtypecast_ref(list,cpointerdef.getreusable(llvmfielddef),cpointerdef.getreusable(field.vardef),recref);
g_ptrtypecast_ref(list,cpointerdef.getreusable(llvmfielddef),cpointerdef.getreusable(field.vardef),recref);
end;

View File

@ -65,12 +65,7 @@ implementation
function tllvmsubscriptnode.handle_platform_subscript: boolean;
var
parentdef,
subscriptdef,
currentstructdef,
llvmfielddef: tdef;
newbase: tregister;
implicitpointer: boolean;
begin
if not(location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
internalerror(2014011905);
@ -85,56 +80,7 @@ implementation
end
else
begin
implicitpointer:=is_implicit_pointer_object_type(left.resultdef);
currentstructdef:=left.resultdef;
{ in case the field is part of a parent of the current object,
index into the parents until we're at the parent containing the
field; if it's an implicit pointer type, these embedded parents
will be of the structure type of the class rather than of the
class time itself -> one indirection fewer }
while vs.owner<>tabstractrecorddef(currentstructdef).symtable do
begin
{ only objectdefs have parents and hence the owner of the
fieldvarsym can be different from the current def's owner }
parentdef:=tobjectdef(currentstructdef).childof;
if implicitpointer then
newbase:=hlcg.getaddressregister(current_asmdata.CurrAsmList,parentdef)
else
newbase:=hlcg.getaddressregister(current_asmdata.CurrAsmList,cpointerdef.getreusable(parentdef));
location.reference:=thlcgllvm(hlcg).make_simple_ref(current_asmdata.CurrAsmList,location.reference,left.resultdef);
if implicitpointer then
subscriptdef:=currentstructdef
else
subscriptdef:=cpointerdef.getreusable(currentstructdef);
{ recurse into the first field }
current_asmdata.CurrAsmList.concat(taillvm.getelementptr_reg_size_ref_size_const(newbase,subscriptdef,location.reference,s32inttype,0,true));
reference_reset_base(location.reference,newbase,vs.offsetfromllvmfield,newalignment(location.reference.alignment,vs.fieldoffset));
{ go to the parent }
currentstructdef:=parentdef;
end;
{ get the type of the corresponding field in the llvm shadow
definition }
llvmfielddef:=tabstractrecordsymtable(tabstractrecorddef(currentstructdef).symtable).llvmst[vs].def;
if implicitpointer then
subscriptdef:=currentstructdef
else
subscriptdef:=cpointerdef.getreusable(currentstructdef);
{ load the address of that shadow field }
newbase:=hlcg.getaddressregister(current_asmdata.CurrAsmList,cpointerdef.getreusable(llvmfielddef));
location.reference:=thlcgllvm(hlcg).make_simple_ref(current_asmdata.CurrAsmList,location.reference,left.resultdef);
current_asmdata.CurrAsmList.concat(taillvm.getelementptr_reg_size_ref_size_const(newbase,subscriptdef,location.reference,s32inttype,vs.llvmfieldnr,true));
reference_reset_base(location.reference,newbase,vs.offsetfromllvmfield,newalignment(location.reference.alignment,vs.fieldoffset+vs.offsetfromllvmfield));
{ in case of an 80 bits extended type, typecast from an array of 10
bytes (used because otherwise llvm will allocate the ABI-defined
size for extended, which is usually larger) into an extended }
if (llvmfielddef.typ=floatdef) and
(tfloatdef(llvmfielddef).floattype=s80real) then
hlcg.g_ptrtypecast_ref(current_asmdata.CurrAsmList,cpointerdef.getreusable(carraydef.getreusable(u8inttype,10)),cpointerdef.getreusable(s80floattype),location.reference);
{ if it doesn't match the requested field exactly (variant record),
adjust the type of the pointer }
if (vs.offsetfromllvmfield<>0) or
(llvmfielddef<>resultdef) then
hlcg.g_ptrtypecast_ref(current_asmdata.CurrAsmList,cpointerdef.getreusable(llvmfielddef),cpointerdef.getreusable(resultdef),location.reference);
hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,tabstractrecorddef(left.resultdef),vs,location.reference);
location.size:=def_cgsize(resultdef);
result:=true;
end;

View File

@ -309,7 +309,7 @@ implementation
else
reference_reset_symbol(tvref,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0,sizeof(pint));
href:=tvref;
hlcg.g_set_addr_nonbitpacked_record_field_ref(current_asmdata.CurrAsmList,
hlcg.g_set_addr_nonbitpacked_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);
@ -334,7 +334,7 @@ implementation
sizeof(pint) - Threadvar value in single threading }
hlcg.a_label(current_asmdata.CurrAsmList,norelocatelab);
href:=tvref;
hlcg.g_set_addr_nonbitpacked_record_field_ref(current_asmdata.CurrAsmList,
hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,
tv_rec,
tfieldvarsym(tv_non_mt_data_field),href);
{ load in the same "hregister" as above, so after this sequence
@ -381,7 +381,7 @@ implementation
location_reset_ref(location,LOC_CREFERENCE,def_cgsize(cansistringtype),cansistringtype.size);
location.reference.symbol:=current_asmdata.RefAsmSymbol(make_mangledname('RESSTR',symtableentry.owner,symtableentry.name),AT_DATA);
vd:=search_system_type('TRESOURCESTRINGRECORD').typedef;
hlcg.g_set_addr_nonbitpacked_record_field_ref(
hlcg.g_set_addr_nonbitpacked_field_ref(
current_asmdata.CurrAsmList,
trecorddef(vd),
tfieldvarsym(search_struct_member(trecorddef(vd),'CURRENTVALUE')),
@ -1325,7 +1325,7 @@ implementation
internalerror(2015102901);
{ write changing field update href to the next element }
fref:=href;
hlcg.g_set_addr_nonbitpacked_record_field_ref(current_asmdata.CurrAsmList,trecorddef(eledef),varfield,fref);
hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,trecorddef(eledef),varfield,fref);
if vaddr then
begin
hlcg.location_force_mem(current_asmdata.CurrAsmList,hp.left.location,lt);
@ -1337,7 +1337,7 @@ implementation
hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,hp.left.resultdef,varfield.vardef,hp.left.location,fref);
{ update href to the vtype field and write it }
fref:=href;
hlcg.g_set_addr_nonbitpacked_record_field_ref(current_asmdata.CurrAsmList,trecorddef(eledef),varvtypefield,fref);
hlcg.g_set_addr_nonbitpacked_field_ref(current_asmdata.CurrAsmList,trecorddef(eledef),varvtypefield,fref);
hlcg.a_load_const_ref(current_asmdata.CurrAsmList,varvtypefield.vardef,vtype,fref);
{ goto next array element }
advancearrayoffset(href,elesize);