浏览代码

* genlinear(cmp)list can now be overridden by descendents

Jonas Maebe 23 年之前
父节点
当前提交
3446f05f12
共有 1 个文件被更改,包括 191 次插入180 次删除
  1. 191 180
      compiler/ncgset.pas

+ 191 - 180
compiler/ncgset.pas

@@ -27,7 +27,7 @@ unit ncgset;
 interface
 interface
 
 
     uses
     uses
-       node,nset,cpubase,cginfo,cgbase,cgobj,aasmbase,aasmtai;
+       node,nset,cpubase,cginfo,cgbase,cgobj,aasmbase,aasmtai,globals;
 
 
     type
     type
        tcgsetelementnode = class(tsetelementnode)
        tcgsetelementnode = class(tsetelementnode)
@@ -56,6 +56,23 @@ interface
             because of portability problems.
             because of portability problems.
           }
           }
           procedure pass_2;override;
           procedure pass_2;override;
+
+        protected
+
+          procedure genlinearlist(hp : pcaserecord); virtual;
+          procedure genlinearcmplist(hp : pcaserecord); virtual;
+
+          with_sign : boolean;
+          opsize : tcgsize;
+          jmp_gt,jmp_lt,jmp_le : topcmp;
+          { register with case expression }
+          hregister,hregister2 : tregister;
+          endlabel,elselabel : tasmlabel;
+
+          { true, if we can omit the range check of the jump table }
+          jumptable_no_range : boolean;
+          min_label : tconstexprint;
+
        end;
        end;
 
 
 
 
@@ -63,7 +80,7 @@ implementation
 
 
     uses
     uses
       globtype,systems,
       globtype,systems,
-      verbose,globals,
+      verbose,
       symconst,symdef,defbase,
       symconst,symdef,defbase,
       paramgr,
       paramgr,
       pass_2,
       pass_2,
@@ -572,19 +589,175 @@ implementation
                             TCGCASENODE
                             TCGCASENODE
 *****************************************************************************}
 *****************************************************************************}
 
 
-    procedure tcgcasenode.pass_2;
+    procedure tcgcasenode.genlinearlist(hp : pcaserecord);
+
       var
       var
