瀏覽代碼

* assume that compilerprocs never capture the addresses of their arguments

git-svn-id: trunk@31489 -
Jonas Maebe 10 年之前
父節點
當前提交
ee3f89246c
共有 1 個文件被更改,包括 34 次插入16 次删除
  1. 34 16
      compiler/ncal.pas

+ 34 - 16
compiler/ncal.pas

@@ -1306,7 +1306,12 @@ implementation
                         { uninitialized warnings (tbs/tb0542)         }
                         { uninitialized warnings (tbs/tb0542)         }
                         set_varstate(left,vs_written,[]);
                         set_varstate(left,vs_written,[]);
                         set_varstate(left,vs_readwritten,[]);
                         set_varstate(left,vs_readwritten,[]);
-                        make_not_regable(left,[ra_addr_regable,ra_addr_taken]);
+                        { compilerprocs never capture the address of their
+                          parameters }
+                        if not(po_compilerproc in aktcallnode.procdefinition.procoptions) then
+                          make_not_regable(left,[ra_addr_regable,ra_addr_taken])
+                        else
+                          make_not_regable(left,[ra_addr_regable])
                       end;
                       end;
                     vs_var,
                     vs_var,
                     vs_constref:
                     vs_constref:
@@ -1315,7 +1320,12 @@ implementation
                         { constref takes also the address, but storing it is actually the compiler
                         { constref takes also the address, but storing it is actually the compiler
                           is not supposed to expect }
                           is not supposed to expect }
                         if parasym.varspez=vs_var then
                         if parasym.varspez=vs_var then
-                          make_not_regable(left,[ra_addr_regable,ra_addr_taken]);
+                          { compilerprocs never capture the address of their
+                            parameters }
+                          if not(po_compilerproc in aktcallnode.procdefinition.procoptions) then
+                            make_not_regable(left,[ra_addr_regable,ra_addr_taken])
+                          else
+                            make_not_regable(left,[ra_addr_regable])
                       end;
                       end;
                     else
                     else
                       set_varstate(left,vs_read,[vsf_must_be_valid]);
                       set_varstate(left,vs_read,[vsf_must_be_valid]);
@@ -2885,21 +2895,28 @@ implementation
            (procdefinition.parast.symtablelevel=normal_function_level) and
            (procdefinition.parast.symtablelevel=normal_function_level) and
            { must be a local variable, a value para or a hidden function result }
            { must be a local variable, a value para or a hidden function result }
            { parameter (which can be passed by address, but in that case it got }
            { parameter (which can be passed by address, but in that case it got }
-           { through these same checks at the caller side and is thus safe      }
-           (
-            (tloadnode(realassignmenttarget).symtableentry.typ=localvarsym) or
+           { through these same checks at the caller side and is thus safe )    }
+           { other option: we're calling a compilerproc, because those don't
+             rely on global state
+           }
+           ((po_compilerproc in procdefinition.procoptions) or
             (
             (
-             (tloadnode(realassignmenttarget).symtableentry.typ=paravarsym) and
-             ((tparavarsym(tloadnode(realassignmenttarget).symtableentry).varspez = vs_value) or
-              (vo_is_funcret in tparavarsym(tloadnode(realassignmenttarget).symtableentry).varoptions))
+             (
+              (tloadnode(realassignmenttarget).symtableentry.typ=localvarsym) or
+              (
+               (tloadnode(realassignmenttarget).symtableentry.typ=paravarsym) and
+               ((tparavarsym(tloadnode(realassignmenttarget).symtableentry).varspez = vs_value) or
+                (vo_is_funcret in tparavarsym(tloadnode(realassignmenttarget).symtableentry).varoptions))
+              )
+             ) and
+             { the address may not have been taken of the variable/parameter, because }
+             { otherwise it's possible that the called function can access it via a   }
+             { global variable or other stored state                                  }
+             (
+              not(tabstractvarsym(tloadnode(realassignmenttarget).symtableentry).addr_taken) and
+              (tabstractvarsym(tloadnode(realassignmenttarget).symtableentry).varregable in [vr_none,vr_addr])
+             )
             )
             )
-           ) and
-           { the address may not have been taken of the variable/parameter, because }
-           { otherwise it's possible that the called function can access it via a   }
-           { global variable or other stored state                                  }
-           (
-            not(tabstractvarsym(tloadnode(realassignmenttarget).symtableentry).addr_taken) and
-            (tabstractvarsym(tloadnode(realassignmenttarget).symtableentry).varregable in [vr_none,vr_addr])
            ) then
            ) then
           begin
           begin
             { If the funcret is also used as a parameter we can't optimize because the funcret
             { If the funcret is also used as a parameter we can't optimize because the funcret
@@ -4050,7 +4067,8 @@ implementation
                   function result" is not something which can be stored
                   function result" is not something which can be stored
                   persistently by the callee (it becomes invalid when the callee
                   persistently by the callee (it becomes invalid when the callee
                   returns)                                                       }
                   returns)                                                       }
-                if not(vo_is_funcret in hp.parasym.varoptions) then
+                if not(vo_is_funcret in hp.parasym.varoptions) and
+                   not(po_compilerproc in procdefinition.procoptions) then
                   make_not_regable(hp.left,[ra_addr_regable,ra_addr_taken])
                   make_not_regable(hp.left,[ra_addr_regable,ra_addr_taken])
                 else
                 else
                   make_not_regable(hp.left,[ra_addr_regable]);
                   make_not_regable(hp.left,[ra_addr_regable]);