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