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