Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2022-01

Issue 3.2.3 (ok in 3.3.1) Win64 "raise exception" does not go to "except"

4 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Martin Frb

In the  below code compiled with 3.2.3 (today and early Dec) when the exception is reached the app exits.

There is no code from finally, nor from except block executed.

The "randomize" is just to put some code into each block. No special meaning otherwise.

This issue is on Win64. (works for 32 bit Win)
And appears to be ok in 3.3.1.

     program Project1;
     {$mode objfpc}{$H+}
     uses SysUtils;
     var
       bar: boolean;
     procedure Foo;
     begin
       while true do begin
         try
           try
             try
               if bar then
                 raise Exception.Create('');
               Randomize;
             finally
               Randomize;
               try
                 Randomize;
               finally
                 Randomize;
               end;
             end;
             Randomize;
           finally
             Randomize;
           end;
           Randomize;
         except
           bar := false;
           Randomize;
         end;
       end;
     end;
     begin
       bar := true;
       Foo;
     end.

Reply by email

Florian Klämpfl
to Martin Frb
Martin Frb wrote 9 lines
In the  below code compiled with 3.2.3 (today and early Dec) when the exception is reached the app exits. There is no code from finally, nor from except block executed. The "randomize" is just to put some code into each block. No special meaning otherwise. This issue is on Win64. (works for 32 bit Win) And appears to be ok in 3.3.1.

It happens only with -O1 or higher, the compiler optimizes away all the exception data (diff between -O- and -O1):

176,180d170
< # [37] end;
< nop
< leaq (%rbp),%rsp
< popq %rbp
< ret
183,195d172
< .long 3
< .long 0
< .rva .Lj27
< .rva .Lj28
< .rva P$PROJECT1$_$FOO_$$_fin$00000002
< .long 0
< .rva .Lj22
< .rva .Lj23
< .rva P$PROJECT1$_$FOO_$$_fin$00000003
< .long 1
< .rva .Lj20
< .rva .Lj17
< .rva .Lj18
199a177

# [37] end;

Maybe Gareth can have a look?

Show quoted text 46 lines
    program Project1;     {$mode objfpc}{$H+}     uses SysUtils;     var       bar: boolean;     procedure Foo;     begin       while true do begin         try           try             try               if bar then                 raise Exception.Create('');               Randomize;             finally               Randomize;               try                 Randomize;               finally                 Randomize;               end;             end;             Randomize;           finally             Randomize;           end;           Randomize;         except           bar := false;           Randomize;         end;       end;     end;     begin       bar := true;       Foo;     end. _______________________________________________ fpc-devel maillist  -  https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

Reply by email

J. Gareth Moreton
to Florian Klämpfl

Found the reason for it, or at least what looks like the reason... the RemoveDeadCodeAfterJump routine, which removes all instructions between a "jmp" instruction and the next live label (since those instructions will never get executed), doesn't stop if it hits the SEH section and strips all that too.  Because of the "while True do" block covering the entire procedure, the function epilogue is suppressed by an unconditional jump and so gets stripped out (arguably fine in this case), but the optimizer doesn't think to stop if it goes past the final instruction.  I'll start doing a bisect to see if I can locate where this is corrected... or just write it myself if that fails.

Gareth aka. Kit

Florian Klämpfl wrote 91 lines
Am 13.01.2022 um 16:49 schrieb Martin Frb via fpc-devel: > In the  below code compiled with 3.2.3 (today and early Dec) > when the exception is reached the app exits. > > There is no code from finally, nor from except block executed. > > The "randomize" is just to put some code into each block. No special > meaning otherwise. > > This issue is on Win64. (works for 32 bit Win) > And appears to be ok in 3.3.1. It happens only with -O1 or higher, the compiler optimizes away all the exception data (diff between -O- and -O1): 176,180d170 < # [37] end; <       nop <       leaq    (%rbp),%rsp <       popq    %rbp <       ret 183,195d172 <       .long   3 <       .long   0 <       .rva    .Lj27 <       .rva    .Lj28 <       .rva    P$PROJECT1$_$FOO_$$_fin$00000002 <       .long   0 <       .rva    .Lj22 <       .rva    .Lj23 <       .rva    P$PROJECT1$_$FOO_$$_fin$00000003 <       .long   1 <       .rva    .Lj20 <       .rva    .Lj17 <       .rva    .Lj18 199a177 > # [37] end; Maybe Gareth can have a look? > >      program Project1; >      {$mode objfpc}{$H+} > >      uses SysUtils; > >      var >        bar: boolean; > >      procedure Foo; >      begin >        while true do begin >          try >            try >              try >                if bar then >                  raise Exception.Create(''); >                Randomize; >              finally >                Randomize; >                try >                  Randomize; >                finally >                  Randomize; >                end; >              end; >              Randomize; >            finally >              Randomize; >            end; >            Randomize; >          except >            bar := false; >            Randomize; >          end; >        end; >      end; > >      begin >        bar := true; >        Foo; >      end. > > _______________________________________________ > fpc-devel maillist  -  > https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel _______________________________________________ fpc-devel maillist  -  https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus

Reply by email

J. Gareth Moreton
to J. Gareth Moreton

Commit af107ca8fee33355e8c35fab6fc5ba5290bd3ebc fixes the problem in the main branch, so this one should be merged into fixes_3_2.

Note that this commit also extends an optimisation in OptPass2JMP that is unrelated to the bug fix.  If this proves incompatible with the fixes branch, it can be ignored, because the bug fix is wholly contained within compiler/aoptobj.pas, while the additional optimisation is in compiler/x86/aoptx86.pas.

If needs be, the following can be merged manually:

diff --git a/compiler/aoptobj.pas b/compiler/aoptobj.pas index 33efd80aad..67b62606cb 100644
--- a/compiler/aoptobj.pas
+++ b/compiler/aoptobj.pas
@@ -1616,6 +1616,15 @@ Unit AoptObj;

     { Removes all instructions between an unconditional jump and the next label }
     procedure TAOptObj.RemoveDeadCodeAfterJump(p: tai); +      const
+{$ifdef JVM}
+        TaiFence = SkipInstr + [ait_const, ait_realconst, ait_typedconst, ait_label, ait_jcatch];
+{$else JVM}
+        { Stop if it reaches SEH directive information in the form of +          consts, which may occur if RemoveDeadCodeAfterJump is called on +          the final RET instruction on x86, for example } +        TaiFence = SkipInstr + [ait_const, ait_realconst, ait_typedconst, ait_label];
+{$endif JVM}
       var
         hp1, hp2: tai;
       begin
@@ -1624,12 +1633,7 @@ Unit AoptObj;
         }
         while GetNextInstruction(p, hp1) and                (hp1 BlockEnd) and
-              (hp1.typ ait_label)
-{$ifdef JVM}
-              and (hp1.typ ait_jcatch) -{$endif}
-              do
-          if not(hp1.typ in ([ait_label]+skipinstr)) then +              not (hp1.typ in TaiFence) do              begin
               if (hp1.typ = ait_instruction) and                   taicpu(hp1).is_jmp and @@ -1658,9 +1662,7 @@ Unit AoptObj;
                 end
               else
                 p:=hp1;
-            end
-          else
-            Break;
+            end;
       end;

     { If hp is a label, strip it if its reference count is zero.  Repeat until

Gareth aka. Kit

This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus

Reply by email