浏览代码

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

Jonas Maebe 22 年之前
父节点
当前提交
10eb92c546
共有 3 个文件被更改,包括 67 次插入23 次删除
  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                                                   }
         if assigned(resulttype.def) then
           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);
             while assigned(para) do
               begin
@@ -2627,7 +2632,11 @@ begin
 end.
 {
   $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()
       method. Useful to use instead of copying the contents from one temp to
       another

+ 46 - 15
compiler/ncgcal.pas

@@ -409,6 +409,8 @@ implementation
       var
         cgsize : tcgsize;
         r,hregister : tregister;
+        href: treference;
+        tempnode: tnode;
       begin
         { structured results are easy to handle.... }
         { needed also when result_no_used !! }
@@ -423,13 +425,34 @@ implementation
          if is_ansistring(resulttype.def) or
             is_widestring(resulttype.def) then
           begin
-            location_reset(location,LOC_CREFERENCE,OS_ADDR);
-            location.reference:=refcountedtemp;
             r.enum:=R_INTREGISTER;
             r.number:=NR_FUNCTION_RETURN_REG;
             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
         else
         { we have only to handle the result if it is used }
@@ -611,18 +634,22 @@ implementation
          iolabel:=nil;
          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
-             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;
+ 
 
          if (procdefinition.proccalloption in [pocall_cdecl,pocall_cppdecl,pocall_stdcall]) then
           para_alignment:=4
@@ -1382,7 +1409,11 @@ begin
 end.
 {
   $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 :)
 
   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     }
             { still be an argument to the function or even accessed in the   }
             { 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
              tcallnode(right).funcretnode := left;
              result := right;
@@ -1286,7 +1286,11 @@ begin
 end.
 {
   $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()
       method. Useful to use instead of copying the contents from one temp to
       another