-         with_sign : boolean;
-         opsize : tcgsize;
-         jmp_gt,jmp_lt,jmp_le : topcmp;
-         hp : tnode;
-         { register with case expression }
-         hregister,hregister2 : tregister;
-         endlabel,elselabel : tasmlabel;
+         first : boolean;
+         last : TConstExprInt;
+         scratch_reg: tregister;
+
+      procedure genitem(t : pcaserecord);
 
 
-         { true, if we can omit the range check of the jump table }
-         jumptable_no_range : boolean;
-         min_label : tconstexprint;
+          procedure gensub(value:longint);
+          begin
+            { here, since the sub and cmp are separate we need
+              to move the result before subtract to a help
+              register.
+            }
+            cg.a_load_reg_reg(exprasmlist, opsize, hregister, scratch_reg);
+            cg.a_op_const_reg(exprasmlist, OP_SUB, value, hregister);
+          end;
+
+        begin
+           if assigned(t^.less) then
+             genitem(t^.less);
+           { need we to test the first value }
+           if first and (t^._low>get_min_value(left.resulttype.def)) then
+             begin
+                cg.a_cmp_const_reg_label(exprasmlist,OS_INT,jmp_lt,longint(t^._low),hregister,elselabel);
+             end;
+           if t^._low=t^._high then
+             begin
+                if t^._low-last=0 then
+                  begin
+                    cg.a_cmp_const_reg_label(exprasmlist, OS_INT, OC_EQ,0,hregister,t^.statement);
+                  end
+                else
+                  begin
+                      gensub(longint(t^._low-last));
+                      cg.a_cmp_const_reg_label(exprasmlist, OS_INT, OC_EQ,longint(t^._low-last),scratch_reg,t^.statement);
+                  end;
+                last:=t^._low;
+             end
+           else
+             begin
+                { it begins with the smallest label, if the value }
+                { is even smaller then jump immediately to the    }
+                { ELSE-label                                }
+                if first then
+                  begin
+                     { have we to ajust the first value ? }
+                     if (t^._low>get_min_value(left.resulttype.def)) then
+                       gensub(longint(t^._low));
+                  end
+                else
+                  begin
+                    { if there is no unused label between the last and the }
+                    { present label then the lower limit can be checked    }
+                    { immediately. else check the range in between:       }
+                    gensub(longint(t^._low-last));
+                    cg.a_cmp_const_reg_label(exprasmlist, OS_INT,jmp_lt,longint(t^._low-last),scratch_reg,elselabel);
+                  end;
+                gensub(longint(t^._high-t^._low));
+                cg.a_cmp_const_reg_label(exprasmlist, OS_INT,jmp_le,longint(t^._high-t^._low),scratch_reg,t^.statement);
+                last:=t^._high;
+             end;
+           first:=false;
+           if assigned(t^.greater) then
+             genitem(t^.greater);
+        end;
+
+      begin
+         { do we need to generate cmps? }
+         if (with_sign and (min_label<0)) then
+           genlinearcmplist(hp)
+         else
+           begin
+              last:=0;
+              first:=true;
+              scratch_reg := cg.get_scratch_reg_int(exprasmlist);
+              genitem(hp);
+              cg.free_scratch_reg(exprasmlist,scratch_reg);
+              cg.a_jmp_always(exprasmlist,elselabel);
+           end;
+      end;
+
+
+    procedure tcgcasenode.genlinearcmplist(hp : pcaserecord);
+
+      var
+         first : boolean;
+         last : TConstExprInt;
+
+      procedure genitem(t : pcaserecord);
+
+        var
+           l1 : tasmlabel;
+
+        begin
+           if assigned(t^.less) then
+             genitem(t^.less);
+           if t^._low=t^._high then
+             begin
+                if opsize in [OS_S64,OS_64] then
+                  begin
+                     getlabel(l1);
+                     cg.a_cmp_const_reg_label(exprasmlist, OS_INT, OC_NE, longint(hi(int64(t^._low))),hregister2,l1);
+                     cg.a_cmp_const_reg_label(exprasmlist, OS_INT, OC_EQ, longint(lo(int64(t^._low))),hregister, t^.statement);
+                     cg.a_label(exprasmlist,l1);
+                  end
+                else
+                  begin
+                     cg.a_cmp_const_reg_label(exprasmlist, OS_INT, OC_EQ, longint(t^._low),hregister, t^.statement);
+                     last:=t^._low;
+                  end;
+             end
+           else
+             begin
+                { it begins with the smallest label, if the value }
+                { is even smaller then jump immediately to the    }
+                { ELSE-label                                }
+                if first or (t^._low-last>1) then
+                  begin
+                     if opsize in [OS_64,OS_S64] then
+                       begin
+                          getlabel(l1);
+                          cg.a_cmp_const_reg_label(exprasmlist, OS_INT, jmp_lt, longint(hi(int64(t^._low))),
+                               hregister2, elselabel);
+                          cg.a_cmp_const_reg_label(exprasmlist, OS_INT, jmp_gt, longint(hi(int64(t^._low))),
+                               hregister2, l1);
+                          { the comparisation of the low dword must be always unsigned! }
+                          cg.a_cmp_const_reg_label(exprasmlist, OS_INT, OC_B, longint(lo(int64(t^._low))), hregister, elselabel);
+                          cg.a_label(exprasmlist,l1);
+                       end
+                     else
+                       begin
+                        cg.a_cmp_const_reg_label(exprasmlist, OS_INT, jmp_lt, longint(t^._low), hregister,
+                           elselabel);
+                       end;
+                  end;
+
+                if opsize in [OS_S64,OS_64] then
+                  begin
+                     getlabel(l1);
+                     cg.a_cmp_const_reg_label(exprasmlist, OS_INT, jmp_lt, longint(hi(int64(t^._high))), hregister2,
+                           t^.statement);
+                     cg.a_cmp_const_reg_label(exprasmlist, OS_INT, jmp_gt, longint(hi(int64(t^._high))), hregister2,
+                           l1);
+                    cg.a_cmp_const_reg_label(exprasmlist, OS_INT, OC_BE, longint(lo(int64(t^._high))), hregister, t^.statement);
+                    cg.a_label(exprasmlist,l1);
+                  end
+                else
+                  begin
+                     cg.a_cmp_const_reg_label(exprasmlist, OS_INT, jmp_le, longint(t^._high), hregister, t^.statement);
+                  end;
+
+                last:=t^._high;
+             end;
+           first:=false;
+           if assigned(t^.greater) then
+             genitem(t^.greater);
+        end;
+
+      begin
+         last:=0;
+         first:=true;
+         genitem(hp);
+         cg.a_jmp_always(exprasmlist,elselabel);
+      end;
+
+
+    procedure tcgcasenode.pass_2;
 
 
       procedure gentreejmp(p : pcaserecord);
       procedure gentreejmp(p : pcaserecord);
 
 
