Documentation

Bignum.Arm.Tutorial.Sequence

Sequence Example: Proving by Sequential Composition #

This is a line-by-line port of s2n-bignum/arm/tutorial/sequence.ml.

The key technique demonstrated is compositional verification: instead of symbolically executing all instructions at once, we split the program into sequential chunks with intermediate assertions.

The Program #

0:   8b000021        add     x1, x1, x0
4:   8b000042        add     x2, x2, x0
8:   d2800043        mov     x3, #0x2
c:   9b037c21        mul     x1, x1, x3

The Approach #

  1. Split at pc+8 into two chunks:

    • First chunk (pc to pc+8): two add instructions
    • Second chunk (pc+8 to pc+16): mov and mul
  2. Intermediate assertion at pc+8: X1 = a + b

  3. Prove each chunk independently and compose the proofs.

Memory-Based Model #

Following HOL Light's architecture, programs are stored as bytes in memory. The arm step relation fetches, decodes, and executes instructions from memory.

Machine Code #

The sequence program machine code (16 bytes = 4 instructions).

ARM is little-endian, so:

Equations
Instances For

    Specification #

    The specification follows HOL Light's ensures arm style:

    ensures arm
      (\s. aligned_bytes_loaded s (word pc) sequence_mc /\
           read PC s = word pc /\
           read X0 s = word a /\
           read X1 s = word b /\
           read X2 s = word c)
      (\s. read PC s = word (pc+16) /\
           read X1 s = word ((a + b) * 2))
      (MAYCHANGE [PC;X1;X2;X3])
    

    Precondition: program loaded, PC at start, registers initialized.

    Equations
    • One or more equations did not get rendered due to their size.
    Instances For

      Intermediate assertion at pc+8: X1 = a + b.

      This is the \s. read X1 s = word (a + b) from HOL Light's ENSURES_SEQUENCE_TAC.

      Source: s2n-bignum/arm/tutorial/sequence.ml:77

      Equations
      • One or more equations did not get rendered due to their size.
      Instances For

        Postcondition: PC at pc+16, X1 = (a+b)*2.

        Equations
        Instances For

          Symbolic Execution Helpers #

          Decode lemmas for each instruction in the sequence program.

          Decode instruction 3: MOV X3, #2 (encoded as MOVZ)

          Compositional Verification #

          The key insight from sequence.ml is that we can split a program into sequential chunks and prove each separately. This corresponds to HOL Light's ENSURES_SEQUENCE_TAC.

          Given:

          We can derive:

          theorem Bignum.Arm.Tutorial.ensures_sequence {α : Sort u_1} {step : ααProp} (pre mid post : αProp) (frame : ααProp) (h1 : ensures step pre mid frame) (h2 : ensures step mid post frame) (h_frame_trans : ∀ (s1 s2 s3 : α), frame s1 s2frame s2 s3frame s1 s3) :
          ensures step pre post frame

          Sequential composition of ensures: if we can prove ensures for two sequential chunks, we can derive ensures for the whole program.

          This corresponds to HOL Light's ENSURES_SEQUENCE_TAC.

          theorem Bignum.Arm.Tutorial.maychange_regs_trans (regs : List Reg) (s1 s2 s3 : ArmState) :
          maychange_regs regs s1 s2maychange_regs regs s2 s3maychange_regs regs s1 s3

          Frame transitivity for maychange_regs.

          Chunk Proofs #

          First chunk: instructions 1-2 (two ADD instructions) Second chunk: instructions 3-4 (MOV and MUL)

          First chunk specification: the two ADD instructions.

          Precondition: PC at start, X0 = a, X1 = b, X2 = c Postcondition: PC at pc+8, X1 = a + b

          Source: s2n-bignum/arm/tutorial/sequence.ml:80-92

          Second chunk specification: MOV x3, #2 and MUL x1, x1, x3.

          Precondition: PC at pc+8, X1 = a + b (from intermediate assertion) Postcondition: PC at pc+16, X1 = (a + b) * 2

          Source: s2n-bignum/arm/tutorial/sequence.ml:95-100

          Main Correctness Theorem #

          Compose the two chunk proofs to get the full program correctness.

          Main correctness theorem: the sequence program satisfies its specification.

          The proof demonstrates compositional verification:

          1. Split the program at pc+8
          2. Prove chunk1 establishes the intermediate assertion (X1 = a + b)
          3. Prove chunk2 uses the intermediate assertion to establish the final result
          4. Compose using ensures_sequence