diff --git a/compiler/hlcgobj.pas b/compiler/hlcgobj.pas index d91bdc1741..c02cef3dde 100644 --- a/compiler/hlcgobj.pas +++ b/compiler/hlcgobj.pas @@ -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; diff --git a/compiler/llvm/hlcgllvm.pas b/compiler/llvm/hlcgllvm.pas index 6c59ef6280..53948ab06b 100644 --- a/compiler/llvm/hlcgllvm.pas +++ b/compiler/llvm/hlcgllvm.pas @@ -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; diff --git a/compiler/llvm/nllvmmem.pas b/compiler/llvm/nllvmmem.pas index ae346cb349..9dfc4d9599 100644 --- a/compiler/llvm/nllvmmem.pas +++ b/compiler/llvm/nllvmmem.pas @@ -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; diff --git a/compiler/ncgld.pas b/compiler/ncgld.pas index 2b907a826b..654b8de272 100644 --- a/compiler/ncgld.pas +++ b/compiler/ncgld.pas @@ -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);