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