16#include "llvm/Support/CommandLine.h"
17#include "llvm/Support/raw_ostream.h"
26llvm::cl::opt<bool> PCWidthAsArg(
27 "pc-width-as-arg", llvm::cl::init(
true),
29 "Print the width as a separate argument, as opposed to a prefix "
30 "to the operation (default=true)"),
34 PCAllWidths(
"pc-all-widths", llvm::cl::init(
false),
35 llvm::cl::desc(
"Print the width of all operations, including "
36 "booleans (default=false)"),
40 PCPrefixWidth(
"pc-prefix-width", llvm::cl::init(
true),
41 llvm::cl::desc(
"Print width with 'w' prefix (default=true)"),
45 PCMultibyteReads(
"pc-multibyte-reads", llvm::cl::init(
true),
46 llvm::cl::desc(
"Print ReadLSB and ReadMSB expressions "
47 "when possible (default=true)"),
50llvm::cl::opt<bool> PCAllConstWidths(
51 "pc-all-const-widths", llvm::cl::init(
false),
53 "Always print the width of constant expressions (default=false)"),
66 llvm::raw_ostream &
os;
94 }
else if (
const ReadExpr *re = dyn_cast<ReadExpr>(e)) {
127 if (!isa<ConstantExpr>(e)) {
132 if (
const ReadExpr *re = dyn_cast<ReadExpr>(e)) {
143 auto head = updates.
head;
154 bool openedList =
false, nextShouldBreak =
false;
155 unsigned outerIndent = PC.
pos;
156 unsigned middleIndent = 0;
157 for (
auto un = head; un; un = un->next) {
159 std::map<const UpdateNode *, unsigned>::iterator it =
164 PC <<
"U" << it->second;
173 openedList = nextShouldBreak =
false;
179 middleIndent = PC.
pos;
186 print(un->index, PC);
189 print(un->value, PC);
192 nextShouldBreak = !(isa<ConstantExpr>(un->index) &&
193 isa<ConstantExpr>(un->value));
221 if (!re || (re->
getWidth() != Expr::Int8))
229 return SubExpr::create(re->
index, base->
index) == offset;
242 assert(e->
getKind() == Expr::Concat);
243 assert(stride == 1 || stride == -1);
249 if (!base || base->
getWidth() != Expr::Int8)
254 ref<Expr> strideExpr = ConstantExpr::alloc(stride, idxWidth);
255 ref<Expr> offset = ConstantExpr::create(0, idxWidth);
260 while (e->
getKind() == Expr::Concat) {
261 offset = AddExpr::create(offset, strideExpr);
268 offset = AddExpr::create(offset, strideExpr);
273 return cast<ReadExpr>(e.
get());
280 bool hasAllByteReads(
const Expr *ep) {
285 return ep->
getWidth() == Expr::Int8;
289 if (!hashAllByteReads(ep->
getKid(i)))
293 default:
return false;
358 if (e->getWidth() == Expr::Bool)
359 PC << (e->isTrue() ?
"true" :
"false");
361 if (PCAllConstWidths)
365 PC <<
"(w" << e->getWidth() <<
" ";
367 if (e->getWidth() <= 64) {
368 PC << e->getZExtValue();
384 std::map<ref<Expr>,
unsigned>::iterator it =
bindings.find(e);
386 PC <<
'N' << it->second;
400 if (PCMultibyteReads && e->
getKind() == Expr::Concat) {
402 const bool isLSB = (base !=
nullptr);
406 PC <<
"(Read" << (isLSB ?
"LSB" :
"MSB");
421 unsigned indent = PC.
pos;
422 if (
const ReadExpr *re = dyn_cast<ReadExpr>(e)) {
424 }
else if (
const ExtractExpr *ee = dyn_cast<ExtractExpr>(e)) {
426 }
else if (e->
getKind() == Expr::Concat || e->
getKind() == Expr::SExt)
481struct ArrayPtrsByName {
482 bool operator()(
const Array *a1,
const Array *a2)
const {
493 const Array *
const *evalArraysBegin,
494 const Array *
const *evalArraysEnd,
495 bool printArrayDecls) {
498 for (
const auto &constraint : constraints)
502 for (
const ref<Expr> *it = evalExprsBegin; it != evalExprsEnd; ++it)
508 if (printArrayDecls) {
509 for (
const Array *
const* it = evalArraysBegin; it != evalArraysEnd; ++it)
511 std::vector<const Array *> sortedArray(p.
usedArrays.begin(),
513 std::sort(sortedArray.begin(), sortedArray.end(), ArrayPtrsByName());
514 for (std::vector<const Array *>::iterator it = sortedArray.begin(),
515 ie = sortedArray.end();
518 PC <<
"array " <<
A->name <<
"[" <<
A->size <<
"]"
519 <<
" : w" <<
A->domain <<
" -> w" <<
A->range <<
" = ";
520 if (
A->isSymbolicArray()) {
524 for (
unsigned i = 0, e =
A->size; i != e; ++i) {
527 PC <<
A->constantValues[i];
538 unsigned indent = PC.
pos;
539 for (
auto it = constraints.
begin(), ie = constraints.
end(); it != ie;) {
551 if (evalExprsBegin != evalExprsEnd) {
554 for (
const ref<Expr> *it = evalExprsBegin; it != evalExprsEnd; ++it) {
555 p.
print(*it, PC,
true);
556 if (it + 1 != evalExprsEnd)
563 if (evalArraysBegin != evalArraysEnd) {
564 if (evalExprsBegin == evalExprsEnd)
569 for (
const Array *
const* it = evalArraysBegin; it != evalArraysEnd; ++it) {
571 if (it + 1 != evalArraysEnd)
std::vector< ref< Expr > >::iterator A
void printExpr(const Expr *ep, PrintContext &PC, unsigned indent, bool printConstWidth=false)
std::set< ref< Expr > > shouldPrint
void setNewline(const std::string &_newline)
std::set< const UpdateNode * > couldPrintUpdates
std::map< const UpdateNode *, unsigned > updateBindings
void printRead(const ReadExpr *re, PrintContext &PC, unsigned indent)
void printUpdateList(const UpdateList &updates, PrintContext &PC)
bool isSimple(const ref< Expr > &e)
bool isVerySimpleUpdate(const UpdateNode *un)
void printWidth(PrintContext &PC, ref< Expr > e)
const ReadExpr * hasOrderedReads(ref< Expr > e, int stride)
void setForceNoLineBreaks(bool _forceNoLineBreaks)
bool shouldPrintWidth(ref< Expr > e)
void print(const ref< Expr > &e, unsigned level=0)
std::map< ref< Expr >, unsigned > bindings
void scanUpdate(const UpdateNode *un)
bool hasSimpleKids(const Expr *ep)
void print(const ref< Expr > &e, PrintContext &PC, bool printConstWidth=false)
void printExtract(const ExtractExpr *ee, PrintContext &PC, unsigned indent)
void scan1(const ref< Expr > &e)
void scan(const ref< Expr > &e)
std::set< const UpdateNode * > shouldPrintUpdates
bool isVerySimple(const ref< Expr > &e)
PPrinter(llvm::raw_ostream &_os)
void printSeparator(PrintContext &PC, bool simple, unsigned indent)
std::set< ref< Expr > > couldPrint
std::set< const Array * > usedArrays
void printConst(const ref< ConstantExpr > &e, PrintContext &PC, bool printWidth)
bool isReadExprAtOffset(ref< Expr > e, const ReadExpr *base, ref< Expr > offset)
unsigned pos
Number of characters on the current line.
void breakLine(unsigned indent=0)
static ref< ConstantExpr > alloc(const llvm::APInt &v)
constraint_iterator end() const
constraint_iterator begin() const
static ExprPPrinter * create(llvm::raw_ostream &os)
static void printSingleExpr(llvm::raw_ostream &os, const ref< Expr > &e)
static void printQuery(llvm::raw_ostream &os, const ConstraintSet &constraints, const ref< Expr > &q, const ref< Expr > *evalExprsBegin=0, const ref< Expr > *evalExprsEnd=0, const Array *const *evalArraysBegin=0, const Array *const *evalArraysEnd=0, bool printArrayDecls=true)
static void printOne(llvm::raw_ostream &os, const char *message, const ref< Expr > &e)
static void printConstraints(llvm::raw_ostream &os, const ConstraintSet &constraints)
Class representing symbolic expressions.
virtual Kind getKind() const =0
virtual Width getWidth() const =0
virtual unsigned getNumKids() const =0
unsigned Width
The type of an expression is simply its width, in bits.
bool isFalse() const
isFalse - Is this the false expression.
virtual ref< Expr > getKid(unsigned i) const =0
Class representing a one byte read from an array.
Class representing a complete list of updates into an array.
ref< UpdateNode > head
pointer to the most recent update node
Class representing a byte update of an array.
const ref< UpdateNode > next
llvm::cl::OptionCategory ExprCat