Browse Source

* optimized assignments with on the right side a function that returns
an ansi- or widestring

Jonas Maebe 22 years ago
parent
commit
10eb92c546
3 changed files with 67 additions and 23 deletions
  1. 10 1
      compiler/ncal.pas
  2. 46 15
      compiler/ncgcal.pas
  3. 11 7
      compiler/nld.pas

+ 10 - 1
compiler/ncal.pas

@@ -977,6 +977,11 @@ type
         { everything                                                   }
         { everything                                                   }
         if assigned(resulttype.def) then
         if assigned(resulttype.def) then
           begin
           begin
+            { these are returned as values, but we can optimize their loading }
+            { as well                                                         }
+            if is_ansistring(resulttype.def) or
+               is_widestring(resulttype.def) then
+              exit;
             para := tcallparanode(left);
             para := tcallparanode(left);
             while assigned(para) do
             while assigned(para) do
               begin
               begin
@@ -2627,7 +2632,11 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.167  2003-06-08 18:27:15  jonas
+  Revision 1.168  2003-06-08 20:01:53  jonas
+    * optimized assignments with on the right side a function that returns
+      an ansi- or widestring
+
+  Revision 1.167  2003/06/08 18:27:15  jonas
     + ability to change the location of a ttempref node with changelocation()
     + ability to change the location of a ttempref node with changelocation()
       method. Useful to use instead of copying the contents from one temp to
       method. Useful to use instead of copying the contents from one temp to
       another
       another

+ 46 - 15
compiler/ncgcal.pas

@@ -409,6 +409,8 @@ implementation
       var
       var
         cgsize : tcgsize;
         cgsize : tcgsize;
         r,hregister : tregister;
         r,hregister : tregister;
+        href: treference;
+        tempnode: tnode;
       begin
       begin
         { structured results are easy to handle.... }
         { structured results are easy to handle.... }
         { needed also when result_no_used !! }
         { needed also when result_no_used !! }
@@ -423,13 +425,34 @@ implementation
          if is_ansistring(resulttype.def) or
          if is_ansistring(resulttype.def) or
             is_widestring(resulttype.def) then
             is_widestring(resulttype.def) then
           begin
           begin
-            location_reset(location,LOC_CREFERENCE,OS_ADDR);
-            location.reference:=refcountedtemp;
             r.enum:=R_INTREGISTER;
             r.enum:=R_INTREGISTER;
             r.number:=NR_FUNCTION_RETURN_REG;
             r.number:=NR_FUNCTION_RETURN_REG;
             cg.a_reg_alloc(exprasmlist,r);
             cg.a_reg_alloc(exprasmlist,r);
