  We develop the first theory of control-flow graphs from first principles, and
use it to create an algorithm for automatically synthesizing many variants of
control-flow graph generators from a language's operational semantics. Our
approach first introduces a new algorithm for converting a large class of
small-step operational semantics to an abstract machine. It next uses a
technique called "abstract rewriting" to automatically abstract the semantics
of a language, which is used both to directly generate a CFG from a program
("interpreted mode") and to generate standalone code, similar to a
human-written CFG generator, for any program in a language. We show how the
choice of two abstraction and projection parameters allow our approach to
synthesize several families of CFG-generators useful for different kinds of
tools. We prove the correspondence between the generated graphs and the
original semantics. We provide and prove an algorithm for automatically proving
the termination of interpreted-mode generators. In addition to our theoretical
results, we have implemented this algorithm in a tool called Mandate, and show
that it produces human-readable code on two medium-size languages with 60-80
rules, featuring nearly all intraprocedural control constructs common in modern
languages. We then showed these CFG-generators were sufficient to build two
static analyzers atop them. Our work is a promising step towards the grand
vision of being able to synthesize all desired tools from the semantics of a
programming language.
