Recent

Author Topic: Unexpected/Inconsistent Overflow checking behavior  (Read 715 times)

440bx

  • Hero Member
  • *****
  • Posts: 1351
Unexpected/Inconsistent Overflow checking behavior
« on: January 03, 2020, 06:41:18 am »
Hello,

Overflow checking does not behave the same way when compiling for 32bit and 64bit.

In the following code:
Code: Pascal  [Select]
  1. var r : int32;
  2. begin
  3.   r := low(r);
  4.   writeln(r);
  5.  
  6.   r := -r;      // should cause an overflow
  7.   writeln(r);
  8. end.
When compiling for 32bit, the above will, as expected, report an overflow as a runtime error.  When compiling for 64bit, no overflow is reported and the value of "r" remains low(r); that is, it remains negative even though it was negated.

The inconsistency in 64bit seems related to the automatic promotion of "r" to a 64bit integer (which is unnecessary and unwarranted in this case.)
using FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

Leledumbo

  • Hero Member
  • *****
  • Posts: 8138
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: Unexpected/Inconsistent Overflow checking behavior
« Reply #1 on: January 04, 2020, 12:05:37 pm »
I got runtime error on both (3.3.1 svn about a week ago), but differing in the code. 32-bit gives me EIntOverflow: Arithmetic overflow (RTE 215), while 64-bit gives ERangeError: Range check error (RTE 201). That's with explicit -Cr given, otherwise none gives RTE. To be precise, this is targetting Linux, there's a chance it differs for other targets.

440bx

  • Hero Member
  • *****
  • Posts: 1351
Re: Unexpected/Inconsistent Overflow checking behavior
« Reply #2 on: January 04, 2020, 01:58:53 pm »
<snip> while 64-bit gives ERangeError: Range check error (RTE 201). That's with explicit -Cr given, otherwise none gives RTE.
IMO, that's a bit of a problem.  In 32bit, the overflow is detected just by enabling overflow checking whereas in 64bit, enabling overflow checking isn't enough even though it should be.

That makes the compiler's behavior inconsistent.  In one case (32bit), the overflow is detected by enabling overflow checking and in the other case (64bit) the overflow is detected only by enabling a different check, specifically, range checking.

Overflow checking should be enough in either bitness.  The inconsistency in 64bit is caused by the compiler unnecessarily promoting the 32bit integer to 64bit.

Thanks for testing the behavior on the trunk version.

using FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

ASerge

  • Hero Member
  • *****
  • Posts: 1432
Re: Unexpected/Inconsistent Overflow checking behavior
« Reply #3 on: January 04, 2020, 09:16:57 pm »
That makes the compiler's behavior inconsistent.  In one case (32bit), the overflow is detected by enabling overflow checking and in the other case (64bit) the overflow is detected only by enabling a different check, specifically, range checking.
Overflow checking should be enough in either bitness.
I agree. This is due to the implementation of the overflow check method.
Int64:
Code: ASM  [Select]
  1. # [12] R := -R;      // should cause an overflow
  2.         movslq  U_$P$PROGRAM_$$_R(%rip),%rbx
  3.         negq    %rbx
  4.         movq    $-9223372036854775808,%rax
  5.         cmpq    %rax,%rbx
  6.         jne     .Lj23
  7.         call    fpc_overflow
Int32:
Code: ASM  [Select]
  1. # [12] R := -R;      // should cause an overflow
  2.         movl    U_$P$PROGRAM_$$_R,%ebx
  3.         negl    %ebx
  4.         cmpl    $-2147483648,%ebx
  5.         jne     .Lj23
  6.         call    fpc_overflow
By the way, Delphi (32 or 64) always use such code:
Code: ASM  [Select]
  1. Project15.dpr.12: R := -R;      // should cause an overflow
  2.   neg dword ptr [$004278dc]
  3.   jno $0041f5d5
  4.   call @IntOver
Which outputs IntOverflow regardless of bitness.

440bx

  • Hero Member
  • *****
  • Posts: 1351
Re: Unexpected/Inconsistent Overflow checking behavior
« Reply #4 on: January 04, 2020, 09:49:19 pm »
By the way, Delphi (32 or 64) always use such code:
Code: ASM  [Select]
  1. Project15.dpr.12: R := -R;      // should cause an overflow
  2.   neg dword ptr [$004278dc]
  3.   jno $0041f5d5
  4.   call @IntOver
Which outputs IntOverflow regardless of bitness.
Delphi's method is the inherently correct way of checking for and handling an overflow.
using FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

Zoran

  • Hero Member
  • *****
  • Posts: 1473
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: Unexpected/Inconsistent Overflow checking behavior
« Reply #5 on: January 05, 2020, 07:02:58 am »
Please report in bugtracker.

440bx

  • Hero Member
  • *****
  • Posts: 1351
Re: Unexpected/Inconsistent Overflow checking behavior
« Reply #6 on: January 05, 2020, 07:39:24 am »
Please report in bugtracker.
The reason I didn't is because I'm not sure the FPC developers will consider it a bug.  My guess is, they'll simply say to use range checking in addition to overflow checking.

That said, if one of the developers considers it a bug, I'll gladly report it as such.
using FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

Zoran

  • Hero Member
  • *****
  • Posts: 1473
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: Unexpected/Inconsistent Overflow checking behavior
« Reply #7 on: January 05, 2020, 02:57:09 pm »
Please report in bugtracker.
The reason I didn't is because I'm not sure the FPC developers will consider it a bug.  My guess is, they'll simply say to use range checking in addition to overflow checking.

That said, if one of the developers considers it a bug, I'll gladly report it as such.

Please, don't be afraid to report a possible bug. If you report it in the forum only, there is a big chance the developers will never see this discussion and it will just get lost.

If they have the opinion that it is not a bug, one of them will take the bug report, explain why they do not consider it a bug and resolve it as "no change required".

I don't think that they will just reject this.
Anyway, reporting it will certainly do no harm.