1fc9821a8SSam McCall //===- Formula.cpp ----------------------------------------------*- C++ -*-===//
2fc9821a8SSam McCall //
3fc9821a8SSam McCall // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fc9821a8SSam McCall // See https://llvm.org/LICENSE.txt for license information.
5fc9821a8SSam McCall // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fc9821a8SSam McCall //
7fc9821a8SSam McCall //===----------------------------------------------------------------------===//
8fc9821a8SSam McCall
9fc9821a8SSam McCall #include "clang/Analysis/FlowSensitive/Formula.h"
10fc9821a8SSam McCall #include "clang/Basic/LLVM.h"
11fc9821a8SSam McCall #include "llvm/ADT/STLExtras.h"
12fc9821a8SSam McCall #include "llvm/ADT/StringRef.h"
13fc9821a8SSam McCall #include "llvm/Support/Allocator.h"
14fc9821a8SSam McCall #include "llvm/Support/ErrorHandling.h"
15fc9821a8SSam McCall #include <cassert>
163f78d6abSSam McCall #include <type_traits>
17fc9821a8SSam McCall
18fc9821a8SSam McCall namespace clang::dataflow {
19fc9821a8SSam McCall
create(llvm::BumpPtrAllocator & Alloc,Kind K,ArrayRef<const Formula * > Operands,unsigned Value)20*7338eb56SSam McCall const Formula &Formula::create(llvm::BumpPtrAllocator &Alloc, Kind K,
21*7338eb56SSam McCall ArrayRef<const Formula *> Operands,
22*7338eb56SSam McCall unsigned Value) {
23fc9821a8SSam McCall assert(Operands.size() == numOperands(K));
24fc9821a8SSam McCall if (Value != 0) // Currently, formulas have values or operands, not both.
25fc9821a8SSam McCall assert(numOperands(K) == 0);
26fc9821a8SSam McCall void *Mem = Alloc.Allocate(sizeof(Formula) +
27fc9821a8SSam McCall Operands.size() * sizeof(Operands.front()),
28fc9821a8SSam McCall alignof(Formula));
29fc9821a8SSam McCall Formula *Result = new (Mem) Formula();
30fc9821a8SSam McCall Result->FormulaKind = K;
31fc9821a8SSam McCall Result->Value = Value;
32fc9821a8SSam McCall // Operands are stored as `const Formula *`s after the formula itself.
33fc9821a8SSam McCall // We don't need to construct an object as pointers are trivial types.
34fc9821a8SSam McCall // Formula is alignas(const Formula *), so alignment is satisfied.
35fc9821a8SSam McCall llvm::copy(Operands, reinterpret_cast<const Formula **>(Result + 1));
36fc9821a8SSam McCall return *Result;
37fc9821a8SSam McCall }
38fc9821a8SSam McCall
sigil(Formula::Kind K)39fc9821a8SSam McCall static llvm::StringLiteral sigil(Formula::Kind K) {
40fc9821a8SSam McCall switch (K) {
41fc9821a8SSam McCall case Formula::AtomRef:
42*7338eb56SSam McCall case Formula::Literal:
43fc9821a8SSam McCall return "";
44fc9821a8SSam McCall case Formula::Not:
45fc9821a8SSam McCall return "!";
46fc9821a8SSam McCall case Formula::And:
47fc9821a8SSam McCall return " & ";
48fc9821a8SSam McCall case Formula::Or:
49fc9821a8SSam McCall return " | ";
50fc9821a8SSam McCall case Formula::Implies:
51fc9821a8SSam McCall return " => ";
52fc9821a8SSam McCall case Formula::Equal:
53fc9821a8SSam McCall return " = ";
54fc9821a8SSam McCall }
55fc9821a8SSam McCall llvm_unreachable("unhandled formula kind");
56fc9821a8SSam McCall }
57fc9821a8SSam McCall
print(llvm::raw_ostream & OS,const AtomNames * Names) const58fc9821a8SSam McCall void Formula::print(llvm::raw_ostream &OS, const AtomNames *Names) const {
59fc9821a8SSam McCall if (Names && kind() == AtomRef)
60fc9821a8SSam McCall if (auto It = Names->find(getAtom()); It != Names->end()) {
61fc9821a8SSam McCall OS << It->second;
62fc9821a8SSam McCall return;
63fc9821a8SSam McCall }
64fc9821a8SSam McCall
65fc9821a8SSam McCall switch (numOperands(kind())) {
66fc9821a8SSam McCall case 0:
67*7338eb56SSam McCall switch (kind()) {
68*7338eb56SSam McCall case AtomRef:
69fc9821a8SSam McCall OS << getAtom();
70fc9821a8SSam McCall break;
71*7338eb56SSam McCall case Literal:
72*7338eb56SSam McCall OS << (literal() ? "true" : "false");
73*7338eb56SSam McCall break;
74*7338eb56SSam McCall default:
75*7338eb56SSam McCall llvm_unreachable("unhandled formula kind");
76*7338eb56SSam McCall }
77*7338eb56SSam McCall break;
78fc9821a8SSam McCall case 1:
79fc9821a8SSam McCall OS << sigil(kind());
80fc9821a8SSam McCall operands()[0]->print(OS, Names);
81fc9821a8SSam McCall break;
82fc9821a8SSam McCall case 2:
83fc9821a8SSam McCall OS << '(';
84fc9821a8SSam McCall operands()[0]->print(OS, Names);
85fc9821a8SSam McCall OS << sigil(kind());
86fc9821a8SSam McCall operands()[1]->print(OS, Names);
87fc9821a8SSam McCall OS << ')';
88fc9821a8SSam McCall break;
89fc9821a8SSam McCall default:
90fc9821a8SSam McCall llvm_unreachable("unhandled formula arity");
91fc9821a8SSam McCall }
92fc9821a8SSam McCall }
93fc9821a8SSam McCall
94fc9821a8SSam McCall } // namespace clang::dataflow