Implementation restrictions

With a few exceptions, CM Modula-3 implements the Modula-3 language as defined in ``Systems Programming with Modula-3''.

Arithmetic checking

CM Modula-3 does not generate any special checking for integer arithmetic overflow or underflow. You get whatever checking gcc gives you. Depending on your machine, the FloatMode interface may be used to control floating point exceptions.

Packed types

Packed types are restricted. The compiler enforces the rule that every scalar field (packed or unpacked) can be loaded by a simple ``load, shift, and mask'' sequence on the machine. So, for example, its not possible to have a 32-bit integer that crosses a 32-bit alignment boundary on a machine which only supports aligned 32-bit loads.

Stack overflow checking

CM Modula-3 does not reliably detect thread stack overflows. Stacks are only checked for overflow on procedure entry. No checking is done on external procedures. Thread stacks are allocated in fixed size chunks. The required Thread interface has been augmented with the SizedClosure type to allow arbitrary sized stacks. The default size can be adjusted with Thread.MinDefaultStackSize and Thread.IncDefaultStackSize.

Exception semantics

On some platforms (ALPHA_OSF and DS3100), exceptions scopes are delimited by tables of PCs and exceptions are dispatched by a runtime routine that's able to unwind the stack. If you can implement a stack walker for your machine, send us the code. (See libm3/src/runtime/*/RTExceptionC.c for examples.)

On all other platforms, CM Modula-3 uses C's setjmp/longjmp mechanism to unwind the stack when raising an exception. A problem can occur: assignments may appear to be undone. For example, consider

      i := 3;
      P ();
      j := i;

where P raises exception E. The compiler generates a setjmp at the beginning of the try statement. If the C compiler allocates variable i to a register, the assignment of 3 may be lost during the longjmp and branch that gets to the handler.

Method constants

The language definition says that if T is an object type and m one of its methods, T.m denotes the procedure value that implements that method and that this value is a constant. In CM Modula-3, T.m denotes the correct procedure constant, but since the compiler generates runtime code to locate the method, some uses of the constant that the C compiler must resolve at link time will cause C errors. For example,

    CONST P = T.m;  BEGIN P (...) ...

will work, since no initialized C storage is allocated for P. But the following generates initialized storage and will fail

    CONST X = ARRAY [0..2] OF Proc { T.m, ..};

Similarly, although Modula-3 allows it, the following cannot be evaluated at compile time

    CONST X = (T.m = MyProcedure);