Browse Source

* moved finalization of code generator temps to a node, so it can be getcopy'd
(needed for LLVM, where we need two copies of the finally code: one in case
an exception occurs, and one in case none is raised)
o also first finalize parameters and only then code generator temps, since
in theory the former could create more of the latter

git-svn-id: trunk@40345 -

Jonas Maebe 6 years ago
parent
commit
3b9f5a5e96

+ 4 - 3
compiler/hlcgobj.pas

@@ -4567,13 +4567,14 @@ implementation
       cleanup_regvars(list);
 {$endif OLDREGVARS}
 
-      { finalize temporary data }
-      finalizetempvariables(list);
-
       { finalize paras data }
       if assigned(current_procinfo.procdef.parast) and
          not(po_assembler in current_procinfo.procdef.procoptions) then
         current_procinfo.procdef.parast.SymList.ForEachCall(@final_paras,list);
+
+      { finalize temporary data }
+      finalizetempvariables(list);
+
       current_procinfo:=old_current_procinfo;
     end;
 

+ 0 - 2
compiler/i386/n386flw.pas

@@ -247,8 +247,6 @@ function ti386tryfinallynode.simplify(forinline: boolean): tnode;
         if implicitframe then
           begin
             current_procinfo.finalize_procinfo:=finalizepi;
-            { don't leave dangling pointer }
-            tcgprocinfo(current_procinfo).final_asmnode:=nil;
           end;
       end;
   end;

+ 30 - 1
compiler/nbas.pas

@@ -59,6 +59,13 @@ interface
        end;
        tspecializenodeclass = class of tspecializenode;
 
+       tfinalizetempsnode = class(tnode)
+          constructor create;virtual;
+          function pass_1 : tnode;override;
+          function pass_typecheck:tnode;override;
+       end;
+       tfinalizetempsnodeclass = class of tfinalizetempsnode;
+
        tasmnode = class(tnode)
           p_asm : TAsmList;
           currenttai : tai;
@@ -289,6 +296,7 @@ interface
        cnothingnode : tnothingnodeclass = tnothingnode;
        cerrornode : terrornodeclass = terrornode;
        cspecializenode : tspecializenodeclass = tspecializenode;
+       cfinalizetempsnode: tfinalizetempsnodeclass = tfinalizetempsnode;
        casmnode : tasmnodeclass = tasmnode;
        cstatementnode : tstatementnodeclass = tstatementnode;
        cblocknode : tblocknodeclass = tblocknode;
@@ -363,7 +371,6 @@ implementation
       end;
 
 
-
 {*****************************************************************************
                              TFIRSTNOTHING
 *****************************************************************************}
@@ -456,6 +463,28 @@ implementation
       end;
 
 
+{*****************************************************************************
+                             TFINALIZETEMPSNODE
+*****************************************************************************}
+
+    constructor tfinalizetempsnode.create;
+      begin
+        inherited create(finalizetempsn);
+      end;
+
+    function tfinalizetempsnode.pass_1: tnode;
+      begin
+        result:=nil;
+        expectloc:=LOC_VOID;
+      end;
+
+    function tfinalizetempsnode.pass_typecheck: tnode;
+      begin
+        resultdef:=voidtype;
+        result:=nil;
+      end;
+
+
 {*****************************************************************************
                             TSTATEMENTNODE
 *****************************************************************************}

+ 16 - 0
compiler/ncgbas.pas

@@ -68,6 +68,10 @@ interface
           procedure pass_generate_code;override;
        end;
 
+       tcgfinalizetempsnode = class(tfinalizetempsnode)
+          procedure pass_generate_code; override;
+       end;
+
   implementation
 
     uses
@@ -714,6 +718,17 @@ interface
       end;
 
 
+{*****************************************************************************
+                         TCGFINALIZETEMPSNODE
+*****************************************************************************}
+
+    procedure tcgfinalizetempsnode.pass_generate_code;
+      begin
+        hlcg.gen_finalize_code(current_asmdata.CurrAsmList);
+        location.loc:=LOC_VOID;
+      end;
+
+
 begin
    cnothingnode:=tcgnothingnode;
    casmnode:=tcgasmnode;
@@ -722,4 +737,5 @@ begin
    ctempcreatenode:=tcgtempcreatenode;
    ctemprefnode:=tcgtemprefnode;
    ctempdeletenode:=tcgtempdeletenode;
+   cfinalizetempsnode:=tcgfinalizetempsnode;
 end.

+ 4 - 2
compiler/node.pas

@@ -110,7 +110,8 @@ interface
           loadparentfpn,    { Load the framepointer of the parent for nested procedures }
           objcselectorn,    { node for an Objective-C message selector }
           objcprotocoln,    { node for an Objective-C @protocol() expression (returns metaclass associated with protocol) }
-          specializen       { parser-only node to handle Delphi-mode inline specializations }
+          specializen,      { parser-only node to handle Delphi-mode inline specializations }
+          finalizetempsn        { Internal node used to clean up code generator temps (warning: must NOT create additional tepms that may need to be finalised!) }
        );
 
        tnodetypeset = set of tnodetype;
@@ -194,7 +195,8 @@ interface
           'loadparentfpn',
           'objcselectorn',
           'objcprotocoln',
