Browse Source

+ implementation of raise and try..finally
+ some misc. exception stuff

florian 27 years ago
parent
commit
25b34c1c6c
6 changed files with 174 additions and 21 deletions
  1. 119 8
      compiler/cg386flw.pas
  2. 10 3
      compiler/cgi386.pas
  3. 7 1
      compiler/hcodegen.pas
  4. 19 1
      compiler/pass_1.pas
  5. 6 2
      compiler/pexpr.pas
  6. 13 6
      compiler/pstatmnt.pas

+ 119 - 8
compiler/cg386flw.pas

@@ -484,6 +484,7 @@ do_jmp:
 *****************************************************************************}
 *****************************************************************************}
 
 
     procedure secondgoto(var p : ptree);
     procedure secondgoto(var p : ptree);
+
        begin
        begin
          emitl(A_JMP,p^.labelnr);
          emitl(A_JMP,p^.labelnr);
        end;
        end;
@@ -506,8 +507,10 @@ do_jmp:
 *****************************************************************************}
 *****************************************************************************}
 
 
     procedure secondraise(var p : ptree);
     procedure secondraise(var p : ptree);
+
       var
       var
          a : plabel;
          a : plabel;
+
       begin
       begin
          if assigned(p^.left) then
          if assigned(p^.left) then
            begin
            begin
@@ -515,13 +518,13 @@ do_jmp:
               if assigned(p^.right) then
               if assigned(p^.right) then
                 begin
                 begin
                    secondpass(p^.right);
                    secondpass(p^.right);
-                       if codegenerror then
-                          exit;
+                   if codegenerror then
+                     exit;
                 end
                 end
               else
               else
-                        begin
+                begin
                    getlabel(a);
                    getlabel(a);
-                           emitl(A_LABEL,a);
+                   emitl(A_LABEL,a);
                    exprasmlist^.concat(new(pai386,
                    exprasmlist^.concat(new(pai386,
                      op_csymbol(A_PUSH,S_L,newcsymbol(lab2str(a),0))));
                      op_csymbol(A_PUSH,S_L,newcsymbol(lab2str(a),0))));
                 end;
                 end;
@@ -536,10 +539,12 @@ do_jmp:
                        p^.left^.location.register)));
                        p^.left^.location.register)));
                  else Message(sym_e_type_mismatch);
                  else Message(sym_e_type_mismatch);
               end;
               end;
-                 emitcall('DO_RAISE',true);
+              emitcall('FPC_RAISEEXCEPTION',true);
              end
              end
            else
            else
-             emitcall('DO_RERAISE',true);
+             begin
+                emitcall('FPC_RERAISE',true);
+             end;
        end;
        end;
 
 
 
 
@@ -548,16 +553,118 @@ do_jmp:
 *****************************************************************************}
 *****************************************************************************}
 
 
     procedure secondtryexcept(var p : ptree);
     procedure secondtryexcept(var p : ptree);
+
+      var
+         exceptlabel,doexceptlabel,endexceptlabel,
+         nextonlabel,lastonlabel : plabel;
+
       begin
       begin
-      end;
+         { we modify EAX }
+         usedinproc:=usedinproc or ($80 shr byte(R_EAX));
+
+         getlabel(exceptlabel);
+         getlabel(doexceptlabel);
+         getlabel(endexceptlabel);
+         getlabel(lastonlabel);
+         emitcall('FPC_PUSHEXCEPTADDR',true);
+         exprasmlist^.concat(new(pai386,
+           op_reg(A_PUSH,S_L,R_EAX)));
+         emitcall('FPC_SETJMP',true);
+         exprasmlist^.concat(new(pai386,
+           op_reg(A_PUSH,S_L,R_EAX)));
+         exprasmlist^.concat(new(pai386,
+           op_reg_reg(A_TEST,S_L,R_EAX,R_EAX)));
+         emitl(A_JNE,exceptlabel);
+
+         { try code }
+         secondpass(p^.left);
+         if codegenerror then
+           exit;
+
+         emitl(A_LABEL,exceptlabel);
+         exprasmlist^.concat(new(pai386,
+           op_reg(A_POP,S_L,R_EAX)));
+         exprasmlist^.concat(new(pai386,
+           op_reg_reg(A_TEST,S_L,R_EAX,R_EAX)));
+         emitl(A_JNE,doexceptlabel);
+         emitcall('FPC_POPADDRSTACK',true);
+         emitl(A_JMP,endexceptlabel);
+         emitl(A_LABEL,doexceptlabel);
+
+         { for each object: }
+         while false do
+           begin
+              getlabel(nextonlabel);
+           end;
+{
+for each 'on object' do :
+----------------
+
+pushl objectclass;  // pass object class, or -1 if no class specified.
+call FPC_CATCHES    // Does this object tacth the exception ?
+testl %eax,%eax
+je .nexton          // No, jump to next on...
+... code for on handler...
+.nexton
+...
+}
+         emitl(A_LABEL,lastonlabel);
+         { default handling }
+         if assigned(p^.t1) then
+           secondpass(p^.t1)
+         else
+           emitcall('FPC_RERAISE',true);
+         emitl(A_LABEL,endexceptlabel);
 
 
+      end;
 
 
 {*****************************************************************************
 {*****************************************************************************
                              SecondTryFinally
                              SecondTryFinally
 *****************************************************************************}
 *****************************************************************************}
 
 
     procedure secondtryfinally(var p : ptree);
     procedure secondtryfinally(var p : ptree);
