  Static analysis is a mature field with applications to bug detection,
security analysis, and code optimization, etc. To facilitate these
applications, static analysis frameworks play an essential role by providing a
series of fundamental services such as program abstraction, control flow graph
construction, and points-to/alias information computation, etc. However,
despite impressive progress of static analysis, and this field has seen several
popular frameworks in the last decades, it is still not clear how a static
analysis framework should be designed in a way that analysis developers could
benefit more: for example, what a good IR (for analysis) ought to look like?
What functionalities should the module of fundamental analyses provide to ease
client analyses? How to develop and integrate new analysis conveniently? How to
manage multiple analyses?
  To answer these questions, in this work, we discuss the design trade-offs for
the crucial components of a static analysis framework, and argue for the most
appropriate design by following the HBDC (Harnessing the Best Designs of
Classics) principle: for each crucial component, we compare the design choices
made for it (possibly) by different classic frameworks such as Soot, WALA,
SpotBugs and Doop, and choose arguably the best one, but if none is good
enough, we then propose a better design. These selected or newly proposed
designs finally constitute Tai-e, a new static analysis framework for Java.
Specifically, Tai-e is novel in the designs of several aspects like IR, pointer
analysis and development of new analyses, etc., leading to an easy-to-learn,
easy-to-use and efficient system. To our knowledge, this is the first work that
systematically explores the designs and implementations of various static
analysis frameworks, and we believe it provides useful materials and viewpoints
for building better static analysis infrastructures.
