1 //===- AsmPrinter.cpp - MLIR Assembly Printer Implementation --------------===//
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 // This file implements the MLIR AsmPrinter class, which is used to implement
10 // the various print() methods on the core IR objects.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "mlir/IR/AffineExpr.h"
15 #include "mlir/IR/AffineMap.h"
16 #include "mlir/IR/AsmState.h"
17 #include "mlir/IR/Attributes.h"
18 #include "mlir/IR/BuiltinTypes.h"
19 #include "mlir/IR/Dialect.h"
20 #include "mlir/IR/DialectImplementation.h"
21 #include "mlir/IR/IntegerSet.h"
22 #include "mlir/IR/MLIRContext.h"
23 #include "mlir/IR/OpImplementation.h"
24 #include "mlir/IR/Operation.h"
25 #include "llvm/ADT/APFloat.h"
26 #include "llvm/ADT/DenseMap.h"
27 #include "llvm/ADT/MapVector.h"
28 #include "llvm/ADT/STLExtras.h"
29 #include "llvm/ADT/ScopedHashTable.h"
30 #include "llvm/ADT/SetVector.h"
31 #include "llvm/ADT/SmallString.h"
32 #include "llvm/ADT/StringExtras.h"
33 #include "llvm/ADT/StringSet.h"
34 #include "llvm/ADT/TypeSwitch.h"
35 #include "llvm/Support/CommandLine.h"
36 #include "llvm/Support/Endian.h"
37 #include "llvm/Support/Regex.h"
38 #include "llvm/Support/SaveAndRestore.h"
39 using namespace mlir;
40 using namespace mlir::detail;
41 
42 void Identifier::print(raw_ostream &os) const { os << str(); }
43 
44 void Identifier::dump() const { print(llvm::errs()); }
45 
46 void OperationName::print(raw_ostream &os) const { os << getStringRef(); }
47 
48 void OperationName::dump() const { print(llvm::errs()); }
49 
50 DialectAsmPrinter::~DialectAsmPrinter() {}
51 
52 //===--------------------------------------------------------------------===//
53 // OpAsmPrinter
54 //===--------------------------------------------------------------------===//
55 
56 OpAsmPrinter::~OpAsmPrinter() {}
57 
58 void OpAsmPrinter::printFunctionalType(Operation *op) {
59   auto &os = getStream();
60   os << '(';
61   llvm::interleaveComma(op->getOperands(), os, [&](Value operand) {
62     // Print the types of null values as <<NULL TYPE>>.
63     *this << (operand ? operand.getType() : Type());
64   });
65   os << ") -> ";
66 
67   // Print the result list.  We don't parenthesize single result types unless
68   // it is a function (avoiding a grammar ambiguity).
69   bool wrapped = op->getNumResults() != 1;
70   if (!wrapped && op->getResult(0).getType() &&
71       op->getResult(0).getType().isa<FunctionType>())
72     wrapped = true;
73 
74   if (wrapped)
75     os << '(';
76 
77   llvm::interleaveComma(op->getResults(), os, [&](const OpResult &result) {
78     // Print the types of null values as <<NULL TYPE>>.
79     *this << (result ? result.getType() : Type());
80   });
81 
82   if (wrapped)
83     os << ')';
84 }
85 
86 //===--------------------------------------------------------------------===//
87 // Operation OpAsm interface.
88 //===--------------------------------------------------------------------===//
89 
90 /// The OpAsmOpInterface, see OpAsmInterface.td for more details.
91 #include "mlir/IR/OpAsmInterface.cpp.inc"
92 
93 //===----------------------------------------------------------------------===//
94 // OpPrintingFlags
95 //===----------------------------------------------------------------------===//
96 
97 namespace {
98 /// This struct contains command line options that can be used to initialize
99 /// various bits of the AsmPrinter. This uses a struct wrapper to avoid the need
100 /// for global command line options.
101 struct AsmPrinterOptions {
102   llvm::cl::opt<int64_t> printElementsAttrWithHexIfLarger{
103       "mlir-print-elementsattrs-with-hex-if-larger",
104       llvm::cl::desc(
105           "Print DenseElementsAttrs with a hex string that have "
106           "more elements than the given upper limit (use -1 to disable)")};
107 
108   llvm::cl::opt<unsigned> elideElementsAttrIfLarger{
109       "mlir-elide-elementsattrs-if-larger",
110       llvm::cl::desc("Elide ElementsAttrs with \"...\" that have "
111                      "more elements than the given upper limit")};
112 
113   llvm::cl::opt<bool> printDebugInfoOpt{
114       "mlir-print-debuginfo", llvm::cl::init(false),
115       llvm::cl::desc("Print debug info in MLIR output")};
116 
117   llvm::cl::opt<bool> printPrettyDebugInfoOpt{
118       "mlir-pretty-debuginfo", llvm::cl::init(false),
119       llvm::cl::desc("Print pretty debug info in MLIR output")};
120 
121   // Use the generic op output form in the operation printer even if the custom
122   // form is defined.
123   llvm::cl::opt<bool> printGenericOpFormOpt{
124       "mlir-print-op-generic", llvm::cl::init(false),
125       llvm::cl::desc("Print the generic op form"), llvm::cl::Hidden};
126 
127   llvm::cl::opt<bool> printLocalScopeOpt{
128       "mlir-print-local-scope", llvm::cl::init(false),
129       llvm::cl::desc("Print assuming in local scope by default"),
130       llvm::cl::Hidden};
131 };
132 } // end anonymous namespace
133 
134 static llvm::ManagedStatic<AsmPrinterOptions> clOptions;
135 
136 /// Register a set of useful command-line options that can be used to configure
137 /// various flags within the AsmPrinter.
138 void mlir::registerAsmPrinterCLOptions() {
139   // Make sure that the options struct has been initialized.
140   *clOptions;
141 }
142 
143 /// Initialize the printing flags with default supplied by the cl::opts above.
144 OpPrintingFlags::OpPrintingFlags()
145     : printDebugInfoFlag(false), printDebugInfoPrettyFormFlag(false),
146       printGenericOpFormFlag(false), printLocalScope(false) {
147   // Initialize based upon command line options, if they are available.
148   if (!clOptions.isConstructed())
149     return;
150   if (clOptions->elideElementsAttrIfLarger.getNumOccurrences())
151     elementsAttrElementLimit = clOptions->elideElementsAttrIfLarger;
152   printDebugInfoFlag = clOptions->printDebugInfoOpt;
153   printDebugInfoPrettyFormFlag = clOptions->printPrettyDebugInfoOpt;
154   printGenericOpFormFlag = clOptions->printGenericOpFormOpt;
155   printLocalScope = clOptions->printLocalScopeOpt;
156 }
157 
158 /// Enable the elision of large elements attributes, by printing a '...'
159 /// instead of the element data, when the number of elements is greater than
160 /// `largeElementLimit`. Note: The IR generated with this option is not
161 /// parsable.
162 OpPrintingFlags &
163 OpPrintingFlags::elideLargeElementsAttrs(int64_t largeElementLimit) {
164   elementsAttrElementLimit = largeElementLimit;
165   return *this;
166 }
167 
168 /// Enable printing of debug information. If 'prettyForm' is set to true,
169 /// debug information is printed in a more readable 'pretty' form.
170 OpPrintingFlags &OpPrintingFlags::enableDebugInfo(bool prettyForm) {
171   printDebugInfoFlag = true;
172   printDebugInfoPrettyFormFlag = prettyForm;
173   return *this;
174 }
175 
176 /// Always print operations in the generic form.
177 OpPrintingFlags &OpPrintingFlags::printGenericOpForm() {
178   printGenericOpFormFlag = true;
179   return *this;
180 }
181 
182 /// Use local scope when printing the operation. This allows for using the
183 /// printer in a more localized and thread-safe setting, but may not necessarily
184 /// be identical of what the IR will look like when dumping the full module.
185 OpPrintingFlags &OpPrintingFlags::useLocalScope() {
186   printLocalScope = true;
187   return *this;
188 }
189 
190 /// Return if the given ElementsAttr should be elided.
191 bool OpPrintingFlags::shouldElideElementsAttr(ElementsAttr attr) const {
192   return elementsAttrElementLimit.hasValue() &&
193          *elementsAttrElementLimit < int64_t(attr.getNumElements()) &&
194          !attr.isa<SplatElementsAttr>();
195 }
196 
197 /// Return the size limit for printing large ElementsAttr.
198 Optional<int64_t> OpPrintingFlags::getLargeElementsAttrLimit() const {
199   return elementsAttrElementLimit;
200 }
201 
202 /// Return if debug information should be printed.
203 bool OpPrintingFlags::shouldPrintDebugInfo() const {
204   return printDebugInfoFlag;
205 }
206 
207 /// Return if debug information should be printed in the pretty form.
208 bool OpPrintingFlags::shouldPrintDebugInfoPrettyForm() const {
209   return printDebugInfoPrettyFormFlag;
210 }
211 
212 /// Return if operations should be printed in the generic form.
213 bool OpPrintingFlags::shouldPrintGenericOpForm() const {
214   return printGenericOpFormFlag;
215 }
216 
217 /// Return if the printer should use local scope when dumping the IR.
218 bool OpPrintingFlags::shouldUseLocalScope() const { return printLocalScope; }
219 
220 /// Returns true if an ElementsAttr with the given number of elements should be
221 /// printed with hex.
222 static bool shouldPrintElementsAttrWithHex(int64_t numElements) {
223   // Check to see if a command line option was provided for the limit.
224   if (clOptions.isConstructed()) {
225     if (clOptions->printElementsAttrWithHexIfLarger.getNumOccurrences()) {
226       // -1 is used to disable hex printing.
227       if (clOptions->printElementsAttrWithHexIfLarger == -1)
228         return false;
229       return numElements > clOptions->printElementsAttrWithHexIfLarger;
230     }
231   }
232 
233   // Otherwise, default to printing with hex if the number of elements is >100.
234   return numElements > 100;
235 }
236 
237 //===----------------------------------------------------------------------===//
238 // NewLineCounter
239 //===----------------------------------------------------------------------===//
240 
241 namespace {
242 /// This class is a simple formatter that emits a new line when inputted into a
243 /// stream, that enables counting the number of newlines emitted. This class
244 /// should be used whenever emitting newlines in the printer.
245 struct NewLineCounter {
246   unsigned curLine = 1;
247 };
248 } // end anonymous namespace
249 
250 static raw_ostream &operator<<(raw_ostream &os, NewLineCounter &newLine) {
251   ++newLine.curLine;
252   return os << '\n';
253 }
254 
255 //===----------------------------------------------------------------------===//
256 // AliasInitializer
257 //===----------------------------------------------------------------------===//
258 
259 namespace {
260 /// This class represents a specific instance of a symbol Alias.
261 class SymbolAlias {
262 public:
263   SymbolAlias(StringRef name, bool isDeferrable)
264       : name(name), suffixIndex(0), hasSuffixIndex(false),
265         isDeferrable(isDeferrable) {}
266   SymbolAlias(StringRef name, uint32_t suffixIndex, bool isDeferrable)
267       : name(name), suffixIndex(suffixIndex), hasSuffixIndex(true),
268         isDeferrable(isDeferrable) {}
269 
270   /// Print this alias to the given stream.
271   void print(raw_ostream &os) const {
272     os << name;
273     if (hasSuffixIndex)
274       os << suffixIndex;
275   }
276 
277   /// Returns true if this alias supports deferred resolution when parsing.
278   bool canBeDeferred() const { return isDeferrable; }
279 
280 private:
281   /// The main name of the alias.
282   StringRef name;
283   /// The optional suffix index of the alias, if multiple aliases had the same
284   /// name.
285   uint32_t suffixIndex : 30;
286   /// A flag indicating whether this alias has a suffix or not.
287   bool hasSuffixIndex : 1;
288   /// A flag indicating whether this alias may be deferred or not.
289   bool isDeferrable : 1;
290 };
291 
292 /// This class represents a utility that initializes the set of attribute and
293 /// type aliases, without the need to store the extra information within the
294 /// main AliasState class or pass it around via function arguments.
295 class AliasInitializer {
296 public:
297   AliasInitializer(
298       DialectInterfaceCollection<OpAsmDialectInterface> &interfaces,
299       llvm::BumpPtrAllocator &aliasAllocator)
300       : interfaces(interfaces), aliasAllocator(aliasAllocator),
301         aliasOS(aliasBuffer) {}
302 
303   void initialize(Operation *op, const OpPrintingFlags &printerFlags,
304                   llvm::MapVector<Attribute, SymbolAlias> &attrToAlias,
305                   llvm::MapVector<Type, SymbolAlias> &typeToAlias);
306 
307   /// Visit the given attribute to see if it has an alias. `canBeDeferred` is
308   /// set to true if the originator of this attribute can resolve the alias
309   /// after parsing has completed (e.g. in the case of operation locations).
310   void visit(Attribute attr, bool canBeDeferred = false);
311 
312   /// Visit the given type to see if it has an alias.
313   void visit(Type type);
314 
315 private:
316   /// Try to generate an alias for the provided symbol. If an alias is
317   /// generated, the provided alias mapping and reverse mapping are updated.
318   /// Returns success if an alias was generated, failure otherwise.
319   template <typename T>
320   LogicalResult
321   generateAlias(T symbol,
322                 llvm::MapVector<StringRef, std::vector<T>> &aliasToSymbol);
323 
324   /// The set of asm interfaces within the context.
325   DialectInterfaceCollection<OpAsmDialectInterface> &interfaces;
326 
327   /// Mapping between an alias and the set of symbols mapped to it.
328   llvm::MapVector<StringRef, std::vector<Attribute>> aliasToAttr;
329   llvm::MapVector<StringRef, std::vector<Type>> aliasToType;
330 
331   /// An allocator used for alias names.
332   llvm::BumpPtrAllocator &aliasAllocator;
333 
334   /// The set of visited attributes.
335   DenseSet<Attribute> visitedAttributes;
336 
337   /// The set of attributes that have aliases *and* can be deferred.
338   DenseSet<Attribute> deferrableAttributes;
339 
340   /// The set of visited types.
341   DenseSet<Type> visitedTypes;
342 
343   /// Storage and stream used when generating an alias.
344   SmallString<32> aliasBuffer;
345   llvm::raw_svector_ostream aliasOS;
346 };
347 
348 /// This class implements a dummy OpAsmPrinter that doesn't print any output,
349 /// and merely collects the attributes and types that *would* be printed in a
350 /// normal print invocation so that we can generate proper aliases. This allows
351 /// for us to generate aliases only for the attributes and types that would be
352 /// in the output, and trims down unnecessary output.
353 class DummyAliasOperationPrinter : private OpAsmPrinter {
354 public:
355   explicit DummyAliasOperationPrinter(const OpPrintingFlags &flags,
356                                       AliasInitializer &initializer)
357       : printerFlags(flags), initializer(initializer) {}
358 
359   /// Print the given operation.
360   void print(Operation *op) {
361     // Visit the operation location.
362     if (printerFlags.shouldPrintDebugInfo())
363       initializer.visit(op->getLoc(), /*canBeDeferred=*/true);
364 
365     // If requested, always print the generic form.
366     if (!printerFlags.shouldPrintGenericOpForm()) {
367       // Check to see if this is a known operation.  If so, use the registered
368       // custom printer hook.
369       if (auto *opInfo = op->getAbstractOperation()) {
370         opInfo->printAssembly(op, *this);
371         return;
372       }
373     }
374 
375     // Otherwise print with the generic assembly form.
376     printGenericOp(op);
377   }
378 
379 private:
380   /// Print the given operation in the generic form.
381   void printGenericOp(Operation *op) override {
382     // Consider nested operations for aliases.
383     if (op->getNumRegions() != 0) {
384       for (Region &region : op->getRegions())
385         printRegion(region, /*printEntryBlockArgs=*/true,
386                     /*printBlockTerminators=*/true);
387     }
388 
389     // Visit all the types used in the operation.
390     for (Type type : op->getOperandTypes())
391       printType(type);
392     for (Type type : op->getResultTypes())
393       printType(type);
394 
395     // Consider the attributes of the operation for aliases.
396     for (const NamedAttribute &attr : op->getAttrs())
397       printAttribute(attr.second);
398   }
399 
400   /// Print the given block. If 'printBlockArgs' is false, the arguments of the
401   /// block are not printed. If 'printBlockTerminator' is false, the terminator
402   /// operation of the block is not printed.
403   void print(Block *block, bool printBlockArgs = true,
404              bool printBlockTerminator = true) {
405     // Consider the types of the block arguments for aliases if 'printBlockArgs'
406     // is set to true.
407     if (printBlockArgs) {
408       for (Type type : block->getArgumentTypes())
409         printType(type);
410     }
411 
412     // Consider the operations within this block, ignoring the terminator if
413     // requested.
414     auto range = llvm::make_range(
415         block->begin(), std::prev(block->end(), printBlockTerminator ? 0 : 1));
416     for (Operation &op : range)
417       print(&op);
418   }
419 
420   /// Print the given region.
421   void printRegion(Region &region, bool printEntryBlockArgs,
422                    bool printBlockTerminators,
423                    bool printEmptyBlock = false) override {
424     if (region.empty())
425       return;
426 
427     auto *entryBlock = &region.front();
428     print(entryBlock, printEntryBlockArgs, printBlockTerminators);
429     for (Block &b : llvm::drop_begin(region, 1))
430       print(&b);
431   }
432 
433   /// Consider the given type to be printed for an alias.
434   void printType(Type type) override { initializer.visit(type); }
435 
436   /// Consider the given attribute to be printed for an alias.
437   void printAttribute(Attribute attr) override { initializer.visit(attr); }
438   void printAttributeWithoutType(Attribute attr) override {
439     printAttribute(attr);
440   }
441 
442   /// Print the given set of attributes with names not included within
443   /// 'elidedAttrs'.
444   void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
445                              ArrayRef<StringRef> elidedAttrs = {}) override {
446     if (attrs.empty())
447       return;
448     if (elidedAttrs.empty()) {
449       for (const NamedAttribute &attr : attrs)
450         printAttribute(attr.second);
451       return;
452     }
453     llvm::SmallDenseSet<StringRef> elidedAttrsSet(elidedAttrs.begin(),
454                                                   elidedAttrs.end());
455     for (const NamedAttribute &attr : attrs)
456       if (!elidedAttrsSet.contains(attr.first.strref()))
457         printAttribute(attr.second);
458   }
459   void printOptionalAttrDictWithKeyword(
460       ArrayRef<NamedAttribute> attrs,
461       ArrayRef<StringRef> elidedAttrs = {}) override {
462     printOptionalAttrDict(attrs, elidedAttrs);
463   }
464 
465   /// Return a null stream as the output stream, this will ignore any data fed
466   /// to it.
467   raw_ostream &getStream() const override { return os; }
468 
469   /// The following are hooks of `OpAsmPrinter` that are not necessary for
470   /// determining potential aliases.
471   void printAffineMapOfSSAIds(AffineMapAttr, ValueRange) override {}
472   void printAffineExprOfSSAIds(AffineExpr, ValueRange, ValueRange) override {}
473   void printNewline() override {}
474   void printOperand(Value) override {}
475   void printOperand(Value, raw_ostream &os) override {
476     // Users expect the output string to have at least the prefixed % to signal
477     // a value name. To maintain this invariant, emit a name even if it is
478     // guaranteed to go unused.
479     os << "%";
480   }
481   void printSymbolName(StringRef) override {}
482   void printSuccessor(Block *) override {}
483   void printSuccessorAndUseList(Block *, ValueRange) override {}
484   void shadowRegionArgs(Region &, ValueRange) override {}
485 
486   /// The printer flags to use when determining potential aliases.
487   const OpPrintingFlags &printerFlags;
488 
489   /// The initializer to use when identifying aliases.
490   AliasInitializer &initializer;
491 
492   /// A dummy output stream.
493   mutable llvm::raw_null_ostream os;
494 };
495 } // end anonymous namespace
496 
497 /// Sanitize the given name such that it can be used as a valid identifier. If
498 /// the string needs to be modified in any way, the provided buffer is used to
499 /// store the new copy,
500 static StringRef sanitizeIdentifier(StringRef name, SmallString<16> &buffer,
501                                     StringRef allowedPunctChars = "$._-",
502                                     bool allowTrailingDigit = true) {
503   assert(!name.empty() && "Shouldn't have an empty name here");
504 
505   auto copyNameToBuffer = [&] {
506     for (char ch : name) {
507       if (llvm::isAlnum(ch) || allowedPunctChars.contains(ch))
508         buffer.push_back(ch);
509       else if (ch == ' ')
510         buffer.push_back('_');
511       else
512         buffer.append(llvm::utohexstr((unsigned char)ch));
513     }
514   };
515 
516   // Check to see if this name is valid. If it starts with a digit, then it
517   // could conflict with the autogenerated numeric ID's, so add an underscore
518   // prefix to avoid problems.
519   if (isdigit(name[0])) {
520     buffer.push_back('_');
521     copyNameToBuffer();
522     return buffer;
523   }
524 
525   // If the name ends with a trailing digit, add a '_' to avoid potential
526   // conflicts with autogenerated ID's.
527   if (!allowTrailingDigit && isdigit(name.back())) {
528     copyNameToBuffer();
529     buffer.push_back('_');
530     return buffer;
531   }
532 
533   // Check to see that the name consists of only valid identifier characters.
534   for (char ch : name) {
535     if (!llvm::isAlnum(ch) && !allowedPunctChars.contains(ch)) {
536       copyNameToBuffer();
537       return buffer;
538     }
539   }
540 
541   // If there are no invalid characters, return the original name.
542   return name;
543 }
544 
545 /// Given a collection of aliases and symbols, initialize a mapping from a
546 /// symbol to a given alias.
547 template <typename T>
548 static void
549 initializeAliases(llvm::MapVector<StringRef, std::vector<T>> &aliasToSymbol,
550                   llvm::MapVector<T, SymbolAlias> &symbolToAlias,
551                   DenseSet<T> *deferrableAliases = nullptr) {
552   std::vector<std::pair<StringRef, std::vector<T>>> aliases =
553       aliasToSymbol.takeVector();
554   llvm::array_pod_sort(aliases.begin(), aliases.end(),
555                        [](const auto *lhs, const auto *rhs) {
556                          return lhs->first.compare(rhs->first);
557                        });
558 
559   for (auto &it : aliases) {
560     // If there is only one instance for this alias, use the name directly.
561     if (it.second.size() == 1) {
562       T symbol = it.second.front();
563       bool isDeferrable = deferrableAliases && deferrableAliases->count(symbol);
564       symbolToAlias.insert({symbol, SymbolAlias(it.first, isDeferrable)});
565       continue;
566     }
567     // Otherwise, add the index to the name.
568     for (int i = 0, e = it.second.size(); i < e; ++i) {
569       T symbol = it.second[i];
570       bool isDeferrable = deferrableAliases && deferrableAliases->count(symbol);
571       symbolToAlias.insert({symbol, SymbolAlias(it.first, i, isDeferrable)});
572     }
573   }
574 }
575 
576 void AliasInitializer::initialize(
577     Operation *op, const OpPrintingFlags &printerFlags,
578     llvm::MapVector<Attribute, SymbolAlias> &attrToAlias,
579     llvm::MapVector<Type, SymbolAlias> &typeToAlias) {
580   // Use a dummy printer when walking the IR so that we can collect the
581   // attributes/types that will actually be used during printing when
582   // considering aliases.
583   DummyAliasOperationPrinter aliasPrinter(printerFlags, *this);
584   aliasPrinter.print(op);
585 
586   // Initialize the aliases sorted by name.
587   initializeAliases(aliasToAttr, attrToAlias, &deferrableAttributes);
588   initializeAliases(aliasToType, typeToAlias);
589 }
590 
591 void AliasInitializer::visit(Attribute attr, bool canBeDeferred) {
592   if (!visitedAttributes.insert(attr).second) {
593     // If this attribute already has an alias and this instance can't be
594     // deferred, make sure that the alias isn't deferred.
595     if (!canBeDeferred)
596       deferrableAttributes.erase(attr);
597     return;
598   }
599 
600   // Try to generate an alias for this attribute.
601   if (succeeded(generateAlias(attr, aliasToAttr))) {
602     if (canBeDeferred)
603       deferrableAttributes.insert(attr);
604     return;
605   }
606 
607   if (auto arrayAttr = attr.dyn_cast<ArrayAttr>()) {
608     for (Attribute element : arrayAttr.getValue())
609       visit(element);
610   } else if (auto dictAttr = attr.dyn_cast<DictionaryAttr>()) {
611     for (const NamedAttribute &attr : dictAttr)
612       visit(attr.second);
613   } else if (auto typeAttr = attr.dyn_cast<TypeAttr>()) {
614     visit(typeAttr.getValue());
615   }
616 }
617 
618 void AliasInitializer::visit(Type type) {
619   if (!visitedTypes.insert(type).second)
620     return;
621 
622   // Try to generate an alias for this type.
623   if (succeeded(generateAlias(type, aliasToType)))
624     return;
625 
626   // Visit several subtypes that contain types or attributes.
627   if (auto funcType = type.dyn_cast<FunctionType>()) {
628     // Visit input and result types for functions.
629     for (auto input : funcType.getInputs())
630       visit(input);
631     for (auto result : funcType.getResults())
632       visit(result);
633   } else if (auto shapedType = type.dyn_cast<ShapedType>()) {
634     visit(shapedType.getElementType());
635 
636     // Visit affine maps in memref type.
637     if (auto memref = type.dyn_cast<MemRefType>())
638       for (auto map : memref.getAffineMaps())
639         visit(AffineMapAttr::get(map));
640   }
641 }
642 
643 template <typename T>
644 LogicalResult AliasInitializer::generateAlias(
645     T symbol, llvm::MapVector<StringRef, std::vector<T>> &aliasToSymbol) {
646   SmallString<16> tempBuffer;
647   for (const auto &interface : interfaces) {
648     if (failed(interface.getAlias(symbol, aliasOS)))
649       continue;
650     StringRef name = aliasOS.str();
651     assert(!name.empty() && "expected valid alias name");
652     name = sanitizeIdentifier(name, tempBuffer, /*allowedPunctChars=*/"$_-",
653                               /*allowTrailingDigit=*/false);
654     name = name.copy(aliasAllocator);
655 
656     aliasToSymbol[name].push_back(symbol);
657     aliasBuffer.clear();
658     return success();
659   }
660   return failure();
661 }
662 
663 //===----------------------------------------------------------------------===//
664 // AliasState
665 //===----------------------------------------------------------------------===//
666 
667 namespace {
668 /// This class manages the state for type and attribute aliases.
669 class AliasState {
670 public:
671   // Initialize the internal aliases.
672   void
673   initialize(Operation *op, const OpPrintingFlags &printerFlags,
674              DialectInterfaceCollection<OpAsmDialectInterface> &interfaces);
675 
676   /// Get an alias for the given attribute if it has one and print it in `os`.
677   /// Returns success if an alias was printed, failure otherwise.
678   LogicalResult getAlias(Attribute attr, raw_ostream &os) const;
679 
680   /// Get an alias for the given type if it has one and print it in `os`.
681   /// Returns success if an alias was printed, failure otherwise.
682   LogicalResult getAlias(Type ty, raw_ostream &os) const;
683 
684   /// Print all of the referenced aliases that can not be resolved in a deferred
685   /// manner.
686   void printNonDeferredAliases(raw_ostream &os, NewLineCounter &newLine) const {
687     printAliases(os, newLine, /*isDeferred=*/false);
688   }
689 
690   /// Print all of the referenced aliases that support deferred resolution.
691   void printDeferredAliases(raw_ostream &os, NewLineCounter &newLine) const {
692     printAliases(os, newLine, /*isDeferred=*/true);
693   }
694 
695 private:
696   /// Print all of the referenced aliases that support the provided resolution
697   /// behavior.
698   void printAliases(raw_ostream &os, NewLineCounter &newLine,
699                     bool isDeferred) const;
700 
701   /// Mapping between attribute and alias.
702   llvm::MapVector<Attribute, SymbolAlias> attrToAlias;
703   /// Mapping between type and alias.
704   llvm::MapVector<Type, SymbolAlias> typeToAlias;
705 
706   /// An allocator used for alias names.
707   llvm::BumpPtrAllocator aliasAllocator;
708 };
709 } // end anonymous namespace
710 
711 void AliasState::initialize(
712     Operation *op, const OpPrintingFlags &printerFlags,
713     DialectInterfaceCollection<OpAsmDialectInterface> &interfaces) {
714   AliasInitializer initializer(interfaces, aliasAllocator);
715   initializer.initialize(op, printerFlags, attrToAlias, typeToAlias);
716 }
717 
718 LogicalResult AliasState::getAlias(Attribute attr, raw_ostream &os) const {
719   auto it = attrToAlias.find(attr);
720   if (it == attrToAlias.end())
721     return failure();
722   it->second.print(os << '#');
723   return success();
724 }
725 
726 LogicalResult AliasState::getAlias(Type ty, raw_ostream &os) const {
727   auto it = typeToAlias.find(ty);
728   if (it == typeToAlias.end())
729     return failure();
730 
731   it->second.print(os << '!');
732   return success();
733 }
734 
735 void AliasState::printAliases(raw_ostream &os, NewLineCounter &newLine,
736                               bool isDeferred) const {
737   auto filterFn = [=](const auto &aliasIt) {
738     return aliasIt.second.canBeDeferred() == isDeferred;
739   };
740   for (const auto &it : llvm::make_filter_range(attrToAlias, filterFn)) {
741     it.second.print(os << '#');
742     os << " = " << it.first << newLine;
743   }
744   for (const auto &it : llvm::make_filter_range(typeToAlias, filterFn)) {
745     it.second.print(os << '!');
746     os << " = type " << it.first << newLine;
747   }
748 }
749 
750 //===----------------------------------------------------------------------===//
751 // SSANameState
752 //===----------------------------------------------------------------------===//
753 
754 namespace {
755 /// This class manages the state of SSA value names.
756 class SSANameState {
757 public:
758   /// A sentinel value used for values with names set.
759   enum : unsigned { NameSentinel = ~0U };
760 
761   SSANameState(Operation *op,
762                DialectInterfaceCollection<OpAsmDialectInterface> &interfaces);
763 
764   /// Print the SSA identifier for the given value to 'stream'. If
765   /// 'printResultNo' is true, it also presents the result number ('#' number)
766   /// of this value.
767   void printValueID(Value value, bool printResultNo, raw_ostream &stream) const;
768 
769   /// Return the result indices for each of the result groups registered by this
770   /// operation, or empty if none exist.
771   ArrayRef<int> getOpResultGroups(Operation *op);
772 
773   /// Get the ID for the given block.
774   unsigned getBlockID(Block *block);
775 
776   /// Renumber the arguments for the specified region to the same names as the
777   /// SSA values in namesToUse. See OperationPrinter::shadowRegionArgs for
778   /// details.
779   void shadowRegionArgs(Region &region, ValueRange namesToUse);
780 
781 private:
782   /// Number the SSA values within the given IR unit.
783   void numberValuesInRegion(
784       Region &region,
785       DialectInterfaceCollection<OpAsmDialectInterface> &interfaces);
786   void numberValuesInBlock(
787       Block &block,
788       DialectInterfaceCollection<OpAsmDialectInterface> &interfaces);
789   void numberValuesInOp(
790       Operation &op,
791       DialectInterfaceCollection<OpAsmDialectInterface> &interfaces);
792 
793   /// Given a result of an operation 'result', find the result group head
794   /// 'lookupValue' and the result of 'result' within that group in
795   /// 'lookupResultNo'. 'lookupResultNo' is only filled in if the result group
796   /// has more than 1 result.
797   void getResultIDAndNumber(OpResult result, Value &lookupValue,
798                             Optional<int> &lookupResultNo) const;
799 
800   /// Set a special value name for the given value.
801   void setValueName(Value value, StringRef name);
802 
803   /// Uniques the given value name within the printer. If the given name
804   /// conflicts, it is automatically renamed.
805   StringRef uniqueValueName(StringRef name);
806 
807   /// This is the value ID for each SSA value. If this returns NameSentinel,
808   /// then the valueID has an entry in valueNames.
809   DenseMap<Value, unsigned> valueIDs;
810   DenseMap<Value, StringRef> valueNames;
811 
812   /// This is a map of operations that contain multiple named result groups,
813   /// i.e. there may be multiple names for the results of the operation. The
814   /// value of this map are the result numbers that start a result group.
815   DenseMap<Operation *, SmallVector<int, 1>> opResultGroups;
816 
817   /// This is the block ID for each block in the current.
818   DenseMap<Block *, unsigned> blockIDs;
819 
820   /// This keeps track of all of the non-numeric names that are in flight,
821   /// allowing us to check for duplicates.
822   /// Note: the value of the map is unused.
823   llvm::ScopedHashTable<StringRef, char> usedNames;
824   llvm::BumpPtrAllocator usedNameAllocator;
825 
826   /// This is the next value ID to assign in numbering.
827   unsigned nextValueID = 0;
828   /// This is the next ID to assign to a region entry block argument.
829   unsigned nextArgumentID = 0;
830   /// This is the next ID to assign when a name conflict is detected.
831   unsigned nextConflictID = 0;
832 };
833 } // end anonymous namespace
834 
835 SSANameState::SSANameState(
836     Operation *op,
837     DialectInterfaceCollection<OpAsmDialectInterface> &interfaces) {
838   llvm::ScopedHashTable<StringRef, char>::ScopeTy usedNamesScope(usedNames);
839   numberValuesInOp(*op, interfaces);
840 
841   for (auto &region : op->getRegions())
842     numberValuesInRegion(region, interfaces);
843 }
844 
845 void SSANameState::printValueID(Value value, bool printResultNo,
846                                 raw_ostream &stream) const {
847   if (!value) {
848     stream << "<<NULL>>";
849     return;
850   }
851 
852   Optional<int> resultNo;
853   auto lookupValue = value;
854 
855   // If this is an operation result, collect the head lookup value of the result
856   // group and the result number of 'result' within that group.
857   if (OpResult result = value.dyn_cast<OpResult>())
858     getResultIDAndNumber(result, lookupValue, resultNo);
859 
860   auto it = valueIDs.find(lookupValue);
861   if (it == valueIDs.end()) {
862     stream << "<<UNKNOWN SSA VALUE>>";
863     return;
864   }
865 
866   stream << '%';
867   if (it->second != NameSentinel) {
868     stream << it->second;
869   } else {
870     auto nameIt = valueNames.find(lookupValue);
871     assert(nameIt != valueNames.end() && "Didn't have a name entry?");
872     stream << nameIt->second;
873   }
874 
875   if (resultNo.hasValue() && printResultNo)
876     stream << '#' << resultNo;
877 }
878 
879 ArrayRef<int> SSANameState::getOpResultGroups(Operation *op) {
880   auto it = opResultGroups.find(op);
881   return it == opResultGroups.end() ? ArrayRef<int>() : it->second;
882 }
883 
884 unsigned SSANameState::getBlockID(Block *block) {
885   auto it = blockIDs.find(block);
886   return it != blockIDs.end() ? it->second : NameSentinel;
887 }
888 
889 void SSANameState::shadowRegionArgs(Region &region, ValueRange namesToUse) {
890   assert(!region.empty() && "cannot shadow arguments of an empty region");
891   assert(region.getNumArguments() == namesToUse.size() &&
892          "incorrect number of names passed in");
893   assert(region.getParentOp()->hasTrait<OpTrait::IsIsolatedFromAbove>() &&
894          "only KnownIsolatedFromAbove ops can shadow names");
895 
896   SmallVector<char, 16> nameStr;
897   for (unsigned i = 0, e = namesToUse.size(); i != e; ++i) {
898     auto nameToUse = namesToUse[i];
899     if (nameToUse == nullptr)
900       continue;
901     auto nameToReplace = region.getArgument(i);
902 
903     nameStr.clear();
904     llvm::raw_svector_ostream nameStream(nameStr);
905     printValueID(nameToUse, /*printResultNo=*/true, nameStream);
906 
907     // Entry block arguments should already have a pretty "arg" name.
908     assert(valueIDs[nameToReplace] == NameSentinel);
909 
910     // Use the name without the leading %.
911     auto name = StringRef(nameStream.str()).drop_front();
912 
913     // Overwrite the name.
914     valueNames[nameToReplace] = name.copy(usedNameAllocator);
915   }
916 }
917 
918 void SSANameState::numberValuesInRegion(
919     Region &region,
920     DialectInterfaceCollection<OpAsmDialectInterface> &interfaces) {
921   // Save the current value ids to allow for numbering values in sibling regions
922   // the same.
923   llvm::SaveAndRestore<unsigned> valueIDSaver(nextValueID);
924   llvm::SaveAndRestore<unsigned> argumentIDSaver(nextArgumentID);
925   llvm::SaveAndRestore<unsigned> conflictIDSaver(nextConflictID);
926 
927   // Push a new used names scope.
928   llvm::ScopedHashTable<StringRef, char>::ScopeTy usedNamesScope(usedNames);
929 
930   // Number the values within this region in a breadth-first order.
931   unsigned nextBlockID = 0;
932   for (auto &block : region) {
933     // Each block gets a unique ID, and all of the operations within it get
934     // numbered as well.
935     blockIDs[&block] = nextBlockID++;
936     numberValuesInBlock(block, interfaces);
937   }
938 
939   // After that we traverse the nested regions.
940   // TODO: Rework this loop to not use recursion.
941   for (auto &block : region) {
942     for (auto &op : block)
943       for (auto &nestedRegion : op.getRegions())
944         numberValuesInRegion(nestedRegion, interfaces);
945   }
946 }
947 
948 void SSANameState::numberValuesInBlock(
949     Block &block,
950     DialectInterfaceCollection<OpAsmDialectInterface> &interfaces) {
951   auto setArgNameFn = [&](Value arg, StringRef name) {
952     assert(!valueIDs.count(arg) && "arg numbered multiple times");
953     assert(arg.cast<BlockArgument>().getOwner() == &block &&
954            "arg not defined in 'block'");
955     setValueName(arg, name);
956   };
957 
958   bool isEntryBlock = block.isEntryBlock();
959   if (isEntryBlock) {
960     if (auto *op = block.getParentOp()) {
961       if (auto asmInterface = interfaces.getInterfaceFor(op->getDialect()))
962         asmInterface->getAsmBlockArgumentNames(&block, setArgNameFn);
963     }
964   }
965 
966   // Number the block arguments. We give entry block arguments a special name
967   // 'arg'.
968   SmallString<32> specialNameBuffer(isEntryBlock ? "arg" : "");
969   llvm::raw_svector_ostream specialName(specialNameBuffer);
970   for (auto arg : block.getArguments()) {
971     if (valueIDs.count(arg))
972       continue;
973     if (isEntryBlock) {
974       specialNameBuffer.resize(strlen("arg"));
975       specialName << nextArgumentID++;
976     }
977     setValueName(arg, specialName.str());
978   }
979 
980   // Number the operations in this block.
981   for (auto &op : block)
982     numberValuesInOp(op, interfaces);
983 }
984 
985 void SSANameState::numberValuesInOp(
986     Operation &op,
987     DialectInterfaceCollection<OpAsmDialectInterface> &interfaces) {
988   unsigned numResults = op.getNumResults();
989   if (numResults == 0)
990     return;
991   Value resultBegin = op.getResult(0);
992 
993   // Function used to set the special result names for the operation.
994   SmallVector<int, 2> resultGroups(/*Size=*/1, /*Value=*/0);
995   auto setResultNameFn = [&](Value result, StringRef name) {
996     assert(!valueIDs.count(result) && "result numbered multiple times");
997     assert(result.getDefiningOp() == &op && "result not defined by 'op'");
998     setValueName(result, name);
999 
1000     // Record the result number for groups not anchored at 0.
1001     if (int resultNo = result.cast<OpResult>().getResultNumber())
1002       resultGroups.push_back(resultNo);
1003   };
1004   if (OpAsmOpInterface asmInterface = dyn_cast<OpAsmOpInterface>(&op))
1005     asmInterface.getAsmResultNames(setResultNameFn);
1006   else if (auto *asmInterface = interfaces.getInterfaceFor(op.getDialect()))
1007     asmInterface->getAsmResultNames(&op, setResultNameFn);
1008 
1009   // If the first result wasn't numbered, give it a default number.
1010   if (valueIDs.try_emplace(resultBegin, nextValueID).second)
1011     ++nextValueID;
1012 
1013   // If this operation has multiple result groups, mark it.
1014   if (resultGroups.size() != 1) {
1015     llvm::array_pod_sort(resultGroups.begin(), resultGroups.end());
1016     opResultGroups.try_emplace(&op, std::move(resultGroups));
1017   }
1018 }
1019 
1020 void SSANameState::getResultIDAndNumber(OpResult result, Value &lookupValue,
1021                                         Optional<int> &lookupResultNo) const {
1022   Operation *owner = result.getOwner();
1023   if (owner->getNumResults() == 1)
1024     return;
1025   int resultNo = result.getResultNumber();
1026 
1027   // If this operation has multiple result groups, we will need to find the
1028   // one corresponding to this result.
1029   auto resultGroupIt = opResultGroups.find(owner);
1030   if (resultGroupIt == opResultGroups.end()) {
1031     // If not, just use the first result.
1032     lookupResultNo = resultNo;
1033     lookupValue = owner->getResult(0);
1034     return;
1035   }
1036 
1037   // Find the correct index using a binary search, as the groups are ordered.
1038   ArrayRef<int> resultGroups = resultGroupIt->second;
1039   auto it = llvm::upper_bound(resultGroups, resultNo);
1040   int groupResultNo = 0, groupSize = 0;
1041 
1042   // If there are no smaller elements, the last result group is the lookup.
1043   if (it == resultGroups.end()) {
1044     groupResultNo = resultGroups.back();
1045     groupSize = static_cast<int>(owner->getNumResults()) - resultGroups.back();
1046   } else {
1047     // Otherwise, the previous element is the lookup.
1048     groupResultNo = *std::prev(it);
1049     groupSize = *it - groupResultNo;
1050   }
1051 
1052   // We only record the result number for a group of size greater than 1.
1053   if (groupSize != 1)
1054     lookupResultNo = resultNo - groupResultNo;
1055   lookupValue = owner->getResult(groupResultNo);
1056 }
1057 
1058 void SSANameState::setValueName(Value value, StringRef name) {
1059   // If the name is empty, the value uses the default numbering.
1060   if (name.empty()) {
1061     valueIDs[value] = nextValueID++;
1062     return;
1063   }
1064 
1065   valueIDs[value] = NameSentinel;
1066   valueNames[value] = uniqueValueName(name);
1067 }
1068 
1069 StringRef SSANameState::uniqueValueName(StringRef name) {
1070   SmallString<16> tmpBuffer;
1071   name = sanitizeIdentifier(name, tmpBuffer);
1072 
1073   // Check to see if this name is already unique.
1074   if (!usedNames.count(name)) {
1075     name = name.copy(usedNameAllocator);
1076   } else {
1077     // Otherwise, we had a conflict - probe until we find a unique name. This
1078     // is guaranteed to terminate (and usually in a single iteration) because it
1079     // generates new names by incrementing nextConflictID.
1080     SmallString<64> probeName(name);
1081     probeName.push_back('_');
1082     while (true) {
1083       probeName += llvm::utostr(nextConflictID++);
1084       if (!usedNames.count(probeName)) {
1085         name = StringRef(probeName).copy(usedNameAllocator);
1086         break;
1087       }
1088       probeName.resize(name.size() + 1);
1089     }
1090   }
1091 
1092   usedNames.insert(name, char());
1093   return name;
1094 }
1095 
1096 //===----------------------------------------------------------------------===//
1097 // AsmState
1098 //===----------------------------------------------------------------------===//
1099 
1100 namespace mlir {
1101 namespace detail {
1102 class AsmStateImpl {
1103 public:
1104   explicit AsmStateImpl(Operation *op, AsmState::LocationMap *locationMap)
1105       : interfaces(op->getContext()), nameState(op, interfaces),
1106         locationMap(locationMap) {}
1107 
1108   /// Initialize the alias state to enable the printing of aliases.
1109   void initializeAliases(Operation *op, const OpPrintingFlags &printerFlags) {
1110     aliasState.initialize(op, printerFlags, interfaces);
1111   }
1112 
1113   /// Get an instance of the OpAsmDialectInterface for the given dialect, or
1114   /// null if one wasn't registered.
1115   const OpAsmDialectInterface *getOpAsmInterface(Dialect *dialect) {
1116     return interfaces.getInterfaceFor(dialect);
1117   }
1118 
1119   /// Get the state used for aliases.
1120   AliasState &getAliasState() { return aliasState; }
1121 
1122   /// Get the state used for SSA names.
1123   SSANameState &getSSANameState() { return nameState; }
1124 
1125   /// Register the location, line and column, within the buffer that the given
1126   /// operation was printed at.
1127   void registerOperationLocation(Operation *op, unsigned line, unsigned col) {
1128     if (locationMap)
1129       (*locationMap)[op] = std::make_pair(line, col);
1130   }
1131 
1132 private:
1133   /// Collection of OpAsm interfaces implemented in the context.
1134   DialectInterfaceCollection<OpAsmDialectInterface> interfaces;
1135 
1136   /// The state used for attribute and type aliases.
1137   AliasState aliasState;
1138 
1139   /// The state used for SSA value names.
1140   SSANameState nameState;
1141 
1142   /// An optional location map to be populated.
1143   AsmState::LocationMap *locationMap;
1144 };
1145 } // end namespace detail
1146 } // end namespace mlir
1147 
1148 AsmState::AsmState(Operation *op, LocationMap *locationMap)
1149     : impl(std::make_unique<AsmStateImpl>(op, locationMap)) {}
1150 AsmState::~AsmState() {}
1151 
1152 //===----------------------------------------------------------------------===//
1153 // ModulePrinter
1154 //===----------------------------------------------------------------------===//
1155 
1156 namespace {
1157 class ModulePrinter {
1158 public:
1159   ModulePrinter(raw_ostream &os, OpPrintingFlags flags = llvm::None,
1160                 AsmStateImpl *state = nullptr)
1161       : os(os), printerFlags(flags), state(state) {}
1162   explicit ModulePrinter(ModulePrinter &printer)
1163       : os(printer.os), printerFlags(printer.printerFlags),
1164         state(printer.state) {}
1165 
1166   /// Returns the output stream of the printer.
1167   raw_ostream &getStream() { return os; }
1168 
1169   template <typename Container, typename UnaryFunctor>
1170   inline void interleaveComma(const Container &c, UnaryFunctor each_fn) const {
1171     llvm::interleaveComma(c, os, each_fn);
1172   }
1173 
1174   /// This enum describes the different kinds of elision for the type of an
1175   /// attribute when printing it.
1176   enum class AttrTypeElision {
1177     /// The type must not be elided,
1178     Never,
1179     /// The type may be elided when it matches the default used in the parser
1180     /// (for example i64 is the default for integer attributes).
1181     May,
1182     /// The type must be elided.
1183     Must
1184   };
1185 
1186   /// Print the given attribute.
1187   void printAttribute(Attribute attr,
1188                       AttrTypeElision typeElision = AttrTypeElision::Never);
1189 
1190   void printType(Type type);
1191 
1192   /// Print the given location to the stream. If `allowAlias` is true, this
1193   /// allows for the internal location to use an attribute alias.
1194   void printLocation(LocationAttr loc, bool allowAlias = false);
1195 
1196   void printAffineMap(AffineMap map);
1197   void
1198   printAffineExpr(AffineExpr expr,
1199                   function_ref<void(unsigned, bool)> printValueName = nullptr);
1200   void printAffineConstraint(AffineExpr expr, bool isEq);
1201   void printIntegerSet(IntegerSet set);
1202 
1203 protected:
1204   void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
1205                              ArrayRef<StringRef> elidedAttrs = {},
1206                              bool withKeyword = false);
1207   void printNamedAttribute(NamedAttribute attr);
1208   void printTrailingLocation(Location loc);
1209   void printLocationInternal(LocationAttr loc, bool pretty = false);
1210 
1211   /// Print a dense elements attribute. If 'allowHex' is true, a hex string is
1212   /// used instead of individual elements when the elements attr is large.
1213   void printDenseElementsAttr(DenseElementsAttr attr, bool allowHex);
1214 
1215   /// Print a dense string elements attribute.
1216   void printDenseStringElementsAttr(DenseStringElementsAttr attr);
1217 
1218   /// Print a dense elements attribute. If 'allowHex' is true, a hex string is
1219   /// used instead of individual elements when the elements attr is large.
1220   void printDenseIntOrFPElementsAttr(DenseIntOrFPElementsAttr attr,
1221                                      bool allowHex);
1222 
1223   void printDialectAttribute(Attribute attr);
1224   void printDialectType(Type type);
1225 
1226   /// This enum is used to represent the binding strength of the enclosing
1227   /// context that an AffineExprStorage is being printed in, so we can
1228   /// intelligently produce parens.
1229   enum class BindingStrength {
1230     Weak,   // + and -
1231     Strong, // All other binary operators.
1232   };
1233   void printAffineExprInternal(
1234       AffineExpr expr, BindingStrength enclosingTightness,
1235       function_ref<void(unsigned, bool)> printValueName = nullptr);
1236 
1237   /// The output stream for the printer.
1238   raw_ostream &os;
1239 
1240   /// A set of flags to control the printer's behavior.
1241   OpPrintingFlags printerFlags;
1242 
1243   /// An optional printer state for the module.
1244   AsmStateImpl *state;
1245 
1246   /// A tracker for the number of new lines emitted during printing.
1247   NewLineCounter newLine;
1248 };
1249 } // end anonymous namespace
1250 
1251 void ModulePrinter::printTrailingLocation(Location loc) {
1252   // Check to see if we are printing debug information.
1253   if (!printerFlags.shouldPrintDebugInfo())
1254     return;
1255 
1256   os << " ";
1257   printLocation(loc, /*allowAlias=*/true);
1258 }
1259 
1260 void ModulePrinter::printLocationInternal(LocationAttr loc, bool pretty) {
1261   TypeSwitch<LocationAttr>(loc)
1262       .Case<OpaqueLoc>([&](OpaqueLoc loc) {
1263         printLocationInternal(loc.getFallbackLocation(), pretty);
1264       })
1265       .Case<UnknownLoc>([&](UnknownLoc loc) {
1266         if (pretty)
1267           os << "[unknown]";
1268         else
1269           os << "unknown";
1270       })
1271       .Case<FileLineColLoc>([&](FileLineColLoc loc) {
1272         if (pretty) {
1273           os << loc.getFilename();
1274         } else {
1275           os << "\"";
1276           printEscapedString(loc.getFilename(), os);
1277           os << "\"";
1278         }
1279         os << ':' << loc.getLine() << ':' << loc.getColumn();
1280       })
1281       .Case<NameLoc>([&](NameLoc loc) {
1282         os << '\"';
1283         printEscapedString(loc.getName(), os);
1284         os << '\"';
1285 
1286         // Print the child if it isn't unknown.
1287         auto childLoc = loc.getChildLoc();
1288         if (!childLoc.isa<UnknownLoc>()) {
1289           os << '(';
1290           printLocationInternal(childLoc, pretty);
1291           os << ')';
1292         }
1293       })
1294       .Case<CallSiteLoc>([&](CallSiteLoc loc) {
1295         Location caller = loc.getCaller();
1296         Location callee = loc.getCallee();
1297         if (!pretty)
1298           os << "callsite(";
1299         printLocationInternal(callee, pretty);
1300         if (pretty) {
1301           if (callee.isa<NameLoc>()) {
1302             if (caller.isa<FileLineColLoc>()) {
1303               os << " at ";
1304             } else {
1305               os << newLine << " at ";
1306             }
1307           } else {
1308             os << newLine << " at ";
1309           }
1310         } else {
1311           os << " at ";
1312         }
1313         printLocationInternal(caller, pretty);
1314         if (!pretty)
1315           os << ")";
1316       })
1317       .Case<FusedLoc>([&](FusedLoc loc) {
1318         if (!pretty)
1319           os << "fused";
1320         if (Attribute metadata = loc.getMetadata())
1321           os << '<' << metadata << '>';
1322         os << '[';
1323         interleave(
1324             loc.getLocations(),
1325             [&](Location loc) { printLocationInternal(loc, pretty); },
1326             [&]() { os << ", "; });
1327         os << ']';
1328       });
1329 }
1330 
1331 /// Print a floating point value in a way that the parser will be able to
1332 /// round-trip losslessly.
1333 static void printFloatValue(const APFloat &apValue, raw_ostream &os) {
1334   // We would like to output the FP constant value in exponential notation,
1335   // but we cannot do this if doing so will lose precision.  Check here to
1336   // make sure that we only output it in exponential format if we can parse
1337   // the value back and get the same value.
1338   bool isInf = apValue.isInfinity();
1339   bool isNaN = apValue.isNaN();
1340   if (!isInf && !isNaN) {
1341     SmallString<128> strValue;
1342     apValue.toString(strValue, /*FormatPrecision=*/6, /*FormatMaxPadding=*/0,
1343                      /*TruncateZero=*/false);
1344 
1345     // Check to make sure that the stringized number is not some string like
1346     // "Inf" or NaN, that atof will accept, but the lexer will not.  Check
1347     // that the string matches the "[-+]?[0-9]" regex.
1348     assert(((strValue[0] >= '0' && strValue[0] <= '9') ||
1349             ((strValue[0] == '-' || strValue[0] == '+') &&
1350              (strValue[1] >= '0' && strValue[1] <= '9'))) &&
1351            "[-+]?[0-9] regex does not match!");
1352 
1353     // Parse back the stringized version and check that the value is equal
1354     // (i.e., there is no precision loss).
1355     if (APFloat(apValue.getSemantics(), strValue).bitwiseIsEqual(apValue)) {
1356       os << strValue;
1357       return;
1358     }
1359 
1360     // If it is not, use the default format of APFloat instead of the
1361     // exponential notation.
1362     strValue.clear();
1363     apValue.toString(strValue);
1364 
1365     // Make sure that we can parse the default form as a float.
1366     if (StringRef(strValue).contains('.')) {
1367       os << strValue;
1368       return;
1369     }
1370   }
1371 
1372   // Print special values in hexadecimal format. The sign bit should be included
1373   // in the literal.
1374   SmallVector<char, 16> str;
1375   APInt apInt = apValue.bitcastToAPInt();
1376   apInt.toString(str, /*Radix=*/16, /*Signed=*/false,
1377                  /*formatAsCLiteral=*/true);
1378   os << str;
1379 }
1380 
1381 void ModulePrinter::printLocation(LocationAttr loc, bool allowAlias) {
1382   if (printerFlags.shouldPrintDebugInfoPrettyForm())
1383     return printLocationInternal(loc, /*pretty=*/true);
1384 
1385   os << "loc(";
1386   if (!allowAlias || !state || failed(state->getAliasState().getAlias(loc, os)))
1387     printLocationInternal(loc);
1388   os << ')';
1389 }
1390 
1391 /// Returns true if the given dialect symbol data is simple enough to print in
1392 /// the pretty form, i.e. without the enclosing "".
1393 static bool isDialectSymbolSimpleEnoughForPrettyForm(StringRef symName) {
1394   // The name must start with an identifier.
1395   if (symName.empty() || !isalpha(symName.front()))
1396     return false;
1397 
1398   // Ignore all the characters that are valid in an identifier in the symbol
1399   // name.
1400   symName = symName.drop_while(
1401       [](char c) { return llvm::isAlnum(c) || c == '.' || c == '_'; });
1402   if (symName.empty())
1403     return true;
1404 
1405   // If we got to an unexpected character, then it must be a <>.  Check those
1406   // recursively.
1407   if (symName.front() != '<' || symName.back() != '>')
1408     return false;
1409 
1410   SmallVector<char, 8> nestedPunctuation;
1411   do {
1412     // If we ran out of characters, then we had a punctuation mismatch.
1413     if (symName.empty())
1414       return false;
1415 
1416     auto c = symName.front();
1417     symName = symName.drop_front();
1418 
1419     switch (c) {
1420     // We never allow null characters. This is an EOF indicator for the lexer
1421     // which we could handle, but isn't important for any known dialect.
1422     case '\0':
1423       return false;
1424     case '<':
1425     case '[':
1426     case '(':
1427     case '{':
1428       nestedPunctuation.push_back(c);
1429       continue;
1430     case '-':
1431       // Treat `->` as a special token.
1432       if (!symName.empty() && symName.front() == '>') {
1433         symName = symName.drop_front();
1434         continue;
1435       }
1436       break;
1437     // Reject types with mismatched brackets.
1438     case '>':
1439       if (nestedPunctuation.pop_back_val() != '<')
1440         return false;
1441       break;
1442     case ']':
1443       if (nestedPunctuation.pop_back_val() != '[')
1444         return false;
1445       break;
1446     case ')':
1447       if (nestedPunctuation.pop_back_val() != '(')
1448         return false;
1449       break;
1450     case '}':
1451       if (nestedPunctuation.pop_back_val() != '{')
1452         return false;
1453       break;
1454     default:
1455       continue;
1456     }
1457 
1458     // We're done when the punctuation is fully matched.
1459   } while (!nestedPunctuation.empty());
1460 
1461   // If there were extra characters, then we failed.
1462   return symName.empty();
1463 }
1464 
1465 /// Print the given dialect symbol to the stream.
1466 static void printDialectSymbol(raw_ostream &os, StringRef symPrefix,
1467                                StringRef dialectName, StringRef symString) {
1468   os << symPrefix << dialectName;
1469 
1470   // If this symbol name is simple enough, print it directly in pretty form,
1471   // otherwise, we print it as an escaped string.
1472   if (isDialectSymbolSimpleEnoughForPrettyForm(symString)) {
1473     os << '.' << symString;
1474     return;
1475   }
1476 
1477   // TODO: escape the symbol name, it could contain " characters.
1478   os << "<\"" << symString << "\">";
1479 }
1480 
1481 /// Returns true if the given string can be represented as a bare identifier.
1482 static bool isBareIdentifier(StringRef name) {
1483   assert(!name.empty() && "invalid name");
1484 
1485   // By making this unsigned, the value passed in to isalnum will always be
1486   // in the range 0-255. This is important when building with MSVC because
1487   // its implementation will assert. This situation can arise when dealing
1488   // with UTF-8 multibyte characters.
1489   unsigned char firstChar = static_cast<unsigned char>(name[0]);
1490   if (!isalpha(firstChar) && firstChar != '_')
1491     return false;
1492   return llvm::all_of(name.drop_front(), [](unsigned char c) {
1493     return isalnum(c) || c == '_' || c == '$' || c == '.';
1494   });
1495 }
1496 
1497 /// Print the given string as a symbol reference. A symbol reference is
1498 /// represented as a string prefixed with '@'. The reference is surrounded with
1499 /// ""'s and escaped if it has any special or non-printable characters in it.
1500 static void printSymbolReference(StringRef symbolRef, raw_ostream &os) {
1501   assert(!symbolRef.empty() && "expected valid symbol reference");
1502 
1503   // If the symbol can be represented as a bare identifier, write it directly.
1504   if (isBareIdentifier(symbolRef)) {
1505     os << '@' << symbolRef;
1506     return;
1507   }
1508 
1509   // Otherwise, output the reference wrapped in quotes with proper escaping.
1510   os << "@\"";
1511   printEscapedString(symbolRef, os);
1512   os << '"';
1513 }
1514 
1515 // Print out a valid ElementsAttr that is succinct and can represent any
1516 // potential shape/type, for use when eliding a large ElementsAttr.
1517 //
1518 // We choose to use an opaque ElementsAttr literal with conspicuous content to
1519 // hopefully alert readers to the fact that this has been elided.
1520 //
1521 // Unfortunately, neither of the strings of an opaque ElementsAttr literal will
1522 // accept the string "elided". The first string must be a registered dialect
1523 // name and the latter must be a hex constant.
1524 static void printElidedElementsAttr(raw_ostream &os) {
1525   os << R"(opaque<"_", "0xDEADBEEF">)";
1526 }
1527 
1528 void ModulePrinter::printAttribute(Attribute attr,
1529                                    AttrTypeElision typeElision) {
1530   if (!attr) {
1531     os << "<<NULL ATTRIBUTE>>";
1532     return;
1533   }
1534 
1535   // Try to print an alias for this attribute.
1536   if (state && succeeded(state->getAliasState().getAlias(attr, os)))
1537     return;
1538 
1539   auto attrType = attr.getType();
1540   if (auto opaqueAttr = attr.dyn_cast<OpaqueAttr>()) {
1541     printDialectSymbol(os, "#", opaqueAttr.getDialectNamespace(),
1542                        opaqueAttr.getAttrData());
1543   } else if (attr.isa<UnitAttr>()) {
1544     os << "unit";
1545     return;
1546   } else if (auto dictAttr = attr.dyn_cast<DictionaryAttr>()) {
1547     os << '{';
1548     interleaveComma(dictAttr.getValue(),
1549                     [&](NamedAttribute attr) { printNamedAttribute(attr); });
1550     os << '}';
1551 
1552   } else if (auto intAttr = attr.dyn_cast<IntegerAttr>()) {
1553     if (attrType.isSignlessInteger(1)) {
1554       os << (intAttr.getValue().getBoolValue() ? "true" : "false");
1555 
1556       // Boolean integer attributes always elides the type.
1557       return;
1558     }
1559 
1560     // Only print attributes as unsigned if they are explicitly unsigned or are
1561     // signless 1-bit values.  Indexes, signed values, and multi-bit signless
1562     // values print as signed.
1563     bool isUnsigned =
1564         attrType.isUnsignedInteger() || attrType.isSignlessInteger(1);
1565     intAttr.getValue().print(os, !isUnsigned);
1566 
1567     // IntegerAttr elides the type if I64.
1568     if (typeElision == AttrTypeElision::May && attrType.isSignlessInteger(64))
1569       return;
1570 
1571   } else if (auto floatAttr = attr.dyn_cast<FloatAttr>()) {
1572     printFloatValue(floatAttr.getValue(), os);
1573 
1574     // FloatAttr elides the type if F64.
1575     if (typeElision == AttrTypeElision::May && attrType.isF64())
1576       return;
1577 
1578   } else if (auto strAttr = attr.dyn_cast<StringAttr>()) {
1579     os << '"';
1580     printEscapedString(strAttr.getValue(), os);
1581     os << '"';
1582 
1583   } else if (auto arrayAttr = attr.dyn_cast<ArrayAttr>()) {
1584     os << '[';
1585     interleaveComma(arrayAttr.getValue(), [&](Attribute attr) {
1586       printAttribute(attr, AttrTypeElision::May);
1587     });
1588     os << ']';
1589 
1590   } else if (auto affineMapAttr = attr.dyn_cast<AffineMapAttr>()) {
1591     os << "affine_map<";
1592     affineMapAttr.getValue().print(os);
1593     os << '>';
1594 
1595     // AffineMap always elides the type.
1596     return;
1597 
1598   } else if (auto integerSetAttr = attr.dyn_cast<IntegerSetAttr>()) {
1599     os << "affine_set<";
1600     integerSetAttr.getValue().print(os);
1601     os << '>';
1602 
1603     // IntegerSet always elides the type.
1604     return;
1605 
1606   } else if (auto typeAttr = attr.dyn_cast<TypeAttr>()) {
1607     printType(typeAttr.getValue());
1608 
1609   } else if (auto refAttr = attr.dyn_cast<SymbolRefAttr>()) {
1610     printSymbolReference(refAttr.getRootReference(), os);
1611     for (FlatSymbolRefAttr nestedRef : refAttr.getNestedReferences()) {
1612       os << "::";
1613       printSymbolReference(nestedRef.getValue(), os);
1614     }
1615 
1616   } else if (auto opaqueAttr = attr.dyn_cast<OpaqueElementsAttr>()) {
1617     if (printerFlags.shouldElideElementsAttr(opaqueAttr)) {
1618       printElidedElementsAttr(os);
1619     } else {
1620       os << "opaque<\"" << opaqueAttr.getDialect() << "\", \"0x"
1621          << llvm::toHex(opaqueAttr.getValue()) << "\">";
1622     }
1623 
1624   } else if (auto intOrFpEltAttr = attr.dyn_cast<DenseIntOrFPElementsAttr>()) {
1625     if (printerFlags.shouldElideElementsAttr(intOrFpEltAttr)) {
1626       printElidedElementsAttr(os);
1627     } else {
1628       os << "dense<";
1629       printDenseIntOrFPElementsAttr(intOrFpEltAttr, /*allowHex=*/true);
1630       os << '>';
1631     }
1632 
1633   } else if (auto strEltAttr = attr.dyn_cast<DenseStringElementsAttr>()) {
1634     if (printerFlags.shouldElideElementsAttr(strEltAttr)) {
1635       printElidedElementsAttr(os);
1636     } else {
1637       os << "dense<";
1638       printDenseStringElementsAttr(strEltAttr);
1639       os << '>';
1640     }
1641 
1642   } else if (auto sparseEltAttr = attr.dyn_cast<SparseElementsAttr>()) {
1643     if (printerFlags.shouldElideElementsAttr(sparseEltAttr.getIndices()) ||
1644         printerFlags.shouldElideElementsAttr(sparseEltAttr.getValues())) {
1645       printElidedElementsAttr(os);
1646     } else {
1647       os << "sparse<";
1648       DenseIntElementsAttr indices = sparseEltAttr.getIndices();
1649       if (indices.getNumElements() != 0) {
1650         printDenseIntOrFPElementsAttr(indices, /*allowHex=*/false);
1651         os << ", ";
1652         printDenseElementsAttr(sparseEltAttr.getValues(), /*allowHex=*/true);
1653       }
1654       os << '>';
1655     }
1656 
1657   } else if (auto locAttr = attr.dyn_cast<LocationAttr>()) {
1658     printLocation(locAttr);
1659 
1660   } else {
1661     return printDialectAttribute(attr);
1662   }
1663 
1664   // Don't print the type if we must elide it, or if it is a None type.
1665   if (typeElision != AttrTypeElision::Must && !attrType.isa<NoneType>()) {
1666     os << " : ";
1667     printType(attrType);
1668   }
1669 }
1670 
1671 /// Print the integer element of a DenseElementsAttr.
1672 static void printDenseIntElement(const APInt &value, raw_ostream &os,
1673                                  bool isSigned) {
1674   if (value.getBitWidth() == 1)
1675     os << (value.getBoolValue() ? "true" : "false");
1676   else
1677     value.print(os, isSigned);
1678 }
1679 
1680 static void
1681 printDenseElementsAttrImpl(bool isSplat, ShapedType type, raw_ostream &os,
1682                            function_ref<void(unsigned)> printEltFn) {
1683   // Special case for 0-d and splat tensors.
1684   if (isSplat)
1685     return printEltFn(0);
1686 
1687   // Special case for degenerate tensors.
1688   auto numElements = type.getNumElements();
1689   if (numElements == 0)
1690     return;
1691 
1692   // We use a mixed-radix counter to iterate through the shape. When we bump a
1693   // non-least-significant digit, we emit a close bracket. When we next emit an
1694   // element we re-open all closed brackets.
1695 
1696   // The mixed-radix counter, with radices in 'shape'.
1697   int64_t rank = type.getRank();
1698   SmallVector<unsigned, 4> counter(rank, 0);
1699   // The number of brackets that have been opened and not closed.
1700   unsigned openBrackets = 0;
1701 
1702   auto shape = type.getShape();
1703   auto bumpCounter = [&] {
1704     // Bump the least significant digit.
1705     ++counter[rank - 1];
1706     // Iterate backwards bubbling back the increment.
1707     for (unsigned i = rank - 1; i > 0; --i)
1708       if (counter[i] >= shape[i]) {
1709         // Index 'i' is rolled over. Bump (i-1) and close a bracket.
1710         counter[i] = 0;
1711         ++counter[i - 1];
1712         --openBrackets;
1713         os << ']';
1714       }
1715   };
1716 
1717   for (unsigned idx = 0, e = numElements; idx != e; ++idx) {
1718     if (idx != 0)
1719       os << ", ";
1720     while (openBrackets++ < rank)
1721       os << '[';
1722     openBrackets = rank;
1723     printEltFn(idx);
1724     bumpCounter();
1725   }
1726   while (openBrackets-- > 0)
1727     os << ']';
1728 }
1729 
1730 void ModulePrinter::printDenseElementsAttr(DenseElementsAttr attr,
1731                                            bool allowHex) {
1732   if (auto stringAttr = attr.dyn_cast<DenseStringElementsAttr>())
1733     return printDenseStringElementsAttr(stringAttr);
1734 
1735   printDenseIntOrFPElementsAttr(attr.cast<DenseIntOrFPElementsAttr>(),
1736                                 allowHex);
1737 }
1738 
1739 void ModulePrinter::printDenseIntOrFPElementsAttr(DenseIntOrFPElementsAttr attr,
1740                                                   bool allowHex) {
1741   auto type = attr.getType();
1742   auto elementType = type.getElementType();
1743 
1744   // Check to see if we should format this attribute as a hex string.
1745   auto numElements = type.getNumElements();
1746   if (!attr.isSplat() && allowHex &&
1747       shouldPrintElementsAttrWithHex(numElements)) {
1748     ArrayRef<char> rawData = attr.getRawData();
1749     if (llvm::support::endian::system_endianness() ==
1750         llvm::support::endianness::big) {
1751       // Convert endianess in big-endian(BE) machines. `rawData` is BE in BE
1752       // machines. It is converted here to print in LE format.
1753       SmallVector<char, 64> outDataVec(rawData.size());
1754       MutableArrayRef<char> convRawData(outDataVec);
1755       DenseIntOrFPElementsAttr::convertEndianOfArrayRefForBEmachine(
1756           rawData, convRawData, type);
1757       os << '"' << "0x"
1758          << llvm::toHex(StringRef(convRawData.data(), convRawData.size()))
1759          << "\"";
1760     } else {
1761       os << '"' << "0x"
1762          << llvm::toHex(StringRef(rawData.data(), rawData.size())) << "\"";
1763     }
1764 
1765     return;
1766   }
1767 
1768   if (ComplexType complexTy = elementType.dyn_cast<ComplexType>()) {
1769     Type complexElementType = complexTy.getElementType();
1770     // Note: The if and else below had a common lambda function which invoked
1771     // printDenseElementsAttrImpl. This lambda was hitting a bug in gcc 9.1,9.2
1772     // and hence was replaced.
1773     if (complexElementType.isa<IntegerType>()) {
1774       bool isSigned = !complexElementType.isUnsignedInteger();
1775       printDenseElementsAttrImpl(attr.isSplat(), type, os, [&](unsigned index) {
1776         auto complexValue = *(attr.getComplexIntValues().begin() + index);
1777         os << "(";
1778         printDenseIntElement(complexValue.real(), os, isSigned);
1779         os << ",";
1780         printDenseIntElement(complexValue.imag(), os, isSigned);
1781         os << ")";
1782       });
1783     } else {
1784       printDenseElementsAttrImpl(attr.isSplat(), type, os, [&](unsigned index) {
1785         auto complexValue = *(attr.getComplexFloatValues().begin() + index);
1786         os << "(";
1787         printFloatValue(complexValue.real(), os);
1788         os << ",";
1789         printFloatValue(complexValue.imag(), os);
1790         os << ")";
1791       });
1792     }
1793   } else if (elementType.isIntOrIndex()) {
1794     bool isSigned = !elementType.isUnsignedInteger();
1795     auto intValues = attr.getIntValues();
1796     printDenseElementsAttrImpl(attr.isSplat(), type, os, [&](unsigned index) {
1797       printDenseIntElement(*(intValues.begin() + index), os, isSigned);
1798     });
1799   } else {
1800     assert(elementType.isa<FloatType>() && "unexpected element type");
1801     auto floatValues = attr.getFloatValues();
1802     printDenseElementsAttrImpl(attr.isSplat(), type, os, [&](unsigned index) {
1803       printFloatValue(*(floatValues.begin() + index), os);
1804     });
1805   }
1806 }
1807 
1808 void ModulePrinter::printDenseStringElementsAttr(DenseStringElementsAttr attr) {
1809   ArrayRef<StringRef> data = attr.getRawStringData();
1810   auto printFn = [&](unsigned index) {
1811     os << "\"";
1812     printEscapedString(data[index], os);
1813     os << "\"";
1814   };
1815   printDenseElementsAttrImpl(attr.isSplat(), attr.getType(), os, printFn);
1816 }
1817 
1818 void ModulePrinter::printType(Type type) {
1819   if (!type) {
1820     os << "<<NULL TYPE>>";
1821     return;
1822   }
1823 
1824   // Try to print an alias for this type.
1825   if (state && succeeded(state->getAliasState().getAlias(type, os)))
1826     return;
1827 
1828   TypeSwitch<Type>(type)
1829       .Case<OpaqueType>([&](OpaqueType opaqueTy) {
1830         printDialectSymbol(os, "!", opaqueTy.getDialectNamespace(),
1831                            opaqueTy.getTypeData());
1832       })
1833       .Case<IndexType>([&](Type) { os << "index"; })
1834       .Case<BFloat16Type>([&](Type) { os << "bf16"; })
1835       .Case<Float16Type>([&](Type) { os << "f16"; })
1836       .Case<Float32Type>([&](Type) { os << "f32"; })
1837       .Case<Float64Type>([&](Type) { os << "f64"; })
1838       .Case<Float80Type>([&](Type) { os << "f80"; })
1839       .Case<Float128Type>([&](Type) { os << "f128"; })
1840       .Case<IntegerType>([&](IntegerType integerTy) {
1841         if (integerTy.isSigned())
1842           os << 's';
1843         else if (integerTy.isUnsigned())
1844           os << 'u';
1845         os << 'i' << integerTy.getWidth();
1846       })
1847       .Case<FunctionType>([&](FunctionType funcTy) {
1848         os << '(';
1849         interleaveComma(funcTy.getInputs(), [&](Type ty) { printType(ty); });
1850         os << ") -> ";
1851         ArrayRef<Type> results = funcTy.getResults();
1852         if (results.size() == 1 && !results[0].isa<FunctionType>()) {
1853           os << results[0];
1854         } else {
1855           os << '(';
1856           interleaveComma(results, [&](Type ty) { printType(ty); });
1857           os << ')';
1858         }
1859       })
1860       .Case<VectorType>([&](VectorType vectorTy) {
1861         os << "vector<";
1862         for (int64_t dim : vectorTy.getShape())
1863           os << dim << 'x';
1864         os << vectorTy.getElementType() << '>';
1865       })
1866       .Case<RankedTensorType>([&](RankedTensorType tensorTy) {
1867         os << "tensor<";
1868         for (int64_t dim : tensorTy.getShape()) {
1869           if (ShapedType::isDynamic(dim))
1870             os << '?';
1871           else
1872             os << dim;
1873           os << 'x';
1874         }
1875         os << tensorTy.getElementType();
1876         // Only print the encoding attribute value if set.
1877         if (tensorTy.getEncoding()) {
1878           os << ", ";
1879           printAttribute(tensorTy.getEncoding());
1880         }
1881         os << '>';
1882       })
1883       .Case<UnrankedTensorType>([&](UnrankedTensorType tensorTy) {
1884         os << "tensor<*x";
1885         printType(tensorTy.getElementType());
1886         os << '>';
1887       })
1888       .Case<MemRefType>([&](MemRefType memrefTy) {
1889         os << "memref<";
1890         for (int64_t dim : memrefTy.getShape()) {
1891           if (ShapedType::isDynamic(dim))
1892             os << '?';
1893           else
1894             os << dim;
1895           os << 'x';
1896         }
1897         printType(memrefTy.getElementType());
1898         for (auto map : memrefTy.getAffineMaps()) {
1899           os << ", ";
1900           printAttribute(AffineMapAttr::get(map));
1901         }
1902         // Only print the memory space if it is the non-default one.
1903         if (memrefTy.getMemorySpace()) {
1904           os << ", ";
1905           printAttribute(memrefTy.getMemorySpace(), AttrTypeElision::May);
1906         }
1907         os << '>';
1908       })
1909       .Case<UnrankedMemRefType>([&](UnrankedMemRefType memrefTy) {
1910         os << "memref<*x";
1911         printType(memrefTy.getElementType());
1912         // Only print the memory space if it is the non-default one.
1913         if (memrefTy.getMemorySpace()) {
1914           os << ", ";
1915           printAttribute(memrefTy.getMemorySpace(), AttrTypeElision::May);
1916         }
1917         os << '>';
1918       })
1919       .Case<ComplexType>([&](ComplexType complexTy) {
1920         os << "complex<";
1921         printType(complexTy.getElementType());
1922         os << '>';
1923       })
1924       .Case<TupleType>([&](TupleType tupleTy) {
1925         os << "tuple<";
1926         interleaveComma(tupleTy.getTypes(),
1927                         [&](Type type) { printType(type); });
1928         os << '>';
1929       })
1930       .Case<NoneType>([&](Type) { os << "none"; })
1931       .Default([&](Type type) { return printDialectType(type); });
1932 }
1933 
1934 void ModulePrinter::printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
1935                                           ArrayRef<StringRef> elidedAttrs,
1936                                           bool withKeyword) {
1937   // If there are no attributes, then there is nothing to be done.
1938   if (attrs.empty())
1939     return;
1940 
1941   // Functor used to print a filtered attribute list.
1942   auto printFilteredAttributesFn = [&](auto filteredAttrs) {
1943     // Print the 'attributes' keyword if necessary.
1944     if (withKeyword)
1945       os << " attributes";
1946 
1947     // Otherwise, print them all out in braces.
1948     os << " {";
1949     interleaveComma(filteredAttrs,
1950                     [&](NamedAttribute attr) { printNamedAttribute(attr); });
1951     os << '}';
1952   };
1953 
1954   // If no attributes are elided, we can directly print with no filtering.
1955   if (elidedAttrs.empty())
1956     return printFilteredAttributesFn(attrs);
1957 
1958   // Otherwise, filter out any attributes that shouldn't be included.
1959   llvm::SmallDenseSet<StringRef> elidedAttrsSet(elidedAttrs.begin(),
1960                                                 elidedAttrs.end());
1961   auto filteredAttrs = llvm::make_filter_range(attrs, [&](NamedAttribute attr) {
1962     return !elidedAttrsSet.contains(attr.first.strref());
1963   });
1964   if (!filteredAttrs.empty())
1965     printFilteredAttributesFn(filteredAttrs);
1966 }
1967 
1968 void ModulePrinter::printNamedAttribute(NamedAttribute attr) {
1969   if (isBareIdentifier(attr.first)) {
1970     os << attr.first;
1971   } else {
1972     os << '"';
1973     printEscapedString(attr.first.strref(), os);
1974     os << '"';
1975   }
1976 
1977   // Pretty printing elides the attribute value for unit attributes.
1978   if (attr.second.isa<UnitAttr>())
1979     return;
1980 
1981   os << " = ";
1982   printAttribute(attr.second);
1983 }
1984 
1985 //===----------------------------------------------------------------------===//
1986 // CustomDialectAsmPrinter
1987 //===----------------------------------------------------------------------===//
1988 
1989 namespace {
1990 /// This class provides the main specialization of the DialectAsmPrinter that is
1991 /// used to provide support for print attributes and types. This hooks allows
1992 /// for dialects to hook into the main ModulePrinter.
1993 struct CustomDialectAsmPrinter : public DialectAsmPrinter {
1994 public:
1995   CustomDialectAsmPrinter(ModulePrinter &printer) : printer(printer) {}
1996   ~CustomDialectAsmPrinter() override {}
1997 
1998   raw_ostream &getStream() const override { return printer.getStream(); }
1999 
2000   /// Print the given attribute to the stream.
2001   void printAttribute(Attribute attr) override { printer.printAttribute(attr); }
2002 
2003   /// Print the given floating point value in a stablized form.
2004   void printFloat(const APFloat &value) override {
2005     printFloatValue(value, getStream());
2006   }
2007 
2008   /// Print the given type to the stream.
2009   void printType(Type type) override { printer.printType(type); }
2010 
2011   /// The main module printer.
2012   ModulePrinter &printer;
2013 };
2014 } // end anonymous namespace
2015 
2016 void ModulePrinter::printDialectAttribute(Attribute attr) {
2017   auto &dialect = attr.getDialect();
2018 
2019   // Ask the dialect to serialize the attribute to a string.
2020   std::string attrName;
2021   {
2022     llvm::raw_string_ostream attrNameStr(attrName);
2023     ModulePrinter subPrinter(attrNameStr, printerFlags, state);
2024     CustomDialectAsmPrinter printer(subPrinter);
2025     dialect.printAttribute(attr, printer);
2026   }
2027   printDialectSymbol(os, "#", dialect.getNamespace(), attrName);
2028 }
2029 
2030 void ModulePrinter::printDialectType(Type type) {
2031   auto &dialect = type.getDialect();
2032 
2033   // Ask the dialect to serialize the type to a string.
2034   std::string typeName;
2035   {
2036     llvm::raw_string_ostream typeNameStr(typeName);
2037     ModulePrinter subPrinter(typeNameStr, printerFlags, state);
2038     CustomDialectAsmPrinter printer(subPrinter);
2039     dialect.printType(type, printer);
2040   }
2041   printDialectSymbol(os, "!", dialect.getNamespace(), typeName);
2042 }
2043 
2044 //===----------------------------------------------------------------------===//
2045 // Affine expressions and maps
2046 //===----------------------------------------------------------------------===//
2047 
2048 void ModulePrinter::printAffineExpr(
2049     AffineExpr expr, function_ref<void(unsigned, bool)> printValueName) {
2050   printAffineExprInternal(expr, BindingStrength::Weak, printValueName);
2051 }
2052 
2053 void ModulePrinter::printAffineExprInternal(
2054     AffineExpr expr, BindingStrength enclosingTightness,
2055     function_ref<void(unsigned, bool)> printValueName) {
2056   const char *binopSpelling = nullptr;
2057   switch (expr.getKind()) {
2058   case AffineExprKind::SymbolId: {
2059     unsigned pos = expr.cast<AffineSymbolExpr>().getPosition();
2060     if (printValueName)
2061       printValueName(pos, /*isSymbol=*/true);
2062     else
2063       os << 's' << pos;
2064     return;
2065   }
2066   case AffineExprKind::DimId: {
2067     unsigned pos = expr.cast<AffineDimExpr>().getPosition();
2068     if (printValueName)
2069       printValueName(pos, /*isSymbol=*/false);
2070     else
2071       os << 'd' << pos;
2072     return;
2073   }
2074   case AffineExprKind::Constant:
2075     os << expr.cast<AffineConstantExpr>().getValue();
2076     return;
2077   case AffineExprKind::Add:
2078     binopSpelling = " + ";
2079     break;
2080   case AffineExprKind::Mul:
2081     binopSpelling = " * ";
2082     break;
2083   case AffineExprKind::FloorDiv:
2084     binopSpelling = " floordiv ";
2085     break;
2086   case AffineExprKind::CeilDiv:
2087     binopSpelling = " ceildiv ";
2088     break;
2089   case AffineExprKind::Mod:
2090     binopSpelling = " mod ";
2091     break;
2092   }
2093 
2094   auto binOp = expr.cast<AffineBinaryOpExpr>();
2095   AffineExpr lhsExpr = binOp.getLHS();
2096   AffineExpr rhsExpr = binOp.getRHS();
2097 
2098   // Handle tightly binding binary operators.
2099   if (binOp.getKind() != AffineExprKind::Add) {
2100     if (enclosingTightness == BindingStrength::Strong)
2101       os << '(';
2102 
2103     // Pretty print multiplication with -1.
2104     auto rhsConst = rhsExpr.dyn_cast<AffineConstantExpr>();
2105     if (rhsConst && binOp.getKind() == AffineExprKind::Mul &&
2106         rhsConst.getValue() == -1) {
2107       os << "-";
2108       printAffineExprInternal(lhsExpr, BindingStrength::Strong, printValueName);
2109       if (enclosingTightness == BindingStrength::Strong)
2110         os << ')';
2111       return;
2112     }
2113 
2114     printAffineExprInternal(lhsExpr, BindingStrength::Strong, printValueName);
2115 
2116     os << binopSpelling;
2117     printAffineExprInternal(rhsExpr, BindingStrength::Strong, printValueName);
2118 
2119     if (enclosingTightness == BindingStrength::Strong)
2120       os << ')';
2121     return;
2122   }
2123 
2124   // Print out special "pretty" forms for add.
2125   if (enclosingTightness == BindingStrength::Strong)
2126     os << '(';
2127 
2128   // Pretty print addition to a product that has a negative operand as a
2129   // subtraction.
2130   if (auto rhs = rhsExpr.dyn_cast<AffineBinaryOpExpr>()) {
2131     if (rhs.getKind() == AffineExprKind::Mul) {
2132       AffineExpr rrhsExpr = rhs.getRHS();
2133       if (auto rrhs = rrhsExpr.dyn_cast<AffineConstantExpr>()) {
2134         if (rrhs.getValue() == -1) {
2135           printAffineExprInternal(lhsExpr, BindingStrength::Weak,
2136                                   printValueName);
2137           os << " - ";
2138           if (rhs.getLHS().getKind() == AffineExprKind::Add) {
2139             printAffineExprInternal(rhs.getLHS(), BindingStrength::Strong,
2140                                     printValueName);
2141           } else {
2142             printAffineExprInternal(rhs.getLHS(), BindingStrength::Weak,
2143                                     printValueName);
2144           }
2145 
2146           if (enclosingTightness == BindingStrength::Strong)
2147             os << ')';
2148           return;
2149         }
2150 
2151         if (rrhs.getValue() < -1) {
2152           printAffineExprInternal(lhsExpr, BindingStrength::Weak,
2153                                   printValueName);
2154           os << " - ";
2155           printAffineExprInternal(rhs.getLHS(), BindingStrength::Strong,
2156                                   printValueName);
2157           os << " * " << -rrhs.getValue();
2158           if (enclosingTightness == BindingStrength::Strong)
2159             os << ')';
2160           return;
2161         }
2162       }
2163     }
2164   }
2165 
2166   // Pretty print addition to a negative number as a subtraction.
2167   if (auto rhsConst = rhsExpr.dyn_cast<AffineConstantExpr>()) {
2168     if (rhsConst.getValue() < 0) {
2169       printAffineExprInternal(lhsExpr, BindingStrength::Weak, printValueName);
2170       os << " - " << -rhsConst.getValue();
2171       if (enclosingTightness == BindingStrength::Strong)
2172         os << ')';
2173       return;
2174     }
2175   }
2176 
2177   printAffineExprInternal(lhsExpr, BindingStrength::Weak, printValueName);
2178 
2179   os << " + ";
2180   printAffineExprInternal(rhsExpr, BindingStrength::Weak, printValueName);
2181 
2182   if (enclosingTightness == BindingStrength::Strong)
2183     os << ')';
2184 }
2185 
2186 void ModulePrinter::printAffineConstraint(AffineExpr expr, bool isEq) {
2187   printAffineExprInternal(expr, BindingStrength::Weak);
2188   isEq ? os << " == 0" : os << " >= 0";
2189 }
2190 
2191 void ModulePrinter::printAffineMap(AffineMap map) {
2192   // Dimension identifiers.
2193   os << '(';
2194   for (int i = 0; i < (int)map.getNumDims() - 1; ++i)
2195     os << 'd' << i << ", ";
2196   if (map.getNumDims() >= 1)
2197     os << 'd' << map.getNumDims() - 1;
2198   os << ')';
2199 
2200   // Symbolic identifiers.
2201   if (map.getNumSymbols() != 0) {
2202     os << '[';
2203     for (unsigned i = 0; i < map.getNumSymbols() - 1; ++i)
2204       os << 's' << i << ", ";
2205     if (map.getNumSymbols() >= 1)
2206       os << 's' << map.getNumSymbols() - 1;
2207     os << ']';
2208   }
2209 
2210   // Result affine expressions.
2211   os << " -> (";
2212   interleaveComma(map.getResults(),
2213                   [&](AffineExpr expr) { printAffineExpr(expr); });
2214   os << ')';
2215 }
2216 
2217 void ModulePrinter::printIntegerSet(IntegerSet set) {
2218   // Dimension identifiers.
2219   os << '(';
2220   for (unsigned i = 1; i < set.getNumDims(); ++i)
2221     os << 'd' << i - 1 << ", ";
2222   if (set.getNumDims() >= 1)
2223     os << 'd' << set.getNumDims() - 1;
2224   os << ')';
2225 
2226   // Symbolic identifiers.
2227   if (set.getNumSymbols() != 0) {
2228     os << '[';
2229     for (unsigned i = 0; i < set.getNumSymbols() - 1; ++i)
2230       os << 's' << i << ", ";
2231     if (set.getNumSymbols() >= 1)
2232       os << 's' << set.getNumSymbols() - 1;
2233     os << ']';
2234   }
2235 
2236   // Print constraints.
2237   os << " : (";
2238   int numConstraints = set.getNumConstraints();
2239   for (int i = 1; i < numConstraints; ++i) {
2240     printAffineConstraint(set.getConstraint(i - 1), set.isEq(i - 1));
2241     os << ", ";
2242   }
2243   if (numConstraints >= 1)
2244     printAffineConstraint(set.getConstraint(numConstraints - 1),
2245                           set.isEq(numConstraints - 1));
2246   os << ')';
2247 }
2248 
2249 //===----------------------------------------------------------------------===//
2250 // OperationPrinter
2251 //===----------------------------------------------------------------------===//
2252 
2253 namespace {
2254 /// This class contains the logic for printing operations, regions, and blocks.
2255 class OperationPrinter : public ModulePrinter, private OpAsmPrinter {
2256 public:
2257   explicit OperationPrinter(raw_ostream &os, OpPrintingFlags flags,
2258                             AsmStateImpl &state)
2259       : ModulePrinter(os, flags, &state) {}
2260 
2261   /// Print the given top-level operation.
2262   void printTopLevelOperation(Operation *op);
2263 
2264   /// Print the given operation with its indent and location.
2265   void print(Operation *op);
2266   /// Print the bare location, not including indentation/location/etc.
2267   void printOperation(Operation *op);
2268   /// Print the given operation in the generic form.
2269   void printGenericOp(Operation *op) override;
2270 
2271   /// Print the name of the given block.
2272   void printBlockName(Block *block);
2273 
2274   /// Print the given block. If 'printBlockArgs' is false, the arguments of the
2275   /// block are not printed. If 'printBlockTerminator' is false, the terminator
2276   /// operation of the block is not printed.
2277   void print(Block *block, bool printBlockArgs = true,
2278              bool printBlockTerminator = true);
2279 
2280   /// Print the ID of the given value, optionally with its result number.
2281   void printValueID(Value value, bool printResultNo = true,
2282                     raw_ostream *streamOverride = nullptr) const;
2283 
2284   //===--------------------------------------------------------------------===//
2285   // OpAsmPrinter methods
2286   //===--------------------------------------------------------------------===//
2287 
2288   /// Return the current stream of the printer.
2289   raw_ostream &getStream() const override { return os; }
2290 
2291   /// Print a newline and indent the printer to the start of the current
2292   /// operation.
2293   void printNewline() override {
2294     os << newLine;
2295     os.indent(currentIndent);
2296   }
2297 
2298   /// Print the given type.
2299   void printType(Type type) override { ModulePrinter::printType(type); }
2300 
2301   /// Print the given attribute.
2302   void printAttribute(Attribute attr) override {
2303     ModulePrinter::printAttribute(attr);
2304   }
2305 
2306   /// Print the given attribute without its type. The corresponding parser must
2307   /// provide a valid type for the attribute.
2308   void printAttributeWithoutType(Attribute attr) override {
2309     ModulePrinter::printAttribute(attr, AttrTypeElision::Must);
2310   }
2311 
2312   /// Print the ID for the given value.
2313   void printOperand(Value value) override { printValueID(value); }
2314   void printOperand(Value value, raw_ostream &os) override {
2315     printValueID(value, /*printResultNo=*/true, &os);
2316   }
2317 
2318   /// Print an optional attribute dictionary with a given set of elided values.
2319   void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
2320                              ArrayRef<StringRef> elidedAttrs = {}) override {
2321     ModulePrinter::printOptionalAttrDict(attrs, elidedAttrs);
2322   }
2323   void printOptionalAttrDictWithKeyword(
2324       ArrayRef<NamedAttribute> attrs,
2325       ArrayRef<StringRef> elidedAttrs = {}) override {
2326     ModulePrinter::printOptionalAttrDict(attrs, elidedAttrs,
2327                                          /*withKeyword=*/true);
2328   }
2329 
2330   /// Print the given successor.
2331   void printSuccessor(Block *successor) override;
2332 
2333   /// Print an operation successor with the operands used for the block
2334   /// arguments.
2335   void printSuccessorAndUseList(Block *successor,
2336                                 ValueRange succOperands) override;
2337 
2338   /// Print the given region.
2339   void printRegion(Region &region, bool printEntryBlockArgs,
2340                    bool printBlockTerminators, bool printEmptyBlock) override;
2341 
2342   /// Renumber the arguments for the specified region to the same names as the
2343   /// SSA values in namesToUse. This may only be used for IsolatedFromAbove
2344   /// operations. If any entry in namesToUse is null, the corresponding
2345   /// argument name is left alone.
2346   void shadowRegionArgs(Region &region, ValueRange namesToUse) override {
2347     state->getSSANameState().shadowRegionArgs(region, namesToUse);
2348   }
2349 
2350   /// Print the given affine map with the symbol and dimension operands printed
2351   /// inline with the map.
2352   void printAffineMapOfSSAIds(AffineMapAttr mapAttr,
2353                               ValueRange operands) override;
2354 
2355   /// Print the given affine expression with the symbol and dimension operands
2356   /// printed inline with the expression.
2357   void printAffineExprOfSSAIds(AffineExpr expr, ValueRange dimOperands,
2358                                ValueRange symOperands) override;
2359 
2360   /// Print the given string as a symbol reference.
2361   void printSymbolName(StringRef symbolRef) override {
2362     ::printSymbolReference(symbolRef, os);
2363   }
2364 
2365 private:
2366   /// The number of spaces used for indenting nested operations.
2367   const static unsigned indentWidth = 2;
2368 
2369   // This is the current indentation level for nested structures.
2370   unsigned currentIndent = 0;
2371 };
2372 } // end anonymous namespace
2373 
2374 void OperationPrinter::printTopLevelOperation(Operation *op) {
2375   // Output the aliases at the top level that can't be deferred.
2376   state->getAliasState().printNonDeferredAliases(os, newLine);
2377 
2378   // Print the module.
2379   print(op);
2380   os << newLine;
2381 
2382   // Output the aliases at the top level that can be deferred.
2383   state->getAliasState().printDeferredAliases(os, newLine);
2384 }
2385 
2386 void OperationPrinter::print(Operation *op) {
2387   // Track the location of this operation.
2388   state->registerOperationLocation(op, newLine.curLine, currentIndent);
2389 
2390   os.indent(currentIndent);
2391   printOperation(op);
2392   printTrailingLocation(op->getLoc());
2393 }
2394 
2395 void OperationPrinter::printOperation(Operation *op) {
2396   if (size_t numResults = op->getNumResults()) {
2397     auto printResultGroup = [&](size_t resultNo, size_t resultCount) {
2398       printValueID(op->getResult(resultNo), /*printResultNo=*/false);
2399       if (resultCount > 1)
2400         os << ':' << resultCount;
2401     };
2402 
2403     // Check to see if this operation has multiple result groups.
2404     ArrayRef<int> resultGroups = state->getSSANameState().getOpResultGroups(op);
2405     if (!resultGroups.empty()) {
2406       // Interleave the groups excluding the last one, this one will be handled
2407       // separately.
2408       interleaveComma(llvm::seq<int>(0, resultGroups.size() - 1), [&](int i) {
2409         printResultGroup(resultGroups[i],
2410                          resultGroups[i + 1] - resultGroups[i]);
2411       });
2412       os << ", ";
2413       printResultGroup(resultGroups.back(), numResults - resultGroups.back());
2414 
2415     } else {
2416       printResultGroup(/*resultNo=*/0, /*resultCount=*/numResults);
2417     }
2418 
2419     os << " = ";
2420   }
2421 
2422   // If requested, always print the generic form.
2423   if (!printerFlags.shouldPrintGenericOpForm()) {
2424     // Check to see if this is a known operation.  If so, use the registered
2425     // custom printer hook.
2426     if (auto *opInfo = op->getAbstractOperation()) {
2427       opInfo->printAssembly(op, *this);
2428       return;
2429     }
2430     // Otherwise try to dispatch to the dialect, if available.
2431     if (Dialect *dialect = op->getDialect()) {
2432       if (succeeded(dialect->printOperation(op, *this)))
2433         return;
2434     }
2435   }
2436 
2437   // Otherwise print with the generic assembly form.
2438   printGenericOp(op);
2439 }
2440 
2441 void OperationPrinter::printGenericOp(Operation *op) {
2442   os << '"';
2443   printEscapedString(op->getName().getStringRef(), os);
2444   os << "\"(";
2445   interleaveComma(op->getOperands(), [&](Value value) { printValueID(value); });
2446   os << ')';
2447 
2448   // For terminators, print the list of successors and their operands.
2449   if (op->getNumSuccessors() != 0) {
2450     os << '[';
2451     interleaveComma(op->getSuccessors(),
2452                     [&](Block *successor) { printBlockName(successor); });
2453     os << ']';
2454   }
2455 
2456   // Print regions.
2457   if (op->getNumRegions() != 0) {
2458     os << " (";
2459     interleaveComma(op->getRegions(), [&](Region &region) {
2460       printRegion(region, /*printEntryBlockArgs=*/true,
2461                   /*printBlockTerminators=*/true, /*printEmptyBlock=*/true);
2462     });
2463     os << ')';
2464   }
2465 
2466   auto attrs = op->getAttrs();
2467   printOptionalAttrDict(attrs);
2468 
2469   // Print the type signature of the operation.
2470   os << " : ";
2471   printFunctionalType(op);
2472 }
2473 
2474 void OperationPrinter::printBlockName(Block *block) {
2475   auto id = state->getSSANameState().getBlockID(block);
2476   if (id != SSANameState::NameSentinel)
2477     os << "^bb" << id;
2478   else
2479     os << "^INVALIDBLOCK";
2480 }
2481 
2482 void OperationPrinter::print(Block *block, bool printBlockArgs,
2483                              bool printBlockTerminator) {
2484   // Print the block label and argument list if requested.
2485   if (printBlockArgs) {
2486     os.indent(currentIndent);
2487     printBlockName(block);
2488 
2489     // Print the argument list if non-empty.
2490     if (!block->args_empty()) {
2491       os << '(';
2492       interleaveComma(block->getArguments(), [&](BlockArgument arg) {
2493         printValueID(arg);
2494         os << ": ";
2495         printType(arg.getType());
2496       });
2497       os << ')';
2498     }
2499     os << ':';
2500 
2501     // Print out some context information about the predecessors of this block.
2502     if (!block->getParent()) {
2503       os << "  // block is not in a region!";
2504     } else if (block->hasNoPredecessors()) {
2505       os << "  // no predecessors";
2506     } else if (auto *pred = block->getSinglePredecessor()) {
2507       os << "  // pred: ";
2508       printBlockName(pred);
2509     } else {
2510       // We want to print the predecessors in increasing numeric order, not in
2511       // whatever order the use-list is in, so gather and sort them.
2512       SmallVector<std::pair<unsigned, Block *>, 4> predIDs;
2513       for (auto *pred : block->getPredecessors())
2514         predIDs.push_back({state->getSSANameState().getBlockID(pred), pred});
2515       llvm::array_pod_sort(predIDs.begin(), predIDs.end());
2516 
2517       os << "  // " << predIDs.size() << " preds: ";
2518 
2519       interleaveComma(predIDs, [&](std::pair<unsigned, Block *> pred) {
2520         printBlockName(pred.second);
2521       });
2522     }
2523     os << newLine;
2524   }
2525 
2526   currentIndent += indentWidth;
2527   auto range = llvm::make_range(
2528       block->begin(), std::prev(block->end(), printBlockTerminator ? 0 : 1));
2529   for (auto &op : range) {
2530     print(&op);
2531     os << newLine;
2532   }
2533   currentIndent -= indentWidth;
2534 }
2535 
2536 void OperationPrinter::printValueID(Value value, bool printResultNo,
2537                                     raw_ostream *streamOverride) const {
2538   state->getSSANameState().printValueID(value, printResultNo,
2539                                         streamOverride ? *streamOverride : os);
2540 }
2541 
2542 void OperationPrinter::printSuccessor(Block *successor) {
2543   printBlockName(successor);
2544 }
2545 
2546 void OperationPrinter::printSuccessorAndUseList(Block *successor,
2547                                                 ValueRange succOperands) {
2548   printBlockName(successor);
2549   if (succOperands.empty())
2550     return;
2551 
2552   os << '(';
2553   interleaveComma(succOperands,
2554                   [this](Value operand) { printValueID(operand); });
2555   os << " : ";
2556   interleaveComma(succOperands,
2557                   [this](Value operand) { printType(operand.getType()); });
2558   os << ')';
2559 }
2560 
2561 void OperationPrinter::printRegion(Region &region, bool printEntryBlockArgs,
2562                                    bool printBlockTerminators,
2563                                    bool printEmptyBlock) {
2564   os << " {" << newLine;
2565   if (!region.empty()) {
2566     auto *entryBlock = &region.front();
2567     // Force printing the block header if printEmptyBlock is set and the block
2568     // is empty or if printEntryBlockArgs is set and there are arguments to
2569     // print.
2570     bool shouldAlwaysPrintBlockHeader =
2571         (printEmptyBlock && entryBlock->empty()) ||
2572         (printEntryBlockArgs && entryBlock->getNumArguments() != 0);
2573     print(entryBlock, shouldAlwaysPrintBlockHeader, printBlockTerminators);
2574     for (auto &b : llvm::drop_begin(region.getBlocks(), 1))
2575       print(&b);
2576   }
2577   os.indent(currentIndent) << "}";
2578 }
2579 
2580 void OperationPrinter::printAffineMapOfSSAIds(AffineMapAttr mapAttr,
2581                                               ValueRange operands) {
2582   AffineMap map = mapAttr.getValue();
2583   unsigned numDims = map.getNumDims();
2584   auto printValueName = [&](unsigned pos, bool isSymbol) {
2585     unsigned index = isSymbol ? numDims + pos : pos;
2586     assert(index < operands.size());
2587     if (isSymbol)
2588       os << "symbol(";
2589     printValueID(operands[index]);
2590     if (isSymbol)
2591       os << ')';
2592   };
2593 
2594   interleaveComma(map.getResults(), [&](AffineExpr expr) {
2595     printAffineExpr(expr, printValueName);
2596   });
2597 }
2598 
2599 void OperationPrinter::printAffineExprOfSSAIds(AffineExpr expr,
2600                                                ValueRange dimOperands,
2601                                                ValueRange symOperands) {
2602   auto printValueName = [&](unsigned pos, bool isSymbol) {
2603     if (!isSymbol)
2604       return printValueID(dimOperands[pos]);
2605     os << "symbol(";
2606     printValueID(symOperands[pos]);
2607     os << ')';
2608   };
2609   printAffineExpr(expr, printValueName);
2610 }
2611 
2612 //===----------------------------------------------------------------------===//
2613 // print and dump methods
2614 //===----------------------------------------------------------------------===//
2615 
2616 void Attribute::print(raw_ostream &os) const {
2617   ModulePrinter(os).printAttribute(*this);
2618 }
2619 
2620 void Attribute::dump() const {
2621   print(llvm::errs());
2622   llvm::errs() << "\n";
2623 }
2624 
2625 void Type::print(raw_ostream &os) { ModulePrinter(os).printType(*this); }
2626 
2627 void Type::dump() { print(llvm::errs()); }
2628 
2629 void AffineMap::dump() const {
2630   print(llvm::errs());
2631   llvm::errs() << "\n";
2632 }
2633 
2634 void IntegerSet::dump() const {
2635   print(llvm::errs());
2636   llvm::errs() << "\n";
2637 }
2638 
2639 void AffineExpr::print(raw_ostream &os) const {
2640   if (!expr) {
2641     os << "<<NULL AFFINE EXPR>>";
2642     return;
2643   }
2644   ModulePrinter(os).printAffineExpr(*this);
2645 }
2646 
2647 void AffineExpr::dump() const {
2648   print(llvm::errs());
2649   llvm::errs() << "\n";
2650 }
2651 
2652 void AffineMap::print(raw_ostream &os) const {
2653   if (!map) {
2654     os << "<<NULL AFFINE MAP>>";
2655     return;
2656   }
2657   ModulePrinter(os).printAffineMap(*this);
2658 }
2659 
2660 void IntegerSet::print(raw_ostream &os) const {
2661   ModulePrinter(os).printIntegerSet(*this);
2662 }
2663 
2664 void Value::print(raw_ostream &os) {
2665   if (auto *op = getDefiningOp())
2666     return op->print(os);
2667   // TODO: Improve this.
2668   BlockArgument arg = this->cast<BlockArgument>();
2669   os << "<block argument> of type '" << arg.getType()
2670      << "' at index: " << arg.getArgNumber() << '\n';
2671 }
2672 void Value::print(raw_ostream &os, AsmState &state) {
2673   if (auto *op = getDefiningOp())
2674     return op->print(os, state);
2675 
2676   // TODO: Improve this.
2677   BlockArgument arg = this->cast<BlockArgument>();
2678   os << "<block argument> of type '" << arg.getType()
2679      << "' at index: " << arg.getArgNumber() << '\n';
2680 }
2681 
2682 void Value::dump() {
2683   print(llvm::errs());
2684   llvm::errs() << "\n";
2685 }
2686 
2687 void Value::printAsOperand(raw_ostream &os, AsmState &state) {
2688   // TODO: This doesn't necessarily capture all potential cases.
2689   // Currently, region arguments can be shadowed when printing the main
2690   // operation. If the IR hasn't been printed, this will produce the old SSA
2691   // name and not the shadowed name.
2692   state.getImpl().getSSANameState().printValueID(*this, /*printResultNo=*/true,
2693                                                  os);
2694 }
2695 
2696 void Operation::print(raw_ostream &os, OpPrintingFlags flags) {
2697   // If this is a top level operation, we also print aliases.
2698   if (!getParent() && !flags.shouldUseLocalScope()) {
2699     AsmState state(this);
2700     state.getImpl().initializeAliases(this, flags);
2701     print(os, state, flags);
2702     return;
2703   }
2704 
2705   // Find the operation to number from based upon the provided flags.
2706   Operation *op = this;
2707   bool shouldUseLocalScope = flags.shouldUseLocalScope();
2708   do {
2709     // If we are printing local scope, stop at the first operation that is
2710     // isolated from above.
2711     if (shouldUseLocalScope && op->hasTrait<OpTrait::IsIsolatedFromAbove>())
2712       break;
2713 
2714     // Otherwise, traverse up to the next parent.
2715     Operation *parentOp = op->getParentOp();
2716     if (!parentOp)
2717       break;
2718     op = parentOp;
2719   } while (true);
2720 
2721   AsmState state(op);
2722   print(os, state, flags);
2723 }
2724 void Operation::print(raw_ostream &os, AsmState &state, OpPrintingFlags flags) {
2725   OperationPrinter printer(os, flags, state.getImpl());
2726   if (!getParent() && !flags.shouldUseLocalScope())
2727     printer.printTopLevelOperation(this);
2728   else
2729     printer.print(this);
2730 }
2731 
2732 void Operation::dump() {
2733   print(llvm::errs(), OpPrintingFlags().useLocalScope());
2734   llvm::errs() << "\n";
2735 }
2736 
2737 void Block::print(raw_ostream &os) {
2738   Operation *parentOp = getParentOp();
2739   if (!parentOp) {
2740     os << "<<UNLINKED BLOCK>>\n";
2741     return;
2742   }
2743   // Get the top-level op.
2744   while (auto *nextOp = parentOp->getParentOp())
2745     parentOp = nextOp;
2746 
2747   AsmState state(parentOp);
2748   print(os, state);
2749 }
2750 void Block::print(raw_ostream &os, AsmState &state) {
2751   OperationPrinter(os, /*flags=*/llvm::None, state.getImpl()).print(this);
2752 }
2753 
2754 void Block::dump() { print(llvm::errs()); }
2755 
2756 /// Print out the name of the block without printing its body.
2757 void Block::printAsOperand(raw_ostream &os, bool printType) {
2758   Operation *parentOp = getParentOp();
2759   if (!parentOp) {
2760     os << "<<UNLINKED BLOCK>>\n";
2761     return;
2762   }
2763   AsmState state(parentOp);
2764   printAsOperand(os, state);
2765 }
2766 void Block::printAsOperand(raw_ostream &os, AsmState &state) {
2767   OperationPrinter printer(os, /*flags=*/llvm::None, state.getImpl());
2768   printer.printBlockName(this);
2769 }
2770