We have intentionally written the program in ex-code in a slightly complicated way, to show that low-level optimizations do not pose significant problems in generating and validating safety proofs. Three of the interesting properties of this program are (1) the instructions are somewhat scheduled, including speculative execution of the load in line 2 and of the addition in line 4, to accommodate the DEC Alpha pipeline latency, (2) register is reused in line 2 to hold the data word instead of the tag address, and (3) even though the precondition is expressed as a function of the value in register , some of the actual memory accesses are done through register . In general, we expect scheduling and register allocation to have no effect on the safety predicate and its proof.
: A Fragment of the formal safety proof of .
It is a simple exercise for the reader familiar with assembly-language programming to verify that this code is indeed correct with respect to the safety policy. The problem, of course, is how to convince even the most suspicious kernel that this code is absolutely safe. To do this, we must prove the safety predicate according to the rules of first-order predicate calculus extended with two's-complement integer arithmetic. We refer to this set of proof rules as and we write when the safety predicate can be proved according to the rules in the set . Most of the rules in are simple. Below we show two of the rules we use, the first being a classical implication-elimination rule from the predicate calculus, and the second a rule about arithmetic:
The second rule is perhaps a bit surprising because is unconditionally true in integer arithmetic. However, for the machine implementation of arithmetic, this statement is true only if the original value of is a valid register value.
A large fragment of the proof of the safety predicate for our example program is shown in a proof-tree form in ex-proof. This proof was generated automatically by our system, which incorporates a simple theorem prover. We use vertical dots to stand for extractions of a conjunct from the precondition. You can read the proof tree from top to bottom, interpreting every node as a valid inference of the predicate below the line using the assumptions above the line. For example, in the upper-right corner of the figure the predicate is proved using the arithmetic rule we discussed with the assumption extracted from the precondition. Then is proved using the implication-elimination rule and the hypothesis u of the predicate . This hypothesis is introduced at a lower level in the proof tree, at the node labeled u, for the purpose of proving the predicate .