Browse Source

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

Jonas Maebe 9 years ago
parent
commit
eaeb9d8351
4 changed files with 55 additions and 77 deletions
  1. 5 5
      compiler/hlcgobj.pas
  2. 44 12
      compiler/llvm/hlcgllvm.pas
  3. 1 55
      compiler/llvm/nllvmmem.pas
  4. 5 5
      compiler/ncgld.pas

+ 5 - 5
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;
 
 

+ 44 - 12
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;
-    begin
+      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;
 
 

+ 1 - 55
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;

+ 5 - 5
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);