Dear Oleg N. Cher,
Thanks for the error reporting.
Actually, I already encountered this error before and understand why it happened, but didn't document about it yet.
In the previous version, the code generated by compiler accessed its global variables by RIP relative addressing, that meant there was no need for changing base register between module boundary, like in ProjectOberon.
However, in this version, I switch to the method of N. Wirth, the benefit is that the number of address fixups during compile process is reduced dramatically. However, it also cause the error which S. Atan encountered.
The procedure P is not exported, so in its code, there is no loading of RBX, because it assumed that RBX would always point to the base of Module2 when it was called. However, P was exported indirectly by procedure variable TT.P When P was called by Module1, RBX was still pointing to Module1 base, hence the crash happened. For more detail, you can check the code of PROCEDURE Procedure in Generator.mod
The moral of this is that adding more "features" or "tweaks" to the products may not be a good thing, because they could interact in an unexpected way (a case of this dialectical statement: the whole is not equal to the sum of its parts).
There are two solutions to this error:
1. Require every procedure must be exported before assignment to procedure variable
2. Saving and Loading of RBX should be mandatory for all procedures, exported or not
I believe solution 2 is less disruptive and more conforming to the spirit of N. Wirth.
Anyway, thank you very much for the report of this error.
In Project Oberon, N. Wirth just let the caller load the base register for the callee, and use the module loader to perform fixup, which was a better solution, but we need more code in module loading phase (which was already complex enough, due to the design of Windows)
Đặng Minh Công