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