Browse Source

* support exit,break,continue in try...except
* support break,continue in try...finally

peter 26 years ago
parent
commit
36710decd4
1 changed files with 101 additions and 18 deletions
  1. 101 18
      compiler/cg386flw.pas

+ 101 - 18
compiler/cg386flw.pas

@@ -599,7 +599,14 @@ do_jmp:
 
 
       var
       var
          exceptlabel,doexceptlabel,oldendexceptlabel,
          exceptlabel,doexceptlabel,oldendexceptlabel,
-         lastonlabel : pasmlabel;
+         lastonlabel,
+         exitexceptlabel,
+         continueexceptlabel,
+         breakexceptlabel,
+         oldaktexitlabel,
+         oldaktexit2label,
+         oldaktcontinuelabel,
+         oldaktbreaklabel : pasmlabel;
          oldexceptblock : ptree;
          oldexceptblock : ptree;
 
 
       begin
       begin
@@ -608,6 +615,18 @@ do_jmp:
          { we modify EAX }
          { we modify EAX }
          usedinproc:=usedinproc or ($80 shr byte(R_EAX));
          usedinproc:=usedinproc or ($80 shr byte(R_EAX));
 
 
+         oldaktcontinuelabel:=aktcontinuelabel;
+         oldaktbreaklabel:=aktbreaklabel;
+         oldaktexitlabel:=aktexitlabel;
+         oldaktexit2label:=aktexit2label;
+         getlabel(exitexceptlabel);
+         getlabel(breakexceptlabel);
+         getlabel(continueexceptlabel);
+         aktcontinuelabel:=continueexceptlabel;
+         aktbreaklabel:=breakexceptlabel;
+         aktexitlabel:=exitexceptlabel;
+         aktexit2label:=exitexceptlabel;
+
          getlabel(exceptlabel);
          getlabel(exceptlabel);
          getlabel(doexceptlabel);
          getlabel(doexceptlabel);
          getlabel(endexceptlabel);
          getlabel(endexceptlabel);
@@ -665,13 +684,35 @@ do_jmp:
            end
            end
          else
          else
            emitcall('FPC_RERAISE');
            emitcall('FPC_RERAISE');