-          'specializen');
+          'specializen',
+          'finalizetempsn');
 
       { a set containing all const nodes }
       nodetype_const = [niln,

+ 5 - 0
compiler/nutils.pas

@@ -963,6 +963,11 @@ implementation
                   end;
 
                 end;
+              finalizetempsn:
+                begin
+                  result:=NODE_COMPLEXITY_INF;
+                  exit;
+                end;
               else
                 begin
                   result := NODE_COMPLEXITY_INF;

+ 2 - 1
compiler/pass_2.pas

@@ -156,7 +156,8 @@ implementation
              'loadparentfpn',
              'objselectorn',
              'objcprotocoln',
-             'specializen'
+             'specializen',
+             'finalizetemps'
              );
       var
         p: pchar;

+ 13 - 21
compiler/psub.pas

@@ -47,9 +47,8 @@ interface
         loadpara_asmnode,
         exitlabel_asmnode,
         stackcheck_asmnode,
-        init_asmnode,
-        final_asmnode : tasmnode;
-        final_used : boolean;
+        init_asmnode    : tasmnode;
+        temps_finalized : boolean;
         dfabuilder : TDFABuilder;
 
         destructor  destroy;override;
@@ -678,8 +677,6 @@ implementation
      destructor tcgprocinfo.destroy;
        begin
          code.free;
-         if not final_used then
-           final_asmnode.free;
          inherited destroy;
        end;
 
@@ -768,9 +765,9 @@ implementation
                   (cs_implicit_exceptions in current_settings.moduleswitches)) then
                   begin
                     include(tocode.flags,nf_block_with_exit);
-                    addstatement(newstatement,final_asmnode);
+                    addstatement(newstatement,cfinalizetempsnode.create);
                     cnodeutils.procdef_block_add_implicit_finalize_nodes(procdef,newstatement);
-                    final_used:=true;
+                    temps_finalized:=true;
                   end;
 
                 { construction successful -> beforedestruction should be called
@@ -880,8 +877,7 @@ implementation
         { Generate code/locations used at end of proc }
         current_filepos:=exitpos;
         exitlabel_asmnode:=casmnode.create_get_position;
-        final_asmnode:=casmnode.create_get_position;
-        final_used:=false;
+        temps_finalized:=false;
         bodyexitcode:=generate_bodyexit_block;
 
         { Generate procedure by combining init+body+final,
@@ -914,13 +910,13 @@ implementation
             current_filepos:=exitpos;
             { Generate code that will be in the try...finally }
             finalcode:=internalstatements(codestatement);
-            addstatement(codestatement,final_asmnode);
+            addstatement(codestatement,cfinalizetempsnode.create);
             cnodeutils.procdef_block_add_implicit_finalize_nodes(procdef,codestatement);
-            final_used:=true;
+            temps_finalized:=true;
 
             current_filepos:=entrypos;
             wrappedbody:=ctryfinallynode.create_implicit(code,finalcode);
-            { afterconstruction must be called after final_asmnode, because it
+            { afterconstruction must be called after finalizetemps, because it
                has to execute after the temps have been finalised in case of a
                refcounted class (afterconstruction decreases the refcount
                without freeing the instance if the count becomes nil, while
@@ -947,12 +943,12 @@ implementation
             addstatement(newstatement,bodyexitcode);
             if not is_constructor then
               begin
-                addstatement(newstatement,final_asmnode);
+                addstatement(newstatement,cfinalizetempsnode.create);
                 cnodeutils.procdef_block_add_implicit_finalize_nodes(procdef,newstatement);
-                final_used:=true;
+                temps_finalized:=true;
               end;
           end;
-        if not final_used then
+        if not temps_finalized then
           begin
             current_filepos:=exitpos;
             cnodeutils.procdef_block_add_implicit_finalize_nodes(procdef,newstatement);
@@ -1569,16 +1565,13 @@ implementation
 
             if assigned(finalize_procinfo) then
               generate_exceptfilter(tcgprocinfo(finalize_procinfo))
-            else
+            else if not temps_finalized then
               begin
                 hlcg.gen_finalize_code(templist);
                 { the finalcode must be concated if there was no position available,
                   using insertlistafter will result in an insert at the start
                   when currentai=nil }
-                if assigned(final_asmnode) and assigned(final_asmnode.currenttai) then
-                  aktproccode.insertlistafter(final_asmnode.currenttai,templist)
-                else
-                  aktproccode.concatlist(templist);
+                aktproccode.concatlist(templist);
               end;
             { insert exit label at the correct position }
             hlcg.a_label(templist,CurrExitLabel);
@@ -1753,7 +1746,6 @@ implementation
             delete_marker(exitlabel_asmnode);
             delete_marker(stackcheck_asmnode);
             delete_marker(init_asmnode);
-            delete_marker(final_asmnode);
 
 {$ifndef NoOpt}
             if not(cs_no_regalloc in current_settings.globalswitches) then

+ 0 - 2
compiler/x86_64/nx64flw.pas

@@ -216,8 +216,6 @@ function tx64tryfinallynode.simplify(forinline: boolean): tnode;
         if implicitframe then
           begin
             current_procinfo.finalize_procinfo:=finalizepi;
-            { don't leave dangling pointer }
-            tcgprocinfo(current_procinfo).final_asmnode:=nil;
           end;
       end;
   end;