+
+      var
+         finallylabel,noreraiselabel,endfinallylabel : plabel;
+
       begin
       begin
+         { we modify EAX }
+         usedinproc:=usedinproc or ($80 shr byte(R_EAX));
+
+         getlabel(finallylabel);
+         getlabel(noreraiselabel);
+         getlabel(endfinallylabel);
+         emitcall('FPC_PUSHEXCEPTADDR',true);
+         exprasmlist^.concat(new(pai386,
+           op_reg(A_PUSH,S_L,R_EAX)));
+         emitcall('FPC_SETJMP',true);
+         exprasmlist^.concat(new(pai386,
+           op_reg(A_PUSH,S_L,R_EAX)));
+         exprasmlist^.concat(new(pai386,
+           op_reg_reg(A_TEST,S_L,R_EAX,R_EAX)));
+         emitl(A_JNE,finallylabel);
+
+         { try code }
+         secondpass(p^.left);
+         if codegenerror then
+           exit;
+
+         emitl(A_LABEL,finallylabel);
+
+         { finally code }
+         secondpass(p^.right);
+         if codegenerror then
+           exit;
+         exprasmlist^.concat(new(pai386,
+           op_reg(A_POP,S_L,R_EAX)));
+         exprasmlist^.concat(new(pai386,
+           op_reg_reg(A_TEST,S_L,R_EAX,R_EAX)));
+         emitl(A_JE,noreraiselabel);
+         emitcall('FPC_RERAISE',true);
+         emitl(A_JMP,endfinallylabel);
+         emitl(A_LABEL,noreraiselabel);
+         emitcall('FPC_POPADDRSTACK',true);
+         emitl(A_LABEL,endfinallylabel);
       end;
       end;
 
 
 
 
@@ -590,7 +697,11 @@ do_jmp:
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.4  1998-07-24 22:16:53  florian
+  Revision 1.5  1998-07-28 21:52:49  florian
+    + implementation of raise and try..finally
+    + some misc. exception stuff
+
+  Revision 1.4  1998/07/24 22:16:53  florian
     * internal error 10 together with array access fixed. I hope
     * internal error 10 together with array access fixed. I hope
       that's the final fix.
       that's the final fix.
 
 

+ 10 - 3
compiler/cgi386.pas

@@ -316,15 +316,17 @@ implementation
            end;
            end;
       end;
       end;
 
 
-
     procedure generatecode(var p : ptree);
     procedure generatecode(var p : ptree);
+
       var
       var
          i       : longint;
          i       : longint;
          regsize : topsize;
          regsize : topsize;
          regi    : tregister;
          regi    : tregister;
          hr      : preference;
          hr      : preference;
+
       label
       label
          nextreg;
          nextreg;
+
       begin
       begin
          cleartempgen;
          cleartempgen;
          { when size optimization only count occurrence }
          { when size optimization only count occurrence }
@@ -353,8 +355,9 @@ implementation
            begin
            begin
               { max. optimizations     }
               { max. optimizations     }
               { only if no asm is used }
               { only if no asm is used }
+              { and no try statement   }
               if (cs_maxoptimieren in aktswitches) and
               if (cs_maxoptimieren in aktswitches) and