-         { reraise doesn't need a maybe_loadesi because it never }
-         { returns (FK)                                          }
+
+         { do some magic for exit in the try block }
+         emitlab(exitexceptlabel);
+         emitcall('FPC_POPADDRSTACK');
+         emit_reg(A_POP,S_L,R_EAX);
+         emitjmp(C_None,oldaktexitlabel);
+
+         if assigned(oldaktbreaklabel) then
+          begin
+            emitlab(breakexceptlabel);
+            emitcall('FPC_POPADDRSTACK');
+            emit_reg(A_POP,S_L,R_EAX);
+            emitjmp(C_None,oldaktbreaklabel);
+          end;
+
+         if assigned(oldaktcontinuelabel) then
+          begin
+            emitlab(continueexceptlabel);
+            emitcall('FPC_POPADDRSTACK');
+            emit_reg(A_POP,S_L,R_EAX);
+            emitjmp(C_None,oldaktcontinuelabel);
+          end;
+
          emitlab(endexceptlabel);
          emitlab(endexceptlabel);
-         freelabel(exceptlabel);
-         freelabel(doexceptlabel);
-         freelabel(endexceptlabel);
-         freelabel(lastonlabel);
+
+         aktexitlabel:=oldaktexitlabel;
+         aktexit2label:=oldaktexit2label;
+         aktcontinuelabel:=oldaktcontinuelabel;
+         aktbreaklabel:=oldaktbreaklabel;
          endexceptlabel:=oldendexceptlabel;
          endexceptlabel:=oldendexceptlabel;
       end;
       end;
 
 
@@ -733,19 +774,33 @@ do_jmp:
     procedure secondtryfinally(var p : ptree);
     procedure secondtryfinally(var p : ptree);
 
 
       var
       var
-         finallylabel,noreraiselabel : pasmlabel;
-         oldaktexitlabel,exitfinallylabel : pasmlabel;
-         oldaktexit2label : pasmlabel;
+         reraiselabel,
+         finallylabel,
+         endfinallylabel,
+         exitfinallylabel,
+         continuefinallylabel,
+         breakfinallylabel,
+         oldaktexitlabel,
+         oldaktexit2label,
+         oldaktcontinuelabel,
+         oldaktbreaklabel : pasmlabel;
          oldexceptblock : ptree;
          oldexceptblock : ptree;
 
 
       begin
       begin
          { we modify EAX }
          { we modify EAX }
          usedinproc:=usedinproc or ($80 shr byte(R_EAX));
          usedinproc:=usedinproc or ($80 shr byte(R_EAX));
          getlabel(finallylabel);
          getlabel(finallylabel);
-         getlabel(noreraiselabel);
+         getlabel(endfinallylabel);
+         oldaktcontinuelabel:=aktcontinuelabel;
+         oldaktbreaklabel:=aktbreaklabel;
          oldaktexitlabel:=aktexitlabel;
          oldaktexitlabel:=aktexitlabel;
          oldaktexit2label:=aktexit2label;
          oldaktexit2label:=aktexit2label;
+         getlabel(reraiselabel);
          getlabel(exitfinallylabel);
          getlabel(exitfinallylabel);
+         getlabel(breakfinallylabel);
+         getlabel(continuefinallylabel);
+         aktcontinuelabel:=continuefinallylabel;
+         aktbreaklabel:=breakfinallylabel;
          aktexitlabel:=exitfinallylabel;
          aktexitlabel:=exitfinallylabel;
          aktexit2label:=exitfinallylabel;
          aktexit2label:=exitfinallylabel;
 
 
@@ -779,20 +834,44 @@ do_jmp:
            exit;
            exit;
          emit_reg(A_POP,S_L,R_EAX);
          emit_reg(A_POP,S_L,R_EAX);
          emit_reg_reg(A_TEST,S_L,R_EAX,R_EAX);
          emit_reg_reg(A_TEST,S_L,R_EAX,R_EAX);
-         emitjmp(C_E,noreraiselabel);
+         emitjmp(C_E,endfinallylabel);
+         emit_reg(A_DEC,S_L,R_EAX);
+         emitjmp(C_Z,reraiselabel);
          emit_reg(A_DEC,S_L,R_EAX);
          emit_reg(A_DEC,S_L,R_EAX);
-         emitjmp(C_NE,oldaktexitlabel);
+         emitjmp(C_Z,oldaktexitlabel);
+         if assigned(oldaktbreaklabel) then
+          begin
+            emit_reg(A_DEC,S_L,R_EAX);
+            emitjmp(C_Z,oldaktbreaklabel);
+            emit_reg(A_DEC,S_L,R_EAX);
+            emitjmp(C_Z,oldaktcontinuelabel);
+          end;
+         emitlab(reraiselabel);
          emitcall('FPC_RERAISE');
          emitcall('FPC_RERAISE');
-         { reraise never returns ! }
-         emitlab(exitfinallylabel);
 
 
-         { do some magic for exit in the try block }
+         { do some magic for exit,break,continue in the try block }
+         emitlab(exitfinallylabel);
          emit_reg(A_POP,S_L,R_EAX);
          emit_reg(A_POP,S_L,R_EAX);
          emit_const(A_PUSH,S_L,2);
          emit_const(A_PUSH,S_L,2);
          emitjmp(C_NONE,finallylabel);
          emitjmp(C_NONE,finallylabel);
-         emitlab(noreraiselabel);
+         if assigned(oldaktbreaklabel) then
+          begin
+            emitlab(breakfinallylabel);
+            emit_reg(A_POP,S_L,R_EAX);
+            emit_const(A_PUSH,S_L,3);
+            emitjmp(C_NONE,finallylabel);
+            emitlab(continuefinallylabel);
+            emit_reg(A_POP,S_L,R_EAX);
+            emit_const(A_PUSH,S_L,4);
+            emitjmp(C_NONE,finallylabel);
+          end;
+
+         emitlab(endfinallylabel);
+
          aktexitlabel:=oldaktexitlabel;
          aktexitlabel:=oldaktexitlabel;
          aktexit2label:=oldaktexit2label;
          aktexit2label:=oldaktexit2label;
+         aktcontinuelabel:=oldaktcontinuelabel;
+         aktbreaklabel:=oldaktbreaklabel;
       end;
       end;
 
 
 
 
@@ -809,7 +888,11 @@ do_jmp:
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.62  1999-12-17 11:20:06  florian
+  Revision 1.63  1999-12-19 17:02:45  peter
+    * support exit,break,continue in try...except
+    * support break,continue in try...finally
+
+  Revision 1.62  1999/12/17 11:20:06  florian
     * made the goto checking for excpetions more fool proof against errors
     * made the goto checking for excpetions more fool proof against errors
 
 
   Revision 1.61  1999/12/14 09:58:41  florian
   Revision 1.61  1999/12/14 09:58:41  florian