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