diff options
author | Yitzhak Mandelbaum <ymand@users.noreply.github.com> | 2025-08-18 11:55:12 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-08-18 11:55:12 -0400 |
commit | 3ecfc0330d93a6c3a3f3d3e427390b01cb52a88d (patch) | |
tree | 44ee278359ea2f7d58920b031deb30221cf42b2d /clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp | |
parent | c67d27dad02ab7debfff6c7f7fc3ea8abf064b6a (diff) | |
download | llvm-3ecfc0330d93a6c3a3f3d3e427390b01cb52a88d.zip llvm-3ecfc0330d93a6c3a3f3d3e427390b01cb52a88d.tar.gz llvm-3ecfc0330d93a6c3a3f3d3e427390b01cb52a88d.tar.bz2 |
[clang][dataflow] Add support for serialization and deserialization. (#152487)
Adds support for compact serialization of Formulas, and a corresponding
parse function. Extends Environment and AnalysisContext with necessary
functions for serializing and deserializing all formula-related parts of
the environment.
Diffstat (limited to 'clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp')
-rw-r--r-- | clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp index 6421ad3..06a8878 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp @@ -208,6 +208,24 @@ bool DataflowAnalysisContext::equivalentFormulas(const Formula &Val1, return isUnsatisfiable(std::move(Constraints)); } +llvm::DenseSet<Atom> DataflowAnalysisContext::collectDependencies( + llvm::DenseSet<Atom> Tokens) const { + // Use a worklist algorithm, with `Remaining` holding the worklist and + // `Tokens` tracking which atoms have already been added to the worklist. + std::vector<Atom> Remaining(Tokens.begin(), Tokens.end()); + while (!Remaining.empty()) { + Atom CurrentToken = Remaining.back(); + Remaining.pop_back(); + if (auto DepsIt = FlowConditionDeps.find(CurrentToken); + DepsIt != FlowConditionDeps.end()) + for (Atom A : DepsIt->second) + if (Tokens.insert(A).second) + Remaining.push_back(A); + } + + return Tokens; +} + void DataflowAnalysisContext::addTransitiveFlowConditionConstraints( Atom Token, llvm::SetVector<const Formula *> &Constraints) { llvm::DenseSet<Atom> AddedTokens; @@ -224,6 +242,8 @@ void DataflowAnalysisContext::addTransitiveFlowConditionConstraints( auto ConstraintsIt = FlowConditionConstraints.find(Token); if (ConstraintsIt == FlowConditionConstraints.end()) { + // The flow condition is unconstrained. Just add the atom directly, which + // is equivalent to asserting it is true. Constraints.insert(&arena().makeAtomRef(Token)); } else { // Bind flow condition token via `iff` to its set of constraints: @@ -239,6 +259,65 @@ void DataflowAnalysisContext::addTransitiveFlowConditionConstraints( } } +static void getReferencedAtoms(const Formula &F, + llvm::DenseSet<dataflow::Atom> &Refs) { + switch (F.kind()) { + case Formula::AtomRef: + Refs.insert(F.getAtom()); + break; + case Formula::Literal: + break; + case Formula::Not: + getReferencedAtoms(*F.operands()[0], Refs); + break; + case Formula::And: + case Formula::Or: + case Formula::Implies: + case Formula::Equal: + ArrayRef<const Formula *> Operands = F.operands(); + getReferencedAtoms(*Operands[0], Refs); + getReferencedAtoms(*Operands[1], Refs); + break; + } +} + +SimpleLogicalContext DataflowAnalysisContext::exportLogicalContext( + llvm::DenseSet<dataflow::Atom> TargetTokens) const { + SimpleLogicalContext LC; + + if (Invariant != nullptr) { + LC.Invariant = Invariant; + getReferencedAtoms(*Invariant, TargetTokens); + } + + llvm::DenseSet<dataflow::Atom> Dependencies = + collectDependencies(std::move(TargetTokens)); + + for (dataflow::Atom Token : Dependencies) { + // Only process the token if it is constrained. Unconstrained tokens don't + // have dependencies. + const Formula *Constraints = FlowConditionConstraints.lookup(Token); + if (Constraints == nullptr) + continue; + LC.TokenDefs[Token] = Constraints; + + if (auto DepsIt = FlowConditionDeps.find(Token); + DepsIt != FlowConditionDeps.end()) + LC.TokenDeps[Token] = DepsIt->second; + } + + return LC; +} + +void DataflowAnalysisContext::initLogicalContext(SimpleLogicalContext LC) { + Invariant = LC.Invariant; + FlowConditionConstraints = std::move(LC.TokenDefs); + // TODO: The dependencies in `LC.TokenDeps` can be reconstructed from + // `LC.TokenDefs`. Give the caller the option to reconstruct, rather than + // providing them directly, to save caller space (memory/disk). + FlowConditionDeps = std::move(LC.TokenDeps); +} + static void printAtomList(const llvm::SmallVector<Atom> &Atoms, llvm::raw_ostream &OS) { OS << "("; |