Procházet zdrojové kódy

* An open array/array of const parameter passed by value and requiring a local copy on heap (currently all targets except non-Darwin i386 ones) should not be placed into register and should force procedure to have an implicit finally block.
* At the same time, allow non-value parameters to be placed into registers even if they have managed type (it is ok because they don't participate in implicit exception handing; explicit exception handling still forces them to memory due to logic in tabstractvarsym.is_regvar).
+ Added tparavarsym.needs_finalization method to handle this logic in a single place.
+ Added tparamanager.use_stackalloc method to determine if local copies should be allocated on heap.

git-svn-id: trunk@19762 -

sergei před 13 roky
rodič
revize
270fc39432
4 změnil soubory, kde provedl 23 přidání a 3 odebrání
  1. 9 0
      compiler/paramgr.pas
  2. 1 1
      compiler/pdecsub.pas
  3. 1 2
      compiler/psub.pas
  4. 12 0
      compiler/symsym.pas

+ 9 - 0
compiler/paramgr.pas

@@ -134,6 +134,8 @@ unit paramgr;
 
           { allocate room for parameters on the stack in the entry code? }
           function use_fixed_stack: boolean;
+          { whether stack pointer can be changed in the middle of procedure }
+          function use_stackalloc: boolean;
        end;
 
 
@@ -467,6 +469,13 @@ implementation
 {$endif i386}
       end;
 
+    { This is a separate function because at least win64 allows stack allocations
+      despite of fixed stack semantics (actually supporting it requires generating
+      a compliant stack frame, not yet possible) }
+    function tparamanager.use_stackalloc: boolean;
+      begin
+        result:=not use_fixed_stack;
+      end;
 
 initialization
   ;

+ 1 - 1
compiler/pdecsub.pas

@@ -488,7 +488,7 @@ implementation
          exit;
         with tparavarsym(p) do
          begin
-           if not is_managed_type(vardef) and
+           if (not needs_finalization) and
               paramanager.push_addr_param(varspez,vardef,tprocdef(arg).proccalloption) then
              varregable:=vr_intreg;
          end;

+ 1 - 2
compiler/psub.pas

@@ -144,8 +144,7 @@ implementation
     procedure check_finalize_paras(p:TObject;arg:pointer);
       begin
         if (tsym(p).typ=paravarsym) and
-           (tparavarsym(p).varspez=vs_value) and
-           is_managed_type(tparavarsym(p).vardef) then
+           tparavarsym(p).needs_finalization then
           include(current_procinfo.flags,pi_needs_implicit_finally);
       end;
 

+ 12 - 0
compiler/symsym.pas

@@ -206,6 +206,7 @@ interface
           constructor ppuload(ppufile:tcompilerppufile);
           destructor destroy;override;
           procedure ppuwrite(ppufile:tcompilerppufile);override;
+          function needs_finalization: boolean;
       end;
 
       tstaticvarsym = class(tabstractnormalvarsym)
@@ -1592,6 +1593,17 @@ implementation
          ppufile.writeentry(ibparavarsym);
       end;
 
+    function tparavarsym.needs_finalization:boolean;
+      begin
+        result:=(varspez=vs_value) and
+          (is_managed_type(vardef) or
+            (
+              (not (tabstractprocdef(owner.defowner).proccalloption in cdecl_pocalls)) and
+              (not paramanager.use_stackalloc) and
+              (is_open_array(vardef) or is_array_of_const(vardef))
+            )
+          );
+      end;
 
 {****************************************************************************
                                TABSOLUTEVARSYM