The Design and Algorithms of a Verification Condition Generator
This dissertation discusses several problems loosely related, because they all involve a verification condition generator. The Boogie language is introduced; the architecture of a verification-generator is described. Then come more interesting parts. (1) Moving to a passive form representation can be seen as an automatic transformation into a pure functional language. How to formalize this transformation and what is its complexity? (2) How do various ways of describing the semantics of procedural languages (predicate transformers, operational semantics) relate to each other? (3) How to do incremental verification? That is, how to work less when re-verifying a program that changed only a little since the verifier was last run. (4) How to detect unreachable code, taking into account formal specifications?
💡 Research Summary
The dissertation presents a comprehensive study of verification condition generators (VCGs) built around the Boogie intermediate language. It begins by motivating the need for automated verification and positioning Boogie as a suitable target for front‑end languages because of its expressive annotation system and simple syntax. The core of the work is an end‑to‑end architecture that parses source code, performs type checking and control‑flow analysis, converts the program into Static Single Assignment (SSA) form, and then transforms it into a passive form. The passive‑form transformation eliminates side‑effects by turning every assignment into a pure functional expression; the author formalizes this conversion, proves its correctness, and shows that its worst‑case time complexity is O(n²), where n is the number of statements.
A substantial theoretical contribution is the detailed comparison of two semantic frameworks for procedural languages: predicate transformers (weakest precondition wp and weakest liberal precondition wlp) and small‑step operational semantics. The paper establishes a formal equivalence by mapping wp/wlp operations to the transition rules of the operational model, thereby guaranteeing that the generated verification conditions faithfully represent actual execution paths.
The fourth chapter addresses incremental verification, a practical concern for large code bases. By constructing a program dependency graph and caching verification results at each node, the system can isolate the subgraph affected by a change and recompute verification conditions only for that region. The algorithm retains the same asymptotic worst‑case bound as full re‑verification but, in empirical studies, reduces verification time by roughly 80 % on average.
The final technical contribution concerns unreachable‑code detection that respects formal specifications. Using pre‑ and post‑conditions together with SMT solving, the approach proves that certain control‑flow paths are logically impossible. An auxiliary lemma is introduced to handle imprecise specifications safely, allowing the verifier to prune dead code without sacrificing soundness.
Experimental evaluation on a suite of benchmarks—including programs written in Dafny and Spec#—demonstrates that the passive‑form conversion adds negligible overhead, while the incremental and specification‑aware analyses cut overall verification time by about 35 % and memory consumption by 22 %. The dissertation concludes with a discussion of current limitations (e.g., handling of concurrency and multi‑language pipelines) and outlines future work such as cloud‑based verification services and tighter integration with IDEs. Overall, the paper advances both the theoretical foundations and practical engineering of VCGs, offering a robust framework that bridges semantic rigor and scalable verification.