Bulletin number: 316 Products affected: D705C_alpha Description: occam 2 compiler error modes Component: compiler Date: Wed Jun 27 12:17:16 BST 1990 ----- 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 TCOFF occam 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.