xref: /llvm-project/clang/lib/Analysis/FlowSensitive/Formula.cpp (revision 7338eb561c48803ec244cd6116154163f56e9717)
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