Skip to content

Optimization -OoRegVar will cause anonymous function captures of variables and parameters to fail with "Internal error 200409241"

Summary

Capturing local variables and parameters fails with -OoRegVar

Alright, I know, a closure capture of a register makes no sense.

However, failing with "Internal error 200409241" does not indicate what the problem is and I had to go through my optimizer options to find the offending one.

System Information

  • Operating system: Linux (ArchLinux)
  • Processor architecture: x86_64
  • Compiler version: 3.3.1-11956-gd8cd4d28
  • Device: Computer

Steps to reproduce

Given the following program:

program procRefRegVar;
{$mode delphi}
{$modeswitch functionreferences}
{$modeswitch anonymousfunctions}

type
  tRefProc = reference to procedure;

procedure main(const a: integer);
  var
      procRef: tRefProc;
      b: integer;

  procedure nested1;
    begin
      procRef := procedure begin writeln(b) end;
      //procRef := procedure begin end;
      procRef;
    end;

  procedure nested2;
    begin
      procRef := procedure begin writeln(a); end;
      //procRef := procedure begin end;
      procRef;
    end;

  begin
    b := 1;
    nested1;
    nested2;
  end;

begin
  main(2)
end.

Try to compile an run it.

# without -OoRegVar it works

$ fpc procRefRegVar.pas && ./procRefRegVar
Free Pascal Compiler version 3.3.1 [2022/10/04] for x86_64
Copyright (c) 1993-2022 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling procRefRegVar.pas
Linking procRefRegVar
36 lines compiled, 0.1 sec, 144672 bytes code, 56496 bytes data
1
2
# with -OoRegVar it fails to compile
$ fpc -OoRegVar procRefRegVar.pas && ./procRefRegVar
Free Pascal Compiler version 3.3.1 [2022/10/04] for x86_64
Copyright (c) 1993-2022 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling procRefRegVar.pas
procRefRegVar.pas(22,5) Fatal: Internal error 200409241
Fatal: Compilation aborted
Error: /home/shared-development/fpc_usr/lib/fpc/3.3.1/ppcx64 returned an error exitcode

If both the closure captures are commented out and replace with an empty begin end the compile will succeed.

Just commenting out one and replacing it with begin end will cause the compile of the other one to fail.

Interesting to note though, it fails on the second by default, unless the second is replaced with begin end, in which case the first one then fails.

Example Project

See steps to reproduce.

What is the current bug behavior?

See steps to reproduce.

Compiler fails with a non helpful error message.

procRefRegVar.pas(22,5) Fatal: Internal error 200409241

What is the expected (correct) behavior?

I'm not totally sure.

Having the optimizer figure out which variables are captured and not turn them into registers "could" arguably be considered the correct behavior. Or if what is being captured is a const function/procedure parameter (and not constref) then cache it somewhere and use the cached copy.

However, I'm not going to try defend either of those.

Those would be an extreme expectations, and not ones I would consider to be feasible (as I've not studied FPC's optimizer or the specifics of the closure capture).

Possibly some error message indicating the particular variable could not by captured and why would suffice.

A more descriptive error message would be helpful so someone else by process elimination does not have to determine what optimization to disable (or not enable).

Not everyone might even consider to do that (track down the offending optimization and disable it) so a more descriptive error message would be very helpful.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information