-            cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,r,location.reference);
-            cg.a_reg_dealloc(exprasmlist,r);
+            if not assigned(funcretnode) then
+              begin
+                location_reset(location,LOC_CREFERENCE,OS_ADDR);
+                location.reference:=refcountedtemp;
+                cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,r,location.reference);
+                cg.a_reg_dealloc(exprasmlist,r);
+              end
+            else
+              begin
+                tg.gettemp(exprasmlist,pointer_size,tt_normal,href);
+                cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,r,href);
+                cg.a_reg_dealloc(exprasmlist,r);
+                { in case of a regular funcretnode with ret_in_param, the }
+                { original funcretnode isn't touched -> make sure it's    }
+                { the same here (not sure if it's necessary)              }
+                tempnode := funcretnode.getcopy;
+                tempnode.pass_2;
+                location := tempnode.location;
+                tempnode.free;
+                cg.g_decrrefcount(exprasmlist,resulttype.def,location.reference, false);
+                cg.a_load_ref_ref(exprasmlist,OS_ADDR,OS_ADDR,href,location.reference);
+                { since we used a normal temp, it won't be finalized or }
+                { decref'd later -> no need to zero it                  }
+                tg.ungettemp(exprasmlist,href);
+              end;
           end
           end
         else
         else
         { we have only to handle the result if it is used }
         { we have only to handle the result if it is used }
@@ -611,18 +634,22 @@ implementation
          iolabel:=nil;
          iolabel:=nil;
          rg.saveunusedstate(unusedstate);
          rg.saveunusedstate(unusedstate);
 
 
-         { if we allocate the temp. location for ansi- or widestrings }
-         { already here, we avoid later a push/pop                    }
-         if is_widestring(resulttype.def) then
+         if not assigned(funcretnode) then
            begin
            begin
-             tg.gettemp(exprasmlist,pointer_size,tt_widestring,refcountedtemp);
-             cg.g_decrrefcount(exprasmlist,resulttype.def,refcountedtemp,false);
-           end
-         else if is_ansistring(resulttype.def) then
-           begin
-             tg.GetTemp(exprasmlist,pointer_size,tt_ansistring,refcountedtemp);
-             cg.g_decrrefcount(exprasmlist,resulttype.def,refcountedtemp,false);
+             { if we allocate the temp. location for ansi- or widestrings }
+             { already here, we avoid later a push/pop                    }
+             if is_widestring(resulttype.def) then
+               begin
+                 tg.gettemp(exprasmlist,pointer_size,tt_widestring,refcountedtemp);
+                 cg.g_decrrefcount(exprasmlist,resulttype.def,refcountedtemp,false);
+               end
+             else if is_ansistring(resulttype.def) then
+               begin
+                 tg.GetTemp(exprasmlist,pointer_size,tt_ansistring,refcountedtemp);
+                 cg.g_decrrefcount(exprasmlist,resulttype.def,refcountedtemp,false);
+               end;
            end;
            end;
+ 
 
 
          if (procdefinition.proccalloption in [pocall_cdecl,pocall_cppdecl,pocall_stdcall]) then
          if (procdefinition.proccalloption in [pocall_cdecl,pocall_cppdecl,pocall_stdcall]) then
           para_alignment:=4
           para_alignment:=4
@@ -1382,7 +1409,11 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.87  2003-06-08 18:21:47  jonas
+  Revision 1.88  2003-06-08 20:01:53  jonas
+    * optimized assignments with on the right side a function that returns
+      an ansi- or widestring
+
+  Revision 1.87  2003/06/08 18:21:47  jonas
     * fixed weird error in the copyleft statement :)
     * fixed weird error in the copyleft statement :)
 
 
   Revision 1.86  2003/06/07 18:57:04  jonas
   Revision 1.86  2003/06/07 18:57:04  jonas

+ 11 - 7
compiler/nld.pas

@@ -838,12 +838,12 @@ implementation
             { result, the current left node is modified and that one may     }
             { result, the current left node is modified and that one may     }
             { still be an argument to the function or even accessed in the   }
             { still be an argument to the function or even accessed in the   }
             { function                                                       }
             { function                                                       }
-            (left.nodetype = temprefn) and
-            { doesn't work correctlyfor refcounted things }
-            not(not is_class(right.resulttype.def) and
-                right.resulttype.def.needs_inittable) and
-            paramanager.ret_in_param(right.resulttype.def,
-             tcallnode(right).procdefinition.proccalloption) then
+            (((left.nodetype = temprefn) and
+              paramanager.ret_in_param(right.resulttype.def,
+                tcallnode(right).procdefinition.proccalloption)) or
+             { there's special support for ansi/widestrings in the callnode }
+             is_ansistring(right.resulttype.def) or
+             is_widestring(right.resulttype.def))  then
            begin
            begin
              tcallnode(right).funcretnode := left;
              tcallnode(right).funcretnode := left;
              result := right;
              result := right;
@@ -1286,7 +1286,11 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.100  2003-06-08 18:27:15  jonas
+  Revision 1.101  2003-06-08 20:01:53  jonas
+    * optimized assignments with on the right side a function that returns
+      an ansi- or widestring
+
+  Revision 1.100  2003/06/08 18:27:15  jonas
     + ability to change the location of a ttempref node with changelocation()
     + ability to change the location of a ttempref node with changelocation()
       method. Useful to use instead of copying the contents from one temp to
       method. Useful to use instead of copying the contents from one temp to
       another
       another