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);
       cleanup_regvars(list);
 {$endif OLDREGVARS}
 {$endif OLDREGVARS}
 
 
-      { finalize temporary data }
-      finalizetempvariables(list);
-
       { finalize paras data }
       { finalize paras data }
       if assigned(current_procinfo.procdef.parast) and
       if assigned(current_procinfo.procdef.parast) and
          not(po_assembler in current_procinfo.procdef.procoptions) then
          not(po_assembler in current_procinfo.procdef.procoptions) then
         current_procinfo.procdef.parast.SymList.ForEachCall(@final_paras,list);
         current_procinfo.procdef.parast.SymList.ForEachCall(@final_paras,list);
+
+      { finalize temporary data }
+      finalizetempvariables(list);
+
       current_procinfo:=old_current_procinfo;
       current_procinfo:=old_current_procinfo;
     end;
     end;
 
 

+ 0 - 2
compiler/i386/n386flw.pas

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

+ 30 - 1
compiler/nbas.pas

@@ -59,6 +59,13 @@ interface
        end;
        end;
        tspecializenodeclass = class of tspecializenode;
        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)
        tasmnode = class(tnode)
           p_asm : TAsmList;
           p_asm : TAsmList;
           currenttai : tai;
           currenttai : tai;
@@ -289,6 +296,7 @@ interface
        cnothingnode : tnothingnodeclass = tnothingnode;
        cnothingnode : tnothingnodeclass = tnothingnode;
        cerrornode : terrornodeclass = terrornode;
        cerrornode : terrornodeclass = terrornode;
        cspecializenode : tspecializenodeclass = tspecializenode;
        cspecializenode : tspecializenodeclass = tspecializenode;
+       cfinalizetempsnode: tfinalizetempsnodeclass = tfinalizetempsnode;
        casmnode : tasmnodeclass = tasmnode;
        casmnode : tasmnodeclass = tasmnode;
        cstatementnode : tstatementnodeclass = tstatementnode;
        cstatementnode : tstatementnodeclass = tstatementnode;
        cblocknode : tblocknodeclass = tblocknode;
        cblocknode : tblocknodeclass = tblocknode;
@@ -363,7 +371,6 @@ implementation
       end;
       end;
 
 
 
 
-
 {*****************************************************************************
 {*****************************************************************************
                              TFIRSTNOTHING
                              TFIRSTNOTHING
 *****************************************************************************}
 *****************************************************************************}
@@ -456,6 +463,28 @@ implementation
       end;
       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
                             TSTATEMENTNODE
 *****************************************************************************}
 *****************************************************************************}

+ 16 - 0
compiler/ncgbas.pas

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

+ 4 - 2
compiler/node.pas

@@ -110,7 +110,8 @@ interface
           loadparentfpn,    { Load the framepointer of the parent for nested procedures }
           loadparentfpn,    { Load the framepointer of the parent for nested procedures }
           objcselectorn,    { node for an Objective-C message selector }
           objcselectorn,    { node for an Objective-C message selector }
           objcprotocoln,    { node for an Objective-C @protocol() expression (returns metaclass associated with protocol) }
           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;
        tnodetypeset = set of tnodetype;
@@ -194,7 +195,8 @@ interface
           'loadparentfpn',
           'loadparentfpn',
           'objcselectorn',
           'objcselectorn',
           'objcprotocoln',
           'objcprotocoln',
-          'specializen');
+          'specializen',
+          'finalizetempsn');
 
 
       { a set containing all const nodes }
       { a set containing all const nodes }
       nodetype_const = [niln,
       nodetype_const = [niln,

+ 5 - 0
compiler/nutils.pas

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

+ 2 - 1
compiler/pass_2.pas

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

+ 13 - 21
compiler/psub.pas

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