-                ((procinfo.flags and pi_uses_asm)=0) then
+                ((procinfo.flags and (pi_uses_asm or pi_uses_exceptions))=0) then
                 begin
                 begin
                    { can we omit the stack frame ? }
                    { can we omit the stack frame ? }
                    { conditions:
                    { conditions:
@@ -502,7 +505,11 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.42  1998-07-15 16:06:44  jonas
+  Revision 1.43  1998-07-28 21:52:50  florian
+    + implementation of raise and try..finally
+    + some misc. exception stuff
+
+  Revision 1.42  1998/07/15 16:06:44  jonas
   * fixed bug that caused the stackframe never to be omitted
   * fixed bug that caused the stackframe never to be omitted
 
 
   Revision 1.41  1998/07/14 14:46:44  peter
   Revision 1.41  1998/07/14 14:46:44  peter

+ 7 - 1
compiler/hcodegen.pas

@@ -40,6 +40,8 @@ unit hcodegen;
        pi_do_call   = $4;       { set, if the procedure does a call }
        pi_do_call   = $4;       { set, if the procedure does a call }
        pi_operator  = $8;       { set, if the procedure is an operator   }
        pi_operator  = $8;       { set, if the procedure is an operator   }
        pi_C_import  = $10;      { set, if the procedure is an external C function }
        pi_C_import  = $10;      { set, if the procedure is an external C function }
+       pi_uses_exceptions = $20;{ set, if the procedure has a try statement => }
+                                { no register variables                        }
 
 
     type
     type
        pprocinfo = ^tprocinfo;
        pprocinfo = ^tprocinfo;
@@ -403,7 +405,11 @@ end.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.10  1998-07-20 18:40:13  florian
+  Revision 1.11  1998-07-28 21:52:51  florian
+    + implementation of raise and try..finally
+    + some misc. exception stuff
+
+  Revision 1.10  1998/07/20 18:40:13  florian
     * handling of ansi string constants should now work
     * handling of ansi string constants should now work
 
 
   Revision 1.9  1998/06/05 16:13:34  pierre
   Revision 1.9  1998/06/05 16:13:34  pierre

+ 19 - 1
compiler/pass_1.pas

@@ -4769,6 +4769,20 @@ unit pass_1;
     procedure firsttryfinally(var p : ptree);
     procedure firsttryfinally(var p : ptree);
 
 
       begin
       begin
+         cleartempgen;
+         must_be_valid:=true;
+         firstpass(p^.left);
+
+         cleartempgen;
+         must_be_valid:=true;
+         firstpass(p^.right);
+         if codegenerror then
+           exit;
+         p^.registers32:=max(p^.left^.registers32,p^.right^.registers32);
+         p^.registersfpu:=max(p^.left^.registersfpu,p^.right^.registersfpu);
+{$ifdef SUPPORT_MMX}
+         p^.registersmmx:=max(p^.left^.registersmmx,p^.right^.registersmmx);
+{$endif SUPPORT_MMX}
       end;
       end;
 
 
     procedure firstis(var p : ptree);
     procedure firstis(var p : ptree);
@@ -5100,7 +5114,11 @@ unit pass_1;
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.45  1998-07-26 21:58:59  florian
+  Revision 1.46  1998-07-28 21:52:52  florian
+    + implementation of raise and try..finally
+    + some misc. exception stuff
+
+  Revision 1.45  1998/07/26 21:58:59  florian
    + better support for switch $H
    + better support for switch $H
    + index access to ansi strings added
    + index access to ansi strings added
    + assigment of data (records/arrays) containing ansi strings
    + assigment of data (records/arrays) containing ansi strings

+ 6 - 2
compiler/pexpr.pas

@@ -683,7 +683,7 @@ unit pexpr;
       procedure postfixoperators;
       procedure postfixoperators;
 
 
         begin
         begin
-             check_tokenpos;
+           check_tokenpos;
            while again do
            while again do
              begin
              begin
                 case token of
                 case token of
@@ -1788,7 +1788,11 @@ unit pexpr;
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.29  1998-07-27 21:57:13  florian
+  Revision 1.30  1998-07-28 21:52:54  florian
+    + implementation of raise and try..finally
+    + some misc. exception stuff
+
+  Revision 1.29  1998/07/27 21:57:13  florian
     * fix to allow tv like stream registration:
     * fix to allow tv like stream registration:
         @tmenu.load doesn't work if load had parameters or if load was only
         @tmenu.load doesn't work if load had parameters or if load was only
         declared in an anchestor class of tmenu
         declared in an anchestor class of tmenu

+ 13 - 6
compiler/pstatmnt.pas

@@ -483,6 +483,9 @@ unit pstatmnt;
          old_in_except_block : boolean;
          old_in_except_block : boolean;
 
 
       begin
       begin
+         procinfo.flags:=procinfo.flags or
+           pi_uses_exceptions;
+
          p_default:=nil;
          p_default:=nil;
          p_specific:=nil;
          p_specific:=nil;
 
 
@@ -541,11 +544,11 @@ unit pstatmnt;
                           { !!!!! }
                           { !!!!! }
                        end;
                        end;
                      consume(_DO);
                      consume(_DO);
-                                         statement;
-                                         if token<>SEMICOLON then
-                                           break;
-                                         emptystats;
-                                   until false;
+                     statement;
+                     if token<>SEMICOLON then
+                       break;
+                     emptystats;
+                   until false;
                    if token=_ELSE then
                    if token=_ELSE then
                      { catch the other exceptions }
                      { catch the other exceptions }
                      begin
                      begin
@@ -1168,7 +1171,11 @@ unit pstatmnt;
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.26  1998-07-27 21:57:14  florian
+  Revision 1.27  1998-07-28 21:52:55  florian
+    + implementation of raise and try..finally
+    + some misc. exception stuff
+
+  Revision 1.26  1998/07/27 21:57:14  florian
     * fix to allow tv like stream registration:
     * fix to allow tv like stream registration:
         @tmenu.load doesn't work if load had parameters or if load was only
         @tmenu.load doesn't work if load had parameters or if load was only
         declared in an anchestor class of tmenu
         declared in an anchestor class of tmenu