In the first case study, I present techniques for constructing certified program verifiers. I present a Coq toolkit for building foundational memory safety verifiers for x86 machine code. The implementation uses rich specification types to mix behavioral requirements with the traditional types of functions, and I mix standard programming practice with tactic-based interactive theorem proving to implement programs of these types. I decompose verifier implementations into libraries of components, where each component is implemented as a functor that transforms a verifier at one level of abstraction into a verifier at a lower level. I use the toolkit to assemble a verifier for programs that use algebraic datatypes using only several hundred lines of code specific to its type system.
The second case study presents work in certified compilers. I focus in particular on type-preserving compilation, where source-level type information is preserved through several statically-typed intermediate languages and used at runtime for such purposes as guiding a garbage collector. I suggest a novel approach to mechanizing the semantics of programming languages, based on dependently-typed abstract syntax and denotational semantics. I use this approach to certify a compiler from simply-typed lambda calculus to an idealized assembly language that interfaces with a garbage collector through tables listing the appropriate root registers for different program points. Significant parts of the proof effort are automated using type-driven heuristics. I also present a generic programming system for automating construction of syntactic helper functions and their correctness proofs, based on an implementation technique called proof by reflection.