@@ -629,172 +802,6 @@ implementation
            gentreejmp(p^.greater);
            gentreejmp(p^.greater);
       end;
       end;
 
 
-      procedure genlinearcmplist(hp : pcaserecord);
-
-        var
-           first : boolean;
-           last : TConstExprInt;
-
-        procedure genitem(t : pcaserecord);
-
-          var
-             l1 : tasmlabel;
-
-          begin
-             if assigned(t^.less) then
-               genitem(t^.less);
-             if t^._low=t^._high then
-               begin
-                  if opsize in [OS_S64,OS_64] then
-                    begin
-                       getlabel(l1);
-                       cg.a_cmp_const_reg_label(exprasmlist, OS_INT, OC_NE, longint(hi(int64(t^._low))),hregister2,l1);
-                       cg.a_cmp_const_reg_label(exprasmlist, OS_INT, OC_EQ, longint(lo(int64(t^._low))),hregister, t^.statement);
-                       cg.a_label(exprasmlist,l1);
-                    end
-                  else
-                    begin
-                       cg.a_cmp_const_reg_label(exprasmlist, OS_INT, OC_EQ, longint(t^._low),hregister, t^.statement);
-                       last:=t^._low;
-                    end;
-               end
-             else
-               begin
-                  { it begins with the smallest label, if the value }
-                  { is even smaller then jump immediately to the    }
-                  { ELSE-label                                }
-                  if first or (t^._low-last>1) then
-                    begin
-                       if opsize in [OS_64,OS_S64] then
-                         begin
-                            getlabel(l1);
-                            cg.a_cmp_const_reg_label(exprasmlist, OS_INT, jmp_lt, longint(hi(int64(t^._low))),
-                                 hregister2, elselabel);
-                            cg.a_cmp_const_reg_label(exprasmlist, OS_INT, jmp_gt, longint(hi(int64(t^._low))),
-                                 hregister2, l1);
-                            { the comparisation of the low dword must be always unsigned! }
-                            cg.a_cmp_const_reg_label(exprasmlist, OS_INT, OC_B, longint(lo(int64(t^._low))), hregister, elselabel);
-                            cg.a_label(exprasmlist,l1);
-                         end
-                       else
-                         begin
-                          cg.a_cmp_const_reg_label(exprasmlist, OS_INT, jmp_lt, longint(t^._low), hregister,
-                             elselabel);
-                         end;
-                    end;
-
-                  if opsize in [OS_S64,OS_64] then
-                    begin
-                       getlabel(l1);
-                       cg.a_cmp_const_reg_label(exprasmlist, OS_INT, jmp_lt, longint(hi(int64(t^._high))), hregister2,
-                             t^.statement);
-                       cg.a_cmp_const_reg_label(exprasmlist, OS_INT, jmp_gt, longint(hi(int64(t^._high))), hregister2,
-                             l1);
-                      cg.a_cmp_const_reg_label(exprasmlist, OS_INT, OC_BE, longint(lo(int64(t^._high))), hregister, t^.statement);
-                      cg.a_label(exprasmlist,l1);
-                    end
-                  else
-                    begin
-                       cg.a_cmp_const_reg_label(exprasmlist, OS_INT, jmp_le, longint(t^._high), hregister, t^.statement);
-                    end;
-
-                  last:=t^._high;
-               end;
-             first:=false;
-             if assigned(t^.greater) then
-               genitem(t^.greater);
-          end;
-
-        begin
-           last:=0;
-           first:=true;
-           genitem(hp);
-           cg.a_jmp_always(exprasmlist,elselabel);
-        end;
-
-      procedure genlinearlist(hp : pcaserecord);
-
-        var
-           first : boolean;
-           last : TConstExprInt;
-           scratch_reg: tregister;
-
-        procedure genitem(t : pcaserecord);
-
-            procedure gensub(value:longint);
-            begin
-              { here, since the sub and cmp are separate we need
-                to move the result before subtract to a help
-                register.
-              }
-              cg.a_load_reg_reg(exprasmlist, opsize, hregister, scratch_reg);
-              cg.a_op_const_reg(exprasmlist, OP_SUB, value, hregister);
-            end;
-
-          begin
-             if assigned(t^.less) then
-               genitem(t^.less);
-             { need we to test the first value }
-             if first and (t^._low>get_min_value(left.resulttype.def)) then
-               begin
-                  cg.a_cmp_const_reg_label(exprasmlist,OS_INT,jmp_lt,longint(t^._low),hregister,elselabel);
-               end;
-             if t^._low=t^._high then
-               begin
-                  if t^._low-last=0 then
-                    begin
-                      cg.a_cmp_const_reg_label(exprasmlist, OS_INT, OC_EQ,0,hregister,t^.statement);
-                    end
-                  else
-                    begin
-                        gensub(longint(t^._low-last));
-                        cg.a_cmp_const_reg_label(exprasmlist, OS_INT, OC_EQ,longint(t^._low-last),hregister,t^.statement);
-                    end;
-                  last:=t^._low;
-               end
-             else
-               begin
-                  { it begins with the smallest label, if the value }
-                  { is even smaller then jump immediately to the    }
-                  { ELSE-label                                }
-                  if first then
-                    begin
-                       { have we to ajust the first value ? }
-                       if (t^._low>get_min_value(left.resulttype.def)) then
-                         gensub(longint(t^._low));
-                    end
-                  else
-                    begin
-                      { if there is no unused label between the last and the }
-                      { present label then the lower limit can be checked    }
-                      { immediately. else check the range in between:       }
-                      gensub(longint(t^._low-last));
-                      cg.a_cmp_const_reg_label(exprasmlist, OS_INT,jmp_lt,longint(t^._low-last),hregister,elselabel);
-                    end;
-                  gensub(longint(t^._high-t^._low));
-                  cg.a_cmp_const_reg_label(exprasmlist, OS_INT,jmp_le,longint(t^._high-t^._low),hregister,t^.statement);
-                  last:=t^._high;
-               end;
-             first:=false;
-             if assigned(t^.greater) then
-               genitem(t^.greater);
-          end;
-
-        begin
-           { do we need to generate cmps? }
-           if (with_sign and (min_label<0)) then
-             genlinearcmplist(hp)
-           else
-             begin
-                last:=0;
-                first:=true;
-                scratch_reg := cg.get_scratch_reg_int(exprasmlist);
-                genitem(hp);
-                cg.free_scratch_reg(exprasmlist,scratch_reg);
-                cg.a_jmp_always(exprasmlist,elselabel);
-             end;
-        end;
-
 
 
       var
       var
          lv,hv,
          lv,hv,
@@ -804,6 +811,7 @@ implementation
          otl, ofl: tasmlabel;
          otl, ofl: tasmlabel;
          isjump : boolean;
          isjump : boolean;
          dist : cardinal;
          dist : cardinal;
+         hp : tnode;
       begin
       begin
          getlabel(endlabel);
          getlabel(endlabel);
          getlabel(elselabel);
          getlabel(elselabel);
@@ -949,7 +957,10 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.13  2002-08-11 06:14:40  florian
+  Revision 1.14  2002-08-11 11:37:42  jonas
+    * genlinear(cmp)list can now be overridden by descendents
+
+  Revision 1.13  2002/08/11 06:14:40  florian
     * fixed powerpc compilation problems
     * fixed powerpc compilation problems
 
 
   Revision 1.12  2002/08/10 17:15:12  jonas
   Revision 1.12  2002/08/10 17:15:12  jonas