Analysis Examples
Simple Typed VarPointsTo
The most straightforward encoding of a var-points-to analysis. Models a code fragment where v1 = h1() and v2 = h2(), demonstrating how Soufflé reasons about heap allocations and variable assignments using typed Datalog relations.
// v1 = h1();
// v2 = h2();
// v3 = v1;
// v4 = v2;
// v1 = v3;
DefUse Chains with Composed Types
Illustrates how Soufflé's type system — including union types and record types — can model definition-use chains. Composed types allow precise tracking of variable definitions and their subsequent uses across program points.
Context Sensitive Flow Graph
Encodes a context-sensitive control-flow graph, capturing how calling context influences interprocedural analysis precision. Demonstrates Soufflé's ability to express complex graph reachability with stratified negation.
Context Sensitive Flow Graph with Records
Extends the context-sensitive flow graph using Soufflé's record types to bundle context information. Records provide a concise way to pass multiple context elements through analysis rules.
Sequences using Recursive Records
Demonstrates how recursive record types can model sequences and linked structures. Useful for analyses that must traverse abstract syntax trees or call chains of arbitrary depth.
Component Inheritance
Shows Soufflé's component system, where one analysis component can inherit and extend another. This enables modular, reusable analysis specifications that can be composed for larger problems.
Explore Further
These examples illustrate core patterns for building static analyses in Soufflé. For a complete walkthrough, start with A Simple Example in the documentation, or browse the Datalog Language reference for syntax details.
→ Full DocumentationSoufflé is a Datalog synthesis tool purpose-built for the demanding domain of static program analysis. By translating declarative Datalog logic into highly optimized parallel C++ code, it enables analysts to express complex program properties without wrestling with low-level implementation details. The tool leverages the Futamura projection, a partial evaluation technique that transforms interpreters into compilers, allowing analysts to write high-level specifications that automatically yield efficient, specialized executables. This approach bridges the gap between the clarity of logic programming and the performance required for real-world analysis tasks, such as security auditing in large Java codebases or deep inspection of complex software systems. The result is a platform where rapid prototyping and deep design space exploration become practical, even at scale.
At the heart of Soufflé's design is a commitment to declarative specification through Datalog, a logic programming language that uses facts and rules to derive new knowledge from existing data. Analysts define relations—sets of tuples representing program properties—and write rules that express how new relations are inferred from existing ones. The tool then takes these logical declarations and synthesizes a parallel C++ program that efficiently computes the fixpoint of the rule system. This approach abstracts away the complexities of iteration, indexing, and parallelization, allowing the analyst to focus on the semantics of the analysis itself. The result is a powerful workflow where complex static analyses can be expressed in just a few lines of logic.
Soufflé's synthesis pipeline is built around staged compilation, where the Datalog program is progressively transformed into increasingly concrete representations. The first stage parses and type-checks the Datalog specification, identifying relations and their dependencies. The second stage performs a series of logical optimizations, including query planning and relation specialization, to minimize redundant computation. The final stage generates optimized C++ code with specialized data structures tailored to the specific relations and rules of the input program. This staged approach not only improves performance but also enables the tool to provide meaningful error messages and debugging information, making it accessible to analysts who may not be experts in compiler design or parallel programming.
The tool is designed to scale to industrial-sized codebases, supporting analyses that involve millions of facts and complex inference rules. Its parallel execution engine distributes work across multiple cores, exploiting the inherent parallelism in Datalog's fixpoint computation. Specialized data structures, such as B-trees and tries, are automatically selected and tuned for each relation based on its size and access patterns. This automatic specialization means that analysts can write simple, high-level Datalog rules without worrying about the low-level data structure choices that would typically dominate performance considerations. The result is a tool that can handle real-world static analysis tasks, from taint tracking in large applications to security policy enforcement across entire codebases.
The Soufflé community is active and growing, with resources available for both newcomers and experienced users. The documentation provides comprehensive guides covering installation, language syntax, and advanced optimization techniques. Example programs demonstrate common patterns for building static analyses, from simple reachability queries to sophisticated pointer analyses. The project is open source, encouraging contributions and collaboration from researchers and practitioners in program analysis, logic programming, and compiler design. Regular updates and a responsive development team ensure that the tool continues to evolve, incorporating new techniques and addressing the needs of its users. Whether you are exploring Datalog for the first time or building a production-grade analysis tool, Soufflé provides a solid foundation.