Ver código fonte

* RiscV 32: overflow checking for unary minus

florian 2 dias atrás
pai
commit
836a08bfe1
2 arquivos alterados com 21 adições e 1 exclusões
  1. 10 1
      compiler/riscv/cgrv.pas
  2. 11 0
      tests/tbs/tb0162.pp

+ 10 - 1
compiler/riscv/cgrv.pas

@@ -235,7 +235,7 @@ unit cgrv;
         tmpreg1, tmpreg2: TRegister;
       begin
         if setflags and
-          { do we know overflow checking for this operation? fix me! }(size in [OS_32,OS_S32]) and (op in [OP_ADD,OP_SUB,OP_MUL,OP_IMUL,OP_IDIV]) then
+          { do we know overflow checking for this operation? fix me! }(size in [OS_32,OS_S32]) and (op in [OP_ADD,OP_SUB,OP_MUL,OP_IMUL,OP_IDIV,OP_NEG]) then
           begin
             ovloc.loc:=LOC_JUMP;
             current_asmdata.getjumplabel(ovloc.truelabel);
@@ -251,6 +251,15 @@ unit cgrv;
         else if op=OP_NEG then
           begin
             list.concat(taicpu.op_reg_reg_reg(A_SUB,dst,NR_X0,src1));
+
+            if setflags then
+              begin
+                { if dst and src are equal, an overflow happened }
+                a_cmp_reg_reg_label(list,OS_INT,OC_NE,dst,src1,ovloc.falselabel);
+
+                a_jmp_always(list,ovloc.truelabel);
+              end;
+
             maybeadjustresult(list,op,size,dst);
           end
         else

+ 11 - 0
tests/tbs/tb0162.pp

@@ -90,6 +90,17 @@ begin
       doerror(10);
   end;
 
+  l := low(longint);
+  try
+    l := -l;
+    doerror(109);
+  except
+    on eintoverflow do
+      ;
+    else
+      doerror(110);
+  end;
+
   c := high(cardinal);
   try
     c := c+1;