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