Documentation

Std.Data.BitVec.Basic

We define bitvectors. We choose the Fin representation over others for its relative efficiency (Lean has special support for Nat), alignment with UIntXY types which are also represented with Fin, and the fact that bitwise operations on Fin are already defined. Some other possible representations are List Bool, { l : List Bool // l.length = w }, Fin w → Bool.

We define many of the bitvector operations from the QF_BV logic. of SMT-LIBv2.

structure Std.BitVec (w : Nat) :

A bitvector of the specified width. This is represented as the underlying Nat number in both the runtime and the kernel, inheriting all the special support for Nat.

  • ofFin :: (
    • toFin : Fin (2 ^ w)

      Interpret a bitvector as a number less than 2^w. O(1), because we use Fin as the internal representation of a bitvector.

  • )
Instances For
    Equations
    • Std.instDecidableEqBitVec = Std.decEqBitVec✝
    @[inline]
    def Std.BitVec.cast {n : Nat} {m : Nat} (eq : n = m) (i : Std.BitVec n) :

    cast eq i embeds i into an equal BitVec type.

    Equations
    Instances For
      @[match_pattern]
      def Std.BitVec.ofNat (n : Nat) (i : Nat) :

      The BitVec with value i mod 2^n. Treated as an operation on bitvectors, this is truncation of the high bits when downcasting and zero-extension when upcasting.

      Equations
      Instances For
        def Std.BitVec.toNat {n : Nat} (a : Std.BitVec n) :

        Given a bitvector a, return the underlying Nat. This is O(1) because BitVec is a (zero-cost) wrapper around a Nat.

        Equations
        Instances For
          theorem Std.BitVec.isLt {w : Nat} (x : Std.BitVec w) :

          Return the bound in terms of toNat.

          @[inline]
          def Std.BitVec.getLsb {w : Nat} (x : Std.BitVec w) (i : Nat) :

          Return the i-th least significant bit or false if i ≥ w.

          Equations
          Instances For
            @[inline]
            def Std.BitVec.getMsb {w : Nat} (x : Std.BitVec w) (i : Nat) :

            Return the i-th most significant bit or false if i ≥ w.

            Equations
            Instances For
              @[inline]
              def Std.BitVec.msb {n : Nat} (a : Std.BitVec n) :

              Return most-significant bit in bitvector.

              Equations
              Instances For
                def Std.BitVec.toInt {n : Nat} (a : Std.BitVec n) :

                Interpret the bitvector as an integer stored in two's complement form.

                Equations
                Instances For

                  Return a bitvector 0 of size n. This is the bitvector with all zero bits.

                  Equations
                  Instances For
                    Equations
                    instance Std.BitVec.instOfNatBitVec {n : Nat} {i : Nat} :
                    Equations
                    • Std.BitVec.instOfNatBitVec = { ofNat := i#n }

                    Notation for bit vector literals. i#n is a shorthand for BitVec.ofNat n i.

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

                      Unexpander for bit vector literals.

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

                        Convert bitvector into a fixed-width hex number.

                        Equations
                        Instances For
                          Equations
                          • One or more equations did not get rendered due to their size.
                          Equations
                          @[simp]
                          theorem Std.BitVec.ofNat_eq_ofNat {n : Nat} {i : Nat} :

                          Theorem for normalizing the bit vector literal representation.

                          def Std.BitVec.add {n : Nat} (x : Std.BitVec n) (y : Std.BitVec n) :

                          Addition for bit vectors. This can be interpreted as either signed or unsigned addition modulo 2^n.

                          SMT-Lib name: bvadd.

                          Equations
                          Instances For
                            Equations
                            • Std.BitVec.instAddBitVec = { add := Std.BitVec.add }
                            def Std.BitVec.sub {n : Nat} (x : Std.BitVec n) (y : Std.BitVec n) :

                            Subtraction for bit vectors. This can be interpreted as either signed or unsigned subtraction modulo 2^n.

                            Equations
                            Instances For
                              Equations
                              • Std.BitVec.instSubBitVec = { sub := Std.BitVec.sub }

                              Negation for bit vectors. This can be interpreted as either signed or unsigned negation modulo 2^n.

                              SMT-Lib name: bvneg.

                              Equations
                              Instances For
                                Equations
                                • Std.BitVec.instNegBitVec = { neg := Std.BitVec.neg }

                                Bit vector of size n where all bits are 1s

                                Equations
                                Instances For

                                  Return the absolute value of a signed bitvector.

                                  Equations
                                  Instances For
                                    def Std.BitVec.mul {n : Nat} (x : Std.BitVec n) (y : Std.BitVec n) :

                                    Multiplication for bit vectors. This can be interpreted as either signed or unsigned negation modulo 2^n.

                                    SMT-Lib name: bvmul.

                                    Equations
                                    Instances For
                                      Equations
                                      • Std.BitVec.instMulBitVec = { mul := Std.BitVec.mul }
                                      def Std.BitVec.udiv {n : Nat} (x : Std.BitVec n) (y : Std.BitVec n) :

                                      Unsigned division for bit vectors using the Lean convention where division by zero returns zero.

                                      Equations
                                      Instances For
                                        Equations
                                        • Std.BitVec.instDivBitVec = { div := Std.BitVec.udiv }
                                        def Std.BitVec.umod {n : Nat} (x : Std.BitVec n) (y : Std.BitVec n) :

                                        Unsigned modulo for bit vectors.

                                        SMT-Lib name: bvurem.

                                        Equations
                                        Instances For
                                          Equations
                                          • Std.BitVec.instModBitVec = { mod := Std.BitVec.umod }

                                          Unsigned division for bit vectors using the SMT-Lib convention where division by zero returns the allOnes bitvector.

                                          SMT-Lib name: bvudiv.

                                          Equations
                                          Instances For
                                            def Std.BitVec.sdiv {n : Nat} (s : Std.BitVec n) (t : Std.BitVec n) :

                                            Signed t-division for bit vectors using the Lean convention where division by zero returns zero.

                                            sdiv 7#4 2 = 3#4
                                            sdiv (-9#4) 2 = -4#4
                                            sdiv 5#4 -2 = -2#4
                                            sdiv (-7#4) (-2) = 3#4
                                            
                                            Equations
                                            • One or more equations did not get rendered due to their size.
                                            Instances For

                                              Signed division for bit vectors using SMTLIB rules for division by zero.

                                              Specifically, smtSDiv x 0 = if x >= 0 then -1 else 1

                                              SMT-Lib name: bvsdiv.

                                              Equations
                                              • One or more equations did not get rendered due to their size.
                                              Instances For
                                                def Std.BitVec.srem {n : Nat} (s : Std.BitVec n) (t : Std.BitVec n) :

                                                Remainder for signed division rounding to zero.

                                                SMT_Lib name: bvsrem.

                                                Equations
                                                • One or more equations did not get rendered due to their size.
                                                Instances For
                                                  def Std.BitVec.smod {m : Nat} (s : Std.BitVec m) (t : Std.BitVec m) :

                                                  Remainder for signed division rounded to negative infinity.

                                                  SMT_Lib name: bvsmod.

                                                  Equations
                                                  • One or more equations did not get rendered due to their size.
                                                  Instances For
                                                    def Std.BitVec.ult {n : Nat} (x : Std.BitVec n) (y : Std.BitVec n) :

                                                    Unsigned less-than for bit vectors.

                                                    SMT-Lib name: bvult.

                                                    Equations
                                                    Instances For
                                                      Equations
                                                      • Std.BitVec.instLTBitVec = { lt := fun (x y : Std.BitVec n) => x.toFin < y.toFin }
                                                      def Std.BitVec.ule {n : Nat} (x : Std.BitVec n) (y : Std.BitVec n) :

                                                      Unsigned less-than-or-equal-to for bit vectors.

                                                      SMT-Lib name: bvule.

                                                      Equations
                                                      Instances For
                                                        Equations
                                                        • Std.BitVec.instLEBitVec = { le := fun (x y : Std.BitVec n) => x.toFin y.toFin }
                                                        def Std.BitVec.slt {n : Nat} (x : Std.BitVec n) (y : Std.BitVec n) :

                                                        Signed less-than for bit vectors.

                                                        BitVec.slt 6#4 7 = true
                                                        BitVec.slt 7#4 8 = false
                                                        

                                                        SMT-Lib name: bvslt.

                                                        Equations
                                                        Instances For
                                                          def Std.BitVec.sle {n : Nat} (x : Std.BitVec n) (y : Std.BitVec n) :

                                                          Signed less-than-or-equal-to for bit vectors.

                                                          SMT-Lib name: bvsle.

                                                          Equations
                                                          Instances For
                                                            def Std.BitVec.and {n : Nat} (x : Std.BitVec n) (y : Std.BitVec n) :

                                                            Bitwise AND for bit vectors.

                                                            0b1010#4 &&& 0b0110#4 = 0b0010#4
                                                            

                                                            SMT-Lib name: bvand.

                                                            Equations
                                                            Instances For
                                                              Equations
                                                              • Std.BitVec.instAndOpBitVec = { and := Std.BitVec.and }
                                                              def Std.BitVec.or {n : Nat} (x : Std.BitVec n) (y : Std.BitVec n) :

                                                              Bitwise OR for bit vectors.

                                                              0b1010#4 ||| 0b0110#4 = 0b1110#4
                                                              

                                                              SMT-Lib name: bvor.

                                                              Equations
                                                              Instances For
                                                                Equations
                                                                • Std.BitVec.instOrOpBitVec = { or := Std.BitVec.or }
                                                                def Std.BitVec.xor {n : Nat} (x : Std.BitVec n) (y : Std.BitVec n) :

                                                                Bitwise XOR for bit vectors.

                                                                0b1010#4 ^^^ 0b0110#4 = 0b1100#4
                                                                

                                                                SMT-Lib name: bvxor.

                                                                Equations
                                                                Instances For
                                                                  Equations
                                                                  • Std.BitVec.instXorBitVec = { xor := Std.BitVec.xor }

                                                                  Bitwise NOT for bit vectors.

                                                                  ~~~(0b0101#4) == 0b1010
                                                                  

                                                                  SMT-Lib name: bvnot.

                                                                  Equations
                                                                  Instances For
                                                                    Equations
                                                                    • Std.BitVec.instComplementBitVec = { complement := Std.BitVec.not }
                                                                    def Std.BitVec.ofInt (n : Nat) (i : Int) :

                                                                    The BitVec with value (2^n + (i mod 2^n)) mod 2^n.

                                                                    Equations
                                                                    Instances For
                                                                      def Std.BitVec.shiftLeft {n : Nat} (a : Std.BitVec n) (s : Nat) :

                                                                      Left shift for bit vectors. The low bits are filled with zeros. As a numeric operation, this is equivalent to a * 2^s, modulo 2^n.

                                                                      SMT-Lib name: bvshl except this operator uses a Nat shift value.

                                                                      Equations
                                                                      Instances For
                                                                        Equations
                                                                        • Std.BitVec.instHShiftLeftBitVecNat = { hShiftLeft := Std.BitVec.shiftLeft }

                                                                        (Logical) right shift for bit vectors. The high bits are filled with zeros. As a numeric operation, this is equivalent to a / 2^s, rounding down.

                                                                        SMT-Lib name: bvlshr except this operator uses a Nat shift value.

                                                                        Equations
                                                                        Instances For
                                                                          Equations
                                                                          • Std.BitVec.instHShiftRightBitVecNat = { hShiftRight := Std.BitVec.ushiftRight }

                                                                          Arithmetic right shift for bit vectors. The high bits are filled with the most-significant bit. As a numeric operation, this is equivalent to a.toInt >>> s.

                                                                          SMT-Lib name: bvashr except this operator uses a Nat shift value.

                                                                          Equations
                                                                          Instances For
                                                                            Equations
                                                                            Equations

                                                                            Rotate left for bit vectors. All the bits of x are shifted to higher positions, with the top n bits wrapping around to fill the low bits.

                                                                            rotateLeft  0b0011#4 3 = 0b1001
                                                                            

                                                                            SMT-Lib name: rotate_left except this operator uses a Nat shift amount.

                                                                            Equations
                                                                            Instances For

                                                                              Rotate right for bit vectors. All the bits of x are shifted to lower positions, with the bottom n bits wrapping around to fill the high bits.

                                                                              rotateRight 0b01001#5 1 = 0b10100
                                                                              

                                                                              SMT-Lib name: rotate_right except this operator uses a Nat shift amount.

                                                                              Equations
                                                                              Instances For
                                                                                def Std.BitVec.zeroExtend' {n : Nat} {w : Nat} (le : n w) (x : Std.BitVec n) :

                                                                                A version of zeroExtend that requires a proof, but is a noop.

                                                                                Equations
                                                                                Instances For
                                                                                  def Std.BitVec.shiftLeftZeroExtend {w : Nat} (msbs : Std.BitVec w) (m : Nat) :

                                                                                  shiftLeftZeroExtend x n returns zeroExtend (w+n) x <<< n without needing to compute x % 2^(2+n).

                                                                                  Equations
                                                                                  • One or more equations did not get rendered due to their size.
                                                                                  Instances For
                                                                                    def Std.BitVec.append {n : Nat} {m : Nat} (msbs : Std.BitVec n) (lsbs : Std.BitVec m) :

                                                                                    Concatenation of bitvectors. This uses the "big endian" convention that the more significant input is on the left, so 0xAB#8 ++ 0xCD#8 = 0xABCD#16.

                                                                                    SMT-Lib name: concat.

                                                                                    Equations
                                                                                    Instances For
                                                                                      Equations
                                                                                      • Std.BitVec.instHAppendBitVecHAddNatInstHAddInstAddNat = { hAppend := Std.BitVec.append }
                                                                                      def Std.BitVec.extractLsb' {n : Nat} (start : Nat) (len : Nat) (a : Std.BitVec n) :

                                                                                      Extraction of bits start to start + len - 1 from a bit vector of size n to yield a new bitvector of size len. If start + len > n, then the vector will be zero-padded in the high bits.

                                                                                      Equations
                                                                                      Instances For
                                                                                        def Std.BitVec.extractLsb {n : Nat} (hi : Nat) (lo : Nat) (a : Std.BitVec n) :
                                                                                        Std.BitVec (hi - lo + 1)

                                                                                        Extraction of bits hi (inclusive) down to lo (inclusive) from a bit vector of size n to yield a new bitvector of size hi - lo + 1.

                                                                                        SMT-Lib name: extract.

                                                                                        Equations
                                                                                        Instances For
                                                                                          def Std.BitVec.replicate {w : Nat} (i : Nat) :
                                                                                          Std.BitVec wStd.BitVec (w * i)

                                                                                          replicate i x concatenates i copies of x into a new vector of length w*i.

                                                                                          Equations
                                                                                          Instances For
                                                                                            def Std.BitVec.fill (w : Nat) (b : Bool) :

                                                                                            Fills a bitvector with w copies of the bit b.

                                                                                            Equations
                                                                                            Instances For

                                                                                              Zero extend vector x of length w by adding zeros in the high bits until it has length v. If v < w then it truncates the high bits instead.

                                                                                              SMT-Lib name: zero_extend.

                                                                                              Equations
                                                                                              Instances For
                                                                                                def Std.BitVec.truncate {w : Nat} (v : Nat) (x : Std.BitVec w) :

                                                                                                Truncate the high bits of bitvector x of length w, resulting in a vector of length v. If v > w then it zero-extends the vector instead.

                                                                                                Equations
                                                                                                Instances For

                                                                                                  Sign extend a vector of length w, extending with i additional copies of the most significant bit in x. If x is an empty vector, then the sign is treated as zero.

                                                                                                  SMT-Lib name: sign_extend.

                                                                                                  Equations
                                                                                                  Instances For

                                                                                                    We add simp-lemmas that rewrite bitvector operations into the equivalent notation

                                                                                                    @[simp]
                                                                                                    theorem Std.BitVec.append_eq {w : Nat} {v : Nat} (x : Std.BitVec w) (y : Std.BitVec v) :
                                                                                                    @[simp]
                                                                                                    theorem Std.BitVec.shiftLeft_eq {w : Nat} (x : Std.BitVec w) (n : Nat) :
                                                                                                    @[simp]
                                                                                                    @[simp]
                                                                                                    @[simp]
                                                                                                    theorem Std.BitVec.and_eq {w : Nat} (x : Std.BitVec w) (y : Std.BitVec w) :
                                                                                                    @[simp]
                                                                                                    theorem Std.BitVec.or_eq {w : Nat} (x : Std.BitVec w) (y : Std.BitVec w) :
                                                                                                    @[simp]
                                                                                                    theorem Std.BitVec.xor_eq {w : Nat} (x : Std.BitVec w) (y : Std.BitVec w) :
                                                                                                    @[simp]
                                                                                                    theorem Std.BitVec.neg_eq {w : Nat} (x : Std.BitVec w) :
                                                                                                    @[simp]
                                                                                                    theorem Std.BitVec.add_eq {w : Nat} (x : Std.BitVec w) (y : Std.BitVec w) :
                                                                                                    @[simp]
                                                                                                    theorem Std.BitVec.sub_eq {w : Nat} (x : Std.BitVec w) (y : Std.BitVec w) :
                                                                                                    @[simp]
                                                                                                    theorem Std.BitVec.mul_eq {w : Nat} (x : Std.BitVec w) (y : Std.BitVec w) :
                                                                                                    @[simp]
                                                                                                    @[simp]
                                                                                                    theorem Std.BitVec.cast_ofNat {n : Nat} {m : Nat} (h : n = m) (x : Nat) :
                                                                                                    Std.BitVec.cast h x#n = x#m
                                                                                                    @[simp]
                                                                                                    theorem Std.BitVec.cast_cast {n : Nat} {m : Nat} {k : Nat} (h₁ : n = m) (h₂ : m = k) (x : Std.BitVec n) :
                                                                                                    @[simp]
                                                                                                    theorem Std.BitVec.cast_eq {n : Nat} (h : n = n) (x : Std.BitVec n) :

                                                                                                    Turn a Bool into a bitvector of length 1

                                                                                                    Equations
                                                                                                    Instances For
                                                                                                      @[inline, reducible]

                                                                                                      The empty bitvector

                                                                                                      Equations
                                                                                                      Instances For

                                                                                                        Cons and Concat #

                                                                                                        We give special names to the operations of adding a single bit to either end of a bitvector. We follow the precedent of Vector.cons/Vector.concat both for the name, and for the decision to have the resulting size be n + 1 for both operations (rather than 1 + n, which would be the result of appending a single bit to the front in the naive implementation).

                                                                                                        def Std.BitVec.concat {n : Nat} (msbs : Std.BitVec n) (lsb : Bool) :

                                                                                                        Append a single bit to the end of a bitvector, using big endian order (see append). That is, the new bit is the least significant bit.

                                                                                                        Equations
                                                                                                        Instances For
                                                                                                          def Std.BitVec.cons {n : Nat} (msb : Bool) (lsbs : Std.BitVec n) :

                                                                                                          Prepend a single bit to the front of a bitvector, using big endian order (see append). That is, the new bit is the most significant bit.

                                                                                                          Equations
                                                                                                          Instances For

                                                                                                            Every bitvector of length 0 is equal to nil, i.e., there is only one empty bitvector

                                                                                                            theorem Std.BitVec.append_ofBool {w : Nat} (msbs : Std.BitVec w) (lsb : Bool) :
                                                                                                            theorem Std.BitVec.ofBool_append {w : Nat} (msb : Bool) (lsbs : Std.BitVec w) :
                                                                                                            Std.BitVec.ofBool msb ++ lsbs = Std.BitVec.cast (_ : w + 1 = 1 + w) (Std.BitVec.cons msb lsbs)