================ @@ -0,0 +1,161 @@ +//===- FormulaSerialization.cpp ---------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "clang/Analysis/FlowSensitive/FormulaSerialization.h" +#include "clang/Analysis/FlowSensitive/Arena.h" +#include "clang/Analysis/FlowSensitive/Formula.h" +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/ErrorHandling.h" +#include <cassert> + +namespace clang::dataflow { + +// Returns the leading indicator of operation formulas. `AtomRef` and `Literal` +// are handled differently. +static char compactSigil(Formula::Kind K) { + switch (K) { + case Formula::AtomRef: + case Formula::Literal: + // No sigil. + return '\0'; + case Formula::Not: + return '!'; + case Formula::And: + return '&'; + case Formula::Or: + return '|'; + case Formula::Implies: + return '>'; + case Formula::Equal: + return '='; + } + llvm_unreachable("unhandled formula kind"); +} + +void serializeFormula(const Formula &F, llvm::raw_ostream &OS) { + switch (Formula::numOperands(F.kind())) { + case 0: + switch (F.kind()) { + case Formula::AtomRef: + OS << F.getAtom(); + break; + case Formula::Literal: + OS << (F.literal() ? 'T' : 'F'); + break; + default: + llvm_unreachable("unhandled formula kind"); + } + break; + case 1: + OS << compactSigil(F.kind()); + serializeFormula(*F.operands()[0], OS); + break; + case 2: + OS << compactSigil(F.kind()); + serializeFormula(*F.operands()[0], OS); + serializeFormula(*F.operands()[1], OS); + break; + default: + llvm_unreachable("unhandled formula arity"); + } +} + +static llvm::Expected<const Formula *> +parsePrefix(llvm::StringRef &Str, Arena &A, + llvm::DenseMap<unsigned, Atom> &AtomMap) { + if (Str.empty()) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "unexpected end of input"); + + char Prefix = Str[0]; + Str = Str.drop_front(); + + switch (Prefix) { + case 'T': + return &A.makeLiteral(true); + case 'F': + return &A.makeLiteral(false); + case 'V': { + unsigned AtomID; + if (Str.consumeInteger(10, AtomID)) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "expected atom id"); + auto [It, Inserted] = AtomMap.try_emplace(AtomID, Atom()); + if (Inserted) + It->second = A.makeAtom(); + return &A.makeAtomRef(It->second); + } + case '!': { + auto OperandOrErr = parsePrefix(Str, A, AtomMap); + if (!OperandOrErr) + return OperandOrErr.takeError(); + return &A.makeNot(**OperandOrErr); + } + case '&': { + auto LeftOrErr = parsePrefix(Str, A, AtomMap); + if (!LeftOrErr) + return LeftOrErr.takeError(); + auto RightOrErr = parsePrefix(Str, A, AtomMap); + if (!RightOrErr) + return RightOrErr.takeError(); + return &A.makeAnd(**LeftOrErr, **RightOrErr); + } + case '|': { + auto LeftOrErr = parsePrefix(Str, A, AtomMap); + if (!LeftOrErr) + return LeftOrErr.takeError(); + auto RightOrErr = parsePrefix(Str, A, AtomMap); + if (!RightOrErr) + return RightOrErr.takeError(); + return &A.makeOr(**LeftOrErr, **RightOrErr); + } + case '>': { + auto LeftOrErr = parsePrefix(Str, A, AtomMap); + if (!LeftOrErr) + return LeftOrErr.takeError(); + auto RightOrErr = parsePrefix(Str, A, AtomMap); + if (!RightOrErr) + return RightOrErr.takeError(); + return &A.makeImplies(**LeftOrErr, **RightOrErr); + } + case '=': { + auto LeftOrErr = parsePrefix(Str, A, AtomMap); + if (!LeftOrErr) + return LeftOrErr.takeError(); + auto RightOrErr = parsePrefix(Str, A, AtomMap); + if (!RightOrErr) + return RightOrErr.takeError(); + return &A.makeEquals(**LeftOrErr, **RightOrErr); + } ---------------- ymand wrote:
Done. thx! https://github.com/llvm/llvm-project/pull/152487 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits