[fpc-devel] Progress on pure functions

J. Gareth Moreton gareth at moreton-family.com
Wed Aug 16 06:05:38 CEST 2023


Fixed my problem with the recursive function (enabling range check and 
overflow errors blocked dead-store elimination, so I worked around that) 
and the warning no longer cascades.  Progress is being made!

Kit

On 16/08/2023 04:02, J. Gareth Moreton via fpc-devel wrote:
> So managed to stop the cascade in a fairly clean way (it detects the 
> difference in ErrorCount, marks the call node as erroneous and flags 
> "codegenerror"), and it seems to work.
>
> pure1a.pp(15,24) Error: Range check error while evaluating constants 
> (6227020800 must be between -2147483648 and 2147483647)
> pure1a.pp(15,24) Error: At least 1 error(s) occurred during the purity 
> analysis of subroutine "Factorial".
> pure1a.pp(17) Fatal: There were 2 errors compiling module, stopping
> Fatal: Compilation aborted
>
> The message says "at least X error(s)" because other errors may get 
> masked.
>
> My recursive version of the factorial function doesn't quite simplify 
> properly yet (it compiles successfully, but the call is a regular call 
> and a warning is generated):
>
> pure1b.pp(15,23) Warning: Subroutine "Factorial" is not eligible to be 
> a pure function due to the following reason: analysis did not produce 
> simple assignment.
>
> Being a warning, this cascades and is generated multiple times (the 
> number of times depends on how deep the recursion goes). I'll work on 
> suppressing the cascade too since when this warning is triggered, the 
> "pure" flag is removed from the subroutine.
>
> Currently the "analysis did not produce simple assignment" part is a 
> hard-coded string and not a part of errore.msg, for exmaple, so there 
> may need to be a way to adapt this to be multi-lingual.
>
> Kit
>
> On 12/08/2023 18:14, J. Gareth Moreton via fpc-devel wrote:
>> Hi everyone,
>>
>> So I'm still working on pure functions and have pushed some merge 
>> requests that are indirectly related to it, mostly simplifying the 
>> node tree so it can more easily be collapsed into simple assignments 
>> (what pure functions should simplify to).  Negative testing is still 
>> limited, but I have stumbled across one potential problem.  Using the 
>> following code example:
>>
>> program pure1a;
>> {$MODE OBJFPC}
>> {$COPERATORS ON}
>>
>> function Factorial(N: Cardinal): Cardinal; pure;
>>   var
>>     X: Integer;
>>   begin
>>     Result := 1;
>>     for X := N downto 2 do
>>       Result *= X;
>>   end;
>>
>> begin
>>   WriteLn(Factorial(32));
>> end.
>>
>> For those not familiar with the factorial function, the result 
>> increases in value very quickly to the point that 13! > 2^32 
>> (LongWord), 21! > 2^64 (QWord) and 70! > 10^100 (a googol), so 32! is 
>> guaranteed to overflow.
>>
>> Having not really handled this eventuality just yet, I decided to see 
>> what happens when the compiler runs it as is:
>>
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (6227020800 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (27048749056 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (19184179200 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (32068960256 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (34071216128 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (-288522240 must be between 0 and 4294967295)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (4006445056 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (-5193400320 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (-898433024 must be between 0 and 4294967295)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (3396534272 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (-17070227456 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (-2102132736 must be between 0 and 4294967295)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (2192834560 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (-44144787456 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (-1195114496 must be between 0 and 4294967295)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (3099852800 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (-26292518912 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (-522715136 must be between 0 and 4294967295)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (3772252160 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (-12022448128 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (20698890240 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (-775946240 must be between 0 and 4294967295)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (3519021056 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (-19398656000 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (53980692480 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (-1853882368 must be between 0 and 4294967295)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (2441084928 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (-50054823936 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (41573941248 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (-1375731712 must be between 0 and 4294967295)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (2919235584 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (-39896219648 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (-1241513984 must be between 0 and 4294967295)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (3053453312 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (-37245419520 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (43687870464 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (23622320128 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Warning: Range check error while evaluating 
>> constants (-2147483648 must be between 0 and 4294967295)
>>
>> Not an ideal cascade of warnings.  I figured it might be better to 
>> throw an error instead, so during the processing of pure functions, I 
>> enforced range and overflow checking:
>>
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (6227020800 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (27048749056 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (19184179200 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (32068960256 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (34071216128 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (-288522240 must be between 0 and 4294967295)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (4006445056 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (-5193400320 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (-898433024 must be between 0 and 4294967295)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (3396534272 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (-17070227456 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (2192834560 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (-2102132736 must be between 0 and 4294967295)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (2192834560 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (-44144787456 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (-1195114496 must be between 0 and 4294967295)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (3099852800 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (-26292518912 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (-522715136 must be between 0 and 4294967295)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (3772252160 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (-12022448128 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (20698890240 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (-775946240 must be between 0 and 4294967295)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (3519021056 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (-19398656000 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (53980692480 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (-1853882368 must be between 0 and 4294967295)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (2441084928 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (-50054823936 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (41573941248 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (-1375731712 must be between 0 and 4294967295)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (2919235584 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (-39896219648 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (-1241513984 must be between 0 and 4294967295)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (3053453312 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (-37245419520 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (43687870464 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (23622320128 must be between -2147483648 and 2147483647)
>> pure1a.pp(15,24) Error: Range check error while evaluating constants 
>> (-2147483648 must be between 0 and 4294967295)
>> pure1a.pp(17) Fatal: There were 39 errors compiling module, stopping
>> Fatal: Compilation aborted
>>
>> This is not much better and is very unhelpful and untidy in an error 
>> log.  Since the node tree is expanded during pure function analysis 
>> (in this case, the for-loop is unrolled) and each node points to the 
>> function call, each compiler message thus points here.  Ideally there 
>> should only be one warning/error message, but since these messages 
>> are generated elsewhere in the node compilation process, it's not 
>> that easy to catch it and drop out the instant an error is thrown.
>>
>> So to ask.  If during analysis an overflow/range check error occurs, 
>> how do you think it should be handled? And does anyone have tips on 
>> how to program the compiler to immediately stop processing if a 
>> single error is found or to otherwise suppress subsequent messages 
>> that point to the same file location?
>>
>> Kit
>>
>> _______________________________________________
>> fpc-devel maillist  -  fpc-devel at lists.freepascal.org
>> https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
>>
> _______________________________________________
> fpc-devel maillist  -  fpc-devel at lists.freepascal.org
> https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
>


More information about the fpc-devel mailing list