An explanation of occam compiler error modes.
Conor O'Neill, INMOS Ltd., 26th June 1990.

This is an informal discussion of how errors are handled in the occam-in-C
toolset which is soon to be shipped as D705C etc.
It is intended to be read as a rationale rather than as absolute fact,
so some minor details may change.


occam defines three ways of treating errors:

HALT      - stop the processor when an error is detected;
STOP      - stop the process when an error is detected;
UNDEFINED - the user guarantees that no errors will occur, so if one does
            the effect is totally undefined.

Note that this says NOTHING DEFINITIVE about which is the 'faster',
except that the language manual adds for UNDEFINED mode:
"and is only useful for optimising programs known to be correct!"
This unfortunately gives a hint that UNDEFINED mode will be fastest.

As an aid to system integrity, we have ensured within the compilers and
linker that HALT and STOP mode may not be mixed on the same processor.
This is mostly due to the presence of a global Halt-On-Error flag on
a transputer.

The D705B toolset system confused this slightly, by adding a UNIVERSAL
error mode. This was simply a way of being able to provide a library
routine which could be called from either HALT or STOP mode.
A side effect of compiling in UNIVERSAL mode was that all error checking
was turned off. This caused problems in many cases.


The new toolsets (what will become D705C etc) have de-coupled the
decision of which errors to detect, and the decision of how to behave
once an error has occured.

Error modes:
The compiler directly implements two occam error modes:
HALT and STOP. These have the same effect as before.
The compiler also implements a UNIVERSAL error mode.
This is defined to behave as either STOP or HALT mode, depending
upon the state of the transputer's Halt-On-Error flag.
Thus if you write a library in UNIVERSAL error mode, you may link it
with a HALT mode program and it will behave as though it was compiled
in HALT mode, and if you link it with a STOP mode program it will behave
as though it were compiled in STOP mode.

Detecting errors:
In order to speed up code WHICH IS KNOWN TO BE CORRECT, you may use two
command line flags: `K' and `U'. (They can also be specified by #OPTION).
It is worth noting that in practice the compiler doesn't insert a lot
of error checking code (the majority being range checking), and what little
it does is pretty efficient, so you should only turn it off as a last
resort.

The K (Range checks) flag tells the compiler not to insert code whose only
purpose is to detect range checks.
Range checks are in this context defined to be anything
which worries about lengths of arrays, and whether subscripts clash, etc.
Note that in any situation where the compiler can detect a range check
error without specifically adding code, it MAY still do so.
However, exept for situations such as array[i+j], where i+j overflows,
I cannot think of anywhere where this may happen.
Hence it is still illegal to access elements outside the bounds of an array,
but the system probably won't notice.

The U flag tells the compiler not to insert code whose only
purpose is to detect some kind of error.
This option is stronger than the K option, and includes the K option,
so you do not need to use both together.
The sort of things this turns off include checking for negative values
for replicators, checking the values of type conversions,
checking the lengths of shifts, checking for zero length moves, etc,
as well as array range checking.
Note that in any situation where the compiler can detect an error
without specifically adding code, it MAY still do so.
Thus arithmetic overflows, etc, can still cause an error, because they
can be checked for for free.
(You should use PLUS, MINUS and TIMES if you want to prevent these).
It is important to realise that it is still the programmer's responsibility
to ensure that errors cannot occur. The effect of errors is undefined,
in that some may be detected, and some not.
The compiler may decide to insert code to blow the nuclear power station
if an error is detected.
So you cannot use this switch to permit illegal code.

Now to implementation details:
Because of the transputer's instruction set, it so happens that to compile
a program in HALT error mode you need do nothing except set the Halt-On-Error
flag, and check the value of the floating point error flag every so often.
For this reason, HALT mode is pretty efficient.

STOP mode, on the other hand, is not very easy to do, so is less efficient.

UNIVERSAL mode requires the union of the stuff for STOP,
plus the stuff for HALT, so could conceivably be even less efficient,
though in practice is pretty similar to STOP code.


The U flag turns off any error checking code, so using it in conjunction
with HALT mode also prevents checking the floating point error flag every
so often. It does not, as I mentioned above, prevent the checking of
arithmetic overflows, etc.

Similarly the U flag with STOP or UNIVERSAL mode will also inhibit all the
stuff which would otherwise be inserted to cope with stopping the process
when an error is detected.

If you think about this, it means that using the U flag in any error
mode produces identical code, but the object file is still marked as the
indicated error mode for the linker.

Thus, the absolute go-faster code is produced by using the U option
with any error mode.
The libraries which are linked with it, though, will be the normal libraries
for that error mode. In practice the HALT libraries will be fastest,
so for benchmarking using HALT mode plus the U flag.

If you want the equivalent of the old system's UNIVERSAL error mode,
use UNIVERSAL error mode, with the U flag specified too.
This, though, doesn't pull in U flagged libraries like it used to.


To sum up:

1)  The questions of
    a) which errors to explicitly detect, and
    b) what to do once an error is detected,
    have now been separated.

2)  There is NO WAY of telling the occam compiler to ignore all errors.
    All you can do is tell it not to explicitly check for them.
    It may still implicitly check for some.

3)  You may prevent explicit code for range checking by using the K flag.

4)  You may prevent any explicit error checking code by using the U flag.
    It is the user's responsibility to ensure that the code is correct,
    and the effect of any errors is completely undefined.

5)  For occam HALT mode use the compiler's HALT mode.

6)  For occam STOP mode use the compiler's STOP mode.

7)  For occam UNDEFINED mode use any compiler error mode, plus the U flag.

8)  For benchmarks, you can use any error mode, but include the U flag.
    If you call other libraries, their HALT versions will probably be fastest,
    so the best combination for benchmarks is HALT plus U flag.

9)  To get the equivalent of the old compiler's UNIVERSAL mode, you must
    use the new UNIVERSAL mode together with the U flag, but you don't
    get go-faster libraries.

---
Conor O'Neill, Software Group, INMOS Ltd., UK.
UK: conor@inmos.co.uk		US: conor@inmos.com
"It's state-of-the-art" "But it doesn't work!" "That is the state-of-the-art".
