Browse Source

+ support to store ttempcreate/ref/deletenodes in registers
* put temps for withnodes and some newnodes in registers
Note: this currently only works because calling ungetregister()
multiple times for the same register doesn't matter. We need again
a way to specify that a register is currently a regvar and as such
should not be freed when you call ungetregister() on it.

Jonas Maebe 21 years ago
parent
commit
694eee6cae
5 changed files with 147 additions and 25 deletions
  1. 31 4
      compiler/nbas.pas
  2. 86 15
      compiler/ncgbas.pas
  3. 10 2
      compiler/ninl.pas
  4. 10 2
      compiler/pinline.pas
  5. 10 2
      compiler/pstatmnt.pas

+ 31 - 4
compiler/nbas.pas

@@ -90,6 +90,12 @@ interface
 
 
        ttempcreatenode = class;
        ttempcreatenode = class;
 
 
+       ttemplocation = record
+         case loc: tcgloc of
+           LOC_REFERENCE: (ref: treference);
+           LOC_REGISTER:  (reg: tregister);
+       end;
+         
        { to allow access to the location by temp references even after the temp has }
        { to allow access to the location by temp references even after the temp has }
        { already been disposed and to make sure the coherency between temps and     }
        { already been disposed and to make sure the coherency between temps and     }
        { temp references is kept after a getcopy                                    }
        { temp references is kept after a getcopy                                    }
@@ -98,12 +104,12 @@ interface
          { set to the copy of a tempcreate pnode (if it gets copied) so that the }
          { set to the copy of a tempcreate pnode (if it gets copied) so that the }
          { refs and deletenode can hook to this copy once they get copied too    }
          { refs and deletenode can hook to this copy once they get copied too    }
          hookoncopy                 : ptempinfo;
          hookoncopy                 : ptempinfo;
-         ref                        : treference;
          restype                    : ttype;
          restype                    : ttype;
          temptype                   : ttemptype;
          temptype                   : ttemptype;
+         owner                      : ttempcreatenode;
          valid                      : boolean;
          valid                      : boolean;
          nextref_set_hookoncopy_nil : boolean;
          nextref_set_hookoncopy_nil : boolean;
-         owner                      : ttempcreatenode;
+         loc                        : ttemplocation;
        end;
        end;
 
 
        { a node which will create a (non)persistent temp of a given type with a given  }
        { a node which will create a (non)persistent temp of a given type with a given  }
@@ -111,14 +117,16 @@ interface
        ttempcreatenode = class(tnode)
        ttempcreatenode = class(tnode)
           size: longint;
           size: longint;
           tempinfo: ptempinfo;
           tempinfo: ptempinfo;
+          may_be_in_reg: boolean;
           { * persistent temps are used in manually written code where the temp }
           { * persistent temps are used in manually written code where the temp }
           { be usable among different statements and where you can manually say }
           { be usable among different statements and where you can manually say }
           { when the temp has to be freed (using a ttempdeletenode)             }
           { when the temp has to be freed (using a ttempdeletenode)             }
           { * non-persistent temps are mostly used in typeconversion helpers,   }
           { * non-persistent temps are mostly used in typeconversion helpers,   }
           { where the node that receives the temp becomes responsible for       }
           { where the node that receives the temp becomes responsible for       }
-          { freeing it. In this last case, you should use only one reference    }
+          { freeing it. In this last case, you must use only one reference      }
           { to it and *not* generate a ttempdeletenode                          }
           { to it and *not* generate a ttempdeletenode                          }
           constructor create(const _restype: ttype; _size: longint; _temptype: ttemptype); virtual;
           constructor create(const _restype: ttype; _size: longint; _temptype: ttemptype); virtual;
+          constructor create_reg(const _restype: ttype; _size: longint; _temptype: ttemptype); virtual;
           constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
           constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
           procedure ppuwrite(ppufile:tcompilerppufile);override;
           procedure ppuwrite(ppufile:tcompilerppufile);override;
           procedure buildderefimpl;override;
           procedure buildderefimpl;override;
@@ -660,6 +668,12 @@ implementation
                           TEMPCREATENODE
                           TEMPCREATENODE
 *****************************************************************************}
 *****************************************************************************}
 
 
+    constructor ttempcreatenode.create_reg(const _restype: ttype; _size: longint; _temptype: ttemptype);
+      begin
+        create(_restype,_size,_temptype);
+        may_be_in_reg:=true;
+      end;
+
     constructor ttempcreatenode.create(const _restype: ttype; _size: longint; _temptype: ttemptype);
     constructor ttempcreatenode.create(const _restype: ttype; _size: longint; _temptype: ttemptype);
       begin
       begin
         inherited create(tempcreaten);
         inherited create(tempcreaten);
@@ -669,6 +683,7 @@ implementation
         tempinfo^.restype := _restype;
         tempinfo^.restype := _restype;
         tempinfo^.temptype := _temptype;
         tempinfo^.temptype := _temptype;
         tempinfo^.owner:=self;
         tempinfo^.owner:=self;
+        may_be_in_reg:=false;
       end;
       end;
 
 
     function ttempcreatenode.getcopy: tnode;
     function ttempcreatenode.getcopy: tnode;
@@ -677,6 +692,7 @@ implementation
       begin
       begin
         n := ttempcreatenode(inherited getcopy);
         n := ttempcreatenode(inherited getcopy);
         n.size := size;
         n.size := size;
+        n.may_be_in_reg := may_be_in_reg;
 
 
         new(n.tempinfo);
         new(n.tempinfo);
         fillchar(n.tempinfo^,sizeof(n.tempinfo^),0);
         fillchar(n.tempinfo^,sizeof(n.tempinfo^),0);
@@ -704,6 +720,7 @@ implementation
         inherited ppuload(t,ppufile);
         inherited ppuload(t,ppufile);
 
 
         size:=ppufile.getlongint;
         size:=ppufile.getlongint;
+        may_be_in_reg:=boolean(ppufile.getbyte);
         new(tempinfo);
         new(tempinfo);
         fillchar(tempinfo^,sizeof(tempinfo^),0);
         fillchar(tempinfo^,sizeof(tempinfo^),0);
         ppufile.gettype(tempinfo^.restype);
         ppufile.gettype(tempinfo^.restype);
@@ -716,6 +733,7 @@ implementation
       begin
       begin
         inherited ppuwrite(ppufile);
         inherited ppuwrite(ppufile);
         ppufile.putlongint(size);
         ppufile.putlongint(size);
+        ppufile.putbyte(byte(may_be_in_reg));
         ppufile.puttype(tempinfo^.restype);
         ppufile.puttype(tempinfo^.restype);
         ppufile.putbyte(byte(tempinfo^.temptype));
         ppufile.putbyte(byte(tempinfo^.temptype));
       end;
       end;
@@ -751,6 +769,7 @@ implementation
         result :=
         result :=
           inherited docompare(p) and
           inherited docompare(p) and
           (ttempcreatenode(p).size = size) and
           (ttempcreatenode(p).size = size) and
+          (ttempcreatenode(p).may_be_in_reg = may_be_in_reg) and
           equal_defs(ttempcreatenode(p).tempinfo^.restype.def,tempinfo^.restype.def);
           equal_defs(ttempcreatenode(p).tempinfo^.restype.def,tempinfo^.restype.def);
       end;
       end;
 
 
@@ -983,7 +1002,15 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.75  2004-01-26 16:12:27  daniel
+  Revision 1.76  2004-02-03 16:46:51  jonas
+    + support to store ttempcreate/ref/deletenodes in registers
+    * put temps for withnodes and some newnodes in registers
+     Note: this currently only works because calling ungetregister()
+       multiple times for the same register doesn't matter. We need again
+       a way to specify that a register is currently a regvar and as such
+       should not be freed when you call ungetregister() on it.
+
+  Revision 1.75  2004/01/26 16:12:27  daniel
     * reginfo now also only allocated during register allocation
     * reginfo now also only allocated during register allocation
     * third round of gdb cleanups: kick out most of concatstabto
     * third round of gdb cleanups: kick out most of concatstabto
 
 

+ 86 - 15
compiler/ncgbas.pas

@@ -337,6 +337,8 @@ interface
 *****************************************************************************}
 *****************************************************************************}
 
 
     procedure tcgtempcreatenode.pass_2;
     procedure tcgtempcreatenode.pass_2;
+      var
+        cgsize: tcgsize;
       begin
       begin
         location_reset(location,LOC_VOID,OS_NO);
         location_reset(location,LOC_VOID,OS_NO);
 
 
@@ -346,9 +348,37 @@ interface
 
 
         { get a (persistent) temp }
         { get a (persistent) temp }
         if tempinfo^.restype.def.needs_inittable then
         if tempinfo^.restype.def.needs_inittable then
-          tg.GetTempTyped(exprasmlist,tempinfo^.restype.def,tempinfo^.temptype,tempinfo^.ref)
+          begin
+            tg.GetTempTyped(exprasmlist,tempinfo^.restype.def,tempinfo^.temptype,tempinfo^.loc.ref);
+            tempinfo^.loc.loc := LOC_REFERENCE;
+          end
+        else if may_be_in_reg then
+          begin
+            cgsize := def_cgsize(tempinfo^.restype.def);
+            if (OS_INT = OS_S32) then
+              begin
+                if not(cgsize in [OS_8,OS_16,OS_32,OS_S8,OS_S16,OS_S32]) then
+                  internalerror(2004020202);
+              end
+            else
+              begin
+                if not(cgsize in [OS_8,OS_16,OS_32,OS_64,OS_S8,OS_S16,OS_S32,OS_S64]) then
+                  internalerror(2004020202);
+              end;
+            tempinfo^.loc.reg := cg.getintregister(exprasmlist,cgsize);
+            if (tempinfo^.temptype = tt_persistent) then
+              begin
+                { !!tell rgobj this register is now a regvar, so it can't be freed!! }
+                tempinfo^.loc.loc := LOC_CREGISTER
+              end
+            else
+              tempinfo^.loc.loc := LOC_REGISTER;
+          end
         else
         else
-          tg.GetTemp(exprasmlist,size,tempinfo^.temptype,tempinfo^.ref);
+          begin
+            tg.GetTemp(exprasmlist,size,tempinfo^.temptype,tempinfo^.loc.ref);
+            tempinfo^.loc.loc := LOC_REFERENCE;
+          end;
         tempinfo^.valid := true;
         tempinfo^.valid := true;
       end;
       end;
 
 
@@ -362,10 +392,26 @@ interface
         { check if the temp is valid }
         { check if the temp is valid }
         if not tempinfo^.valid then
         if not tempinfo^.valid then
           internalerror(200108231);
           internalerror(200108231);
-        { set the temp's location }
-        location_reset(location,LOC_REFERENCE,def_cgsize(tempinfo^.restype.def));
-        location.reference := tempinfo^.ref;
-        inc(location.reference.offset,offset);
+        case tempinfo^.loc.loc of
+          LOC_REFERENCE:
+            begin
+              { set the temp's location }
+              location_reset(location,LOC_REFERENCE,def_cgsize(tempinfo^.restype.def));
+              location.reference := tempinfo^.loc.ref;
+              inc(location.reference.offset,offset);
+            end;
+          LOC_REGISTER,
+          LOC_CREGISTER:
+            begin
+              if offset <> 0 then
+                internalerror(2004020205);
+              { LOC_CREGISTER, not LOC_REGISTER, otherwise we can't assign anything to it }
+              location_reset(location,tempinfo^.loc.loc,def_cgsize(tempinfo^.restype.def));
+              location.register := tempinfo^.loc.reg;
+            end;
+          else
+            internalerror(2004020204);
+        end;
       end;
       end;
 
 
 
 
@@ -374,11 +420,13 @@ interface
         { check if the temp is valid }
         { check if the temp is valid }
         if not tempinfo^.valid then
         if not tempinfo^.valid then
           internalerror(200306081);
           internalerror(200306081);
+        if (tempinfo^.loc.loc = LOC_REGISTER) then
+          internalerror(2004020203);
         if (tempinfo^.temptype = tt_persistent) then
         if (tempinfo^.temptype = tt_persistent) then
-          tg.ChangeTempType(exprasmlist,tempinfo^.ref,tt_normal);
-        tg.ungettemp(exprasmlist,tempinfo^.ref);
-        tempinfo^.ref := ref;
-        tg.ChangeTempType(exprasmlist,tempinfo^.ref,tempinfo^.temptype);
+          tg.ChangeTempType(exprasmlist,tempinfo^.loc.ref,tt_normal);
+        tg.ungettemp(exprasmlist,tempinfo^.loc.ref);
+        tempinfo^.loc.ref := ref;
+        tg.ChangeTempType(exprasmlist,tempinfo^.loc.ref,tempinfo^.temptype);
         { adapt location }
         { adapt location }
         location.reference := ref;
         location.reference := ref;
         inc(location.reference.offset,offset);
         inc(location.reference.offset,offset);
@@ -393,10 +441,25 @@ interface
       begin
       begin
         location_reset(location,LOC_VOID,OS_NO);
         location_reset(location,LOC_VOID,OS_NO);
 
 
-        if release_to_normal then
-          tg.ChangeTempType(exprasmlist,tempinfo^.ref,tt_normal)
-        else
-          tg.UnGetTemp(exprasmlist,tempinfo^.ref);
+        case tempinfo^.loc.loc of
+          LOC_REFERENCE:
+            begin
+              if release_to_normal then
+                tg.ChangeTempType(exprasmlist,tempinfo^.loc.ref,tt_normal)
+              else
+                tg.UnGetTemp(exprasmlist,tempinfo^.loc.ref);
+            end;
+          LOC_REGISTER:
+            begin
+              if release_to_normal then
+                tempinfo^.loc.loc := LOC_REGISTER
+              else
+                begin
+                  { !!tell rgobj this register is no longer a regvar!! }
+                  cg.ungetregister(exprasmlist,tempinfo^.loc.reg);
+                end;
+            end;
+        end;
       end;
       end;
 
 
 
 
@@ -411,7 +474,15 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.51  2003-11-07 15:58:32  florian
+  Revision 1.52  2004-02-03 16:46:51  jonas
+    + support to store ttempcreate/ref/deletenodes in registers
+    * put temps for withnodes and some newnodes in registers
+     Note: this currently only works because calling ungetregister()
+       multiple times for the same register doesn't matter. We need again
+       a way to specify that a register is currently a regvar and as such
+       should not be freed when you call ungetregister() on it.
+
+  Revision 1.51  2003/11/07 15:58:32  florian
     * Florian's culmutative nr. 1; contains:
     * Florian's culmutative nr. 1; contains:
       - invalid calling conventions for a certain cpu are rejected
       - invalid calling conventions for a certain cpu are rejected
       - arm softfloat calling conventions
       - arm softfloat calling conventions

+ 10 - 2
compiler/ninl.pas

@@ -370,7 +370,7 @@ implementation
 
 
             { since the input/output variables are threadvars loading them into
             { since the input/output variables are threadvars loading them into
               a temp once is faster. Create a temp which will hold a pointer to the file }
               a temp once is faster. Create a temp which will hold a pointer to the file }
-            filetemp := ctempcreatenode.create(voidpointertype,voidpointertype.def.size,tt_persistent);
+            filetemp := ctempcreatenode.create_reg(voidpointertype,voidpointertype.def.size,tt_persistent);
             addstatement(newstatement,filetemp);
             addstatement(newstatement,filetemp);
 
 
             { make sure the resulttype of the temp (and as such of the }
             { make sure the resulttype of the temp (and as such of the }
@@ -2374,7 +2374,15 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.128  2004-02-02 20:41:59  florian
+  Revision 1.129  2004-02-03 16:46:51  jonas
+    + support to store ttempcreate/ref/deletenodes in registers
+    * put temps for withnodes and some newnodes in registers
+     Note: this currently only works because calling ungetregister()
+       multiple times for the same register doesn't matter. We need again
+       a way to specify that a register is currently a regvar and as such
+       should not be freed when you call ungetregister() on it.
+
+  Revision 1.128  2004/02/02 20:41:59  florian
     + added prefetch(const mem) support
     + added prefetch(const mem) support
 
 
   Revision 1.127  2004/01/26 16:12:28  daniel
   Revision 1.127  2004/01/26 16:12:28  daniel

+ 10 - 2
compiler/pinline.pas

@@ -240,7 +240,7 @@ implementation
                   if is_new then
                   if is_new then
                    begin
                    begin
                      { create temp for result }
                      { create temp for result }
-                     temp := ctempcreatenode.create(p.resulttype,p.resulttype.def.size,tt_persistent);
+                     temp := ctempcreatenode.create_reg(p.resulttype,p.resulttype.def.size,tt_persistent);
                      addstatement(newstatement,temp);
                      addstatement(newstatement,temp);
 
 
                      { create call to fpc_getmem }
                      { create call to fpc_getmem }
@@ -734,7 +734,15 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.26  2004-01-22 16:44:35  peter
+  Revision 1.27  2004-02-03 16:46:51  jonas
+    + support to store ttempcreate/ref/deletenodes in registers
+    * put temps for withnodes and some newnodes in registers
+     Note: this currently only works because calling ungetregister()
+       multiple times for the same register doesn't matter. We need again
+       a way to specify that a register is currently a regvar and as such
+       should not be freed when you call ungetregister() on it.
+
+  Revision 1.26  2004/01/22 16:44:35  peter
     * fixed allocation of dimension buffer for setlength(dynarr)
     * fixed allocation of dimension buffer for setlength(dynarr)
 
 
   Revision 1.25  2003/11/29 16:19:54  peter
   Revision 1.25  2003/11/29 16:19:54  peter

+ 10 - 2
compiler/pstatmnt.pas

@@ -436,7 +436,7 @@ implementation
                  htype:=p.resulttype
                  htype:=p.resulttype
                else
                else
                  htype.setdef(tpointerdef.create(p.resulttype));
                  htype.setdef(tpointerdef.create(p.resulttype));
-               loadp:=ctempcreatenode.create(htype,POINTER_SIZE,tt_persistent);
+               loadp:=ctempcreatenode.create_reg(htype,POINTER_SIZE,tt_persistent);
                resulttypepass(loadp);
                resulttypepass(loadp);
                if hasimplicitderef then
                if hasimplicitderef then
                 begin
                 begin
@@ -1087,7 +1087,15 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.126  2004-01-22 17:24:49  peter
+  Revision 1.127  2004-02-03 16:46:51  jonas
+    + support to store ttempcreate/ref/deletenodes in registers
+    * put temps for withnodes and some newnodes in registers
+     Note: this currently only works because calling ungetregister()
+       multiple times for the same register doesn't matter. We need again
+       a way to specify that a register is currently a regvar and as such
+       should not be freed when you call ungetregister() on it.
+
+  Revision 1.126  2004/01/22 17:24:49  peter
     * except is also an end of block token
     * except is also an end of block token
     * after a label don't try to parse a statement when the next token
     * after a label don't try to parse a statement when the next token
       is an end token
       is an end token