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       auto valueIt = attr.value_begin<std::complex<APInt>>();
1829       printDenseElementsAttrImpl(attr.isSplat(), type, os, [&](unsigned index) {
1830         auto complexValue = *(valueIt + index);
1831         os << "(";
1832         printDenseIntElement(complexValue.real(), os, isSigned);
1833         os << ",";
1834         printDenseIntElement(complexValue.imag(), os, isSigned);
1835         os << ")";
1836       });
1837     } else {
1838       auto valueIt = attr.value_begin<std::complex<APFloat>>();
1839       printDenseElementsAttrImpl(attr.isSplat(), type, os, [&](unsigned index) {
1840         auto complexValue = *(valueIt + index);
1841         os << "(";
1842         printFloatValue(complexValue.real(), os);
1843         os << ",";
1844         printFloatValue(complexValue.imag(), os);
1845         os << ")";
1846       });
1847     }
1848   } else if (elementType.isIntOrIndex()) {
1849     bool isSigned = !elementType.isUnsignedInteger();
1850     auto valueIt = attr.value_begin<APInt>();
1851     printDenseElementsAttrImpl(attr.isSplat(), type, os, [&](unsigned index) {
1852       printDenseIntElement(*(valueIt + index), os, isSigned);
1853     });
1854   } else {
1855     assert(elementType.isa<FloatType>() && "unexpected element type");
1856     auto valueIt = attr.value_begin<APFloat>();
1857     printDenseElementsAttrImpl(attr.isSplat(), type, os, [&](unsigned index) {
1858       printFloatValue(*(valueIt + index), os);
1859     });
1860   }
1861 }
1862 
1863 void ModulePrinter::printDenseStringElementsAttr(DenseStringElementsAttr attr) {
1864   ArrayRef<StringRef> data = attr.getRawStringData();
1865   auto printFn = [&](unsigned index) {
1866     os << "\"";
1867     printEscapedString(data[index], os);
1868     os << "\"";
1869   };
1870   printDenseElementsAttrImpl(attr.isSplat(), attr.getType(), os, printFn);
1871 }
1872 
1873 void ModulePrinter::printType(Type type) {
1874   if (!type) {
1875     os << "<<NULL TYPE>>";
1876     return;
1877   }
1878 
1879   // Try to print an alias for this type.
1880   if (state && succeeded(state->getAliasState().getAlias(type, os)))
1881     return;
1882 
1883   TypeSwitch<Type>(type)
1884       .Case<OpaqueType>([&](OpaqueType opaqueTy) {
1885         printDialectSymbol(os, "!", opaqueTy.getDialectNamespace(),
1886                            opaqueTy.getTypeData());
1887       })
1888       .Case<IndexType>([&](Type) { os << "index"; })
1889       .Case<BFloat16Type>([&](Type) { os << "bf16"; })
1890       .Case<Float16Type>([&](Type) { os << "f16"; })
1891       .Case<Float32Type>([&](Type) { os << "f32"; })
1892       .Case<Float64Type>([&](Type) { os << "f64"; })
1893       .Case<Float80Type>([&](Type) { os << "f80"; })
1894       .Case<Float128Type>([&](Type) { os << "f128"; })
1895       .Case<IntegerType>([&](IntegerType integerTy) {
1896         if (integerTy.isSigned())
1897           os << 's';
1898         else if (integerTy.isUnsigned())
1899           os << 'u';
1900         os << 'i' << integerTy.getWidth();
1901       })
1902       .Case<FunctionType>([&](FunctionType funcTy) {
1903         os << '(';
1904         interleaveComma(funcTy.getInputs(), [&](Type ty) { printType(ty); });
1905         os << ") -> ";
1906         ArrayRef<Type> results = funcTy.getResults();
1907         if (results.size() == 1 && !results[0].isa<FunctionType>()) {
1908           os << results[0];
1909         } else {
1910           os << '(';
1911           interleaveComma(results, [&](Type ty) { printType(ty); });
1912           os << ')';
1913         }
1914       })
1915       .Case<VectorType>([&](VectorType vectorTy) {
1916         os << "vector<";
1917         for (int64_t dim : vectorTy.getShape())
1918           os << dim << 'x';
1919         os << vectorTy.getElementType() << '>';
1920       })
1921       .Case<RankedTensorType>([&](RankedTensorType tensorTy) {
1922         os << "tensor<";
1923         for (int64_t dim : tensorTy.getShape()) {
1924           if (ShapedType::isDynamic(dim))
1925             os << '?';
1926           else
1927             os << dim;
1928           os << 'x';
1929         }
1930         os << tensorTy.getElementType();
1931         // Only print the encoding attribute value if set.
1932         if (tensorTy.getEncoding()) {
1933           os << ", ";
1934           printAttribute(tensorTy.getEncoding());
1935         }
1936         os << '>';
1937       })
1938       .Case<UnrankedTensorType>([&](UnrankedTensorType tensorTy) {
1939         os << "tensor<*x";
1940         printType(tensorTy.getElementType());
1941         os << '>';
1942       })
1943       .Case<MemRefType>([&](MemRefType memrefTy) {
1944         os << "memref<";
1945         for (int64_t dim : memrefTy.getShape()) {
1946           if (ShapedType::isDynamic(dim))
1947             os << '?';
1948           else
1949             os << dim;
1950           os << 'x';
1951         }
1952         printType(memrefTy.getElementType());
1953         for (auto map : memrefTy.getAffineMaps()) {
1954           os << ", ";
1955           printAttribute(AffineMapAttr::get(map));
1956         }
1957         // Only print the memory space if it is the non-default one.
1958         if (memrefTy.getMemorySpace()) {
1959           os << ", ";
1960           printAttribute(memrefTy.getMemorySpace(), AttrTypeElision::May);
1961         }
1962         os << '>';
1963       })
1964       .Case<UnrankedMemRefType>([&](UnrankedMemRefType memrefTy) {
1965         os << "memref<*x";
1966         printType(memrefTy.getElementType());
1967         // Only print the memory space if it is the non-default one.
1968         if (memrefTy.getMemorySpace()) {
1969           os << ", ";
1970           printAttribute(memrefTy.getMemorySpace(), AttrTypeElision::May);
1971         }
1972         os << '>';
1973       })
1974       .Case<ComplexType>([&](ComplexType complexTy) {
1975         os << "complex<";
1976         printType(complexTy.getElementType());
1977         os << '>';
1978       })
1979       .Case<TupleType>([&](TupleType tupleTy) {
1980         os << "tuple<";
1981         interleaveComma(tupleTy.getTypes(),
1982                         [&](Type type) { printType(type); });
1983         os << '>';
1984       })
1985       .Case<NoneType>([&](Type) { os << "none"; })
1986       .Default([&](Type type) { return printDialectType(type); });
1987 }
1988 
1989 void ModulePrinter::printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
1990                                           ArrayRef<StringRef> elidedAttrs,
1991                                           bool withKeyword) {
1992   // If there are no attributes, then there is nothing to be done.
1993   if (attrs.empty())
1994     return;
1995 
1996   // Functor used to print a filtered attribute list.
1997   auto printFilteredAttributesFn = [&](auto filteredAttrs) {
1998     // Print the 'attributes' keyword if necessary.
1999     if (withKeyword)
2000       os << " attributes";
2001 
2002     // Otherwise, print them all out in braces.
2003     os << " {";
2004     interleaveComma(filteredAttrs,
2005                     [&](NamedAttribute attr) { printNamedAttribute(attr); });
2006     os << '}';
2007   };
2008 
2009   // If no attributes are elided, we can directly print with no filtering.
2010   if (elidedAttrs.empty())
2011     return printFilteredAttributesFn(attrs);
2012 
2013   // Otherwise, filter out any attributes that shouldn't be included.
2014   llvm::SmallDenseSet<StringRef> elidedAttrsSet(elidedAttrs.begin(),
2015                                                 elidedAttrs.end());
2016   auto filteredAttrs = llvm::make_filter_range(attrs, [&](NamedAttribute attr) {
2017     return !elidedAttrsSet.contains(attr.first.strref());
2018   });
2019   if (!filteredAttrs.empty())
2020     printFilteredAttributesFn(filteredAttrs);
2021 }
2022 
2023 void ModulePrinter::printNamedAttribute(NamedAttribute attr) {
2024   if (isBareIdentifier(attr.first)) {
2025     os << attr.first;
2026   } else {
2027     os << '"';
2028     printEscapedString(attr.first.strref(), os);
2029     os << '"';
2030   }
2031 
2032   // Pretty printing elides the attribute value for unit attributes.
2033   if (attr.second.isa<UnitAttr>())
2034     return;
2035 
2036   os << " = ";
2037   printAttribute(attr.second);
2038 }
2039 
2040 //===----------------------------------------------------------------------===//
2041 // CustomDialectAsmPrinter
2042 //===----------------------------------------------------------------------===//
2043 
2044 namespace {
2045 /// This class provides the main specialization of the DialectAsmPrinter that is
2046 /// used to provide support for print attributes and types. This hooks allows
2047 /// for dialects to hook into the main ModulePrinter.
2048 struct CustomDialectAsmPrinter : public DialectAsmPrinter {
2049 public:
2050   CustomDialectAsmPrinter(ModulePrinter &printer) : printer(printer) {}
2051   ~CustomDialectAsmPrinter() override {}
2052 
2053   raw_ostream &getStream() const override { return printer.getStream(); }
2054 
2055   /// Print the given attribute to the stream.
2056   void printAttribute(Attribute attr) override { printer.printAttribute(attr); }
2057 
2058   /// Print the given attribute without its type. The corresponding parser must
2059   /// provide a valid type for the attribute.
2060   void printAttributeWithoutType(Attribute attr) override {
2061     printer.printAttribute(attr, ModulePrinter::AttrTypeElision::Must);
2062   }
2063 
2064   /// Print the given floating point value in a stablized form.
2065   void printFloat(const APFloat &value) override {
2066     printFloatValue(value, getStream());
2067   }
2068 
2069   /// Print the given type to the stream.
2070   void printType(Type type) override { printer.printType(type); }
2071 
2072   /// The main module printer.
2073   ModulePrinter &printer;
2074 };
2075 } // end anonymous namespace
2076 
2077 void ModulePrinter::printDialectAttribute(Attribute attr) {
2078   auto &dialect = attr.getDialect();
2079 
2080   // Ask the dialect to serialize the attribute to a string.
2081   std::string attrName;
2082   {
2083     llvm::raw_string_ostream attrNameStr(attrName);
2084     ModulePrinter subPrinter(attrNameStr, printerFlags, state);
2085     CustomDialectAsmPrinter printer(subPrinter);
2086     dialect.printAttribute(attr, printer);
2087   }
2088   printDialectSymbol(os, "#", dialect.getNamespace(), attrName);
2089 }
2090 
2091 void ModulePrinter::printDialectType(Type type) {
2092   auto &dialect = type.getDialect();
2093 
2094   // Ask the dialect to serialize the type to a string.
2095   std::string typeName;
2096   {
2097     llvm::raw_string_ostream typeNameStr(typeName);
2098     ModulePrinter subPrinter(typeNameStr, printerFlags, state);
2099     CustomDialectAsmPrinter printer(subPrinter);
2100     dialect.printType(type, printer);
2101   }
2102   printDialectSymbol(os, "!", dialect.getNamespace(), typeName);
2103 }
2104 
2105 //===----------------------------------------------------------------------===//
2106 // Affine expressions and maps
2107 //===----------------------------------------------------------------------===//
2108 
2109 void ModulePrinter::printAffineExpr(
2110     AffineExpr expr, function_ref<void(unsigned, bool)> printValueName) {
2111   printAffineExprInternal(expr, BindingStrength::Weak, printValueName);
2112 }
2113 
2114 void ModulePrinter::printAffineExprInternal(
2115     AffineExpr expr, BindingStrength enclosingTightness,
2116     function_ref<void(unsigned, bool)> printValueName) {
2117   const char *binopSpelling = nullptr;
2118   switch (expr.getKind()) {
2119   case AffineExprKind::SymbolId: {
2120     unsigned pos = expr.cast<AffineSymbolExpr>().getPosition();
2121     if (printValueName)
2122       printValueName(pos, /*isSymbol=*/true);
2123     else
2124       os << 's' << pos;
2125     return;
2126   }
2127   case AffineExprKind::DimId: {
2128     unsigned pos = expr.cast<AffineDimExpr>().getPosition();
2129     if (printValueName)
2130       printValueName(pos, /*isSymbol=*/false);
2131     else
2132       os << 'd' << pos;
2133     return;
2134   }
2135   case AffineExprKind::Constant:
2136     os << expr.cast<AffineConstantExpr>().getValue();
2137     return;
2138   case AffineExprKind::Add:
2139     binopSpelling = " + ";
2140     break;
2141   case AffineExprKind::Mul:
2142     binopSpelling = " * ";
2143     break;
2144   case AffineExprKind::FloorDiv:
2145     binopSpelling = " floordiv ";
2146     break;
2147   case AffineExprKind::CeilDiv:
2148     binopSpelling = " ceildiv ";
2149     break;
2150   case AffineExprKind::Mod:
2151     binopSpelling = " mod ";
2152     break;
2153   }
2154 
2155   auto binOp = expr.cast<AffineBinaryOpExpr>();
2156   AffineExpr lhsExpr = binOp.getLHS();
2157   AffineExpr rhsExpr = binOp.getRHS();
2158 
2159   // Handle tightly binding binary operators.
2160   if (binOp.getKind() != AffineExprKind::Add) {
2161     if (enclosingTightness == BindingStrength::Strong)
2162       os << '(';
2163 
2164     // Pretty print multiplication with -1.
2165     auto rhsConst = rhsExpr.dyn_cast<AffineConstantExpr>();
2166     if (rhsConst && binOp.getKind() == AffineExprKind::Mul &&
2167         rhsConst.getValue() == -1) {
2168       os << "-";
2169       printAffineExprInternal(lhsExpr, BindingStrength::Strong, printValueName);
2170       if (enclosingTightness == BindingStrength::Strong)
2171         os << ')';
2172       return;
2173     }
2174 
2175     printAffineExprInternal(lhsExpr, BindingStrength::Strong, printValueName);
2176 
2177     os << binopSpelling;
2178     printAffineExprInternal(rhsExpr, BindingStrength::Strong, printValueName);
2179 
2180     if (enclosingTightness == BindingStrength::Strong)
2181       os << ')';
2182     return;
2183   }
2184 
2185   // Print out special "pretty" forms for add.
2186   if (enclosingTightness == BindingStrength::Strong)
2187     os << '(';
2188 
2189   // Pretty print addition to a product that has a negative operand as a
2190   // subtraction.
2191   if (auto rhs = rhsExpr.dyn_cast<AffineBinaryOpExpr>()) {
2192     if (rhs.getKind() == AffineExprKind::Mul) {
2193       AffineExpr rrhsExpr = rhs.getRHS();
2194       if (auto rrhs = rrhsExpr.dyn_cast<AffineConstantExpr>()) {
2195         if (rrhs.getValue() == -1) {
2196           printAffineExprInternal(lhsExpr, BindingStrength::Weak,
2197                                   printValueName);
2198           os << " - ";
2199           if (rhs.getLHS().getKind() == AffineExprKind::Add) {
2200             printAffineExprInternal(rhs.getLHS(), BindingStrength::Strong,
2201                                     printValueName);
2202           } else {
2203             printAffineExprInternal(rhs.getLHS(), BindingStrength::Weak,
2204                                     printValueName);
2205           }
2206 
2207           if (enclosingTightness == BindingStrength::Strong)
2208             os << ')';
2209           return;
2210         }
2211 
2212         if (rrhs.getValue() < -1) {
2213           printAffineExprInternal(lhsExpr, BindingStrength::Weak,
2214                                   printValueName);
2215           os << " - ";
2216           printAffineExprInternal(rhs.getLHS(), BindingStrength::Strong,
2217                                   printValueName);
2218           os << " * " << -rrhs.getValue();
2219           if (enclosingTightness == BindingStrength::Strong)
2220             os << ')';
2221           return;
2222         }
2223       }
2224     }
2225   }
2226 
2227   // Pretty print addition to a negative number as a subtraction.
2228   if (auto rhsConst = rhsExpr.dyn_cast<AffineConstantExpr>()) {
2229     if (rhsConst.getValue() < 0) {
2230       printAffineExprInternal(lhsExpr, BindingStrength::Weak, printValueName);
2231       os << " - " << -rhsConst.getValue();
2232       if (enclosingTightness == BindingStrength::Strong)
2233         os << ')';
2234       return;
2235     }
2236   }
2237 
2238   printAffineExprInternal(lhsExpr, BindingStrength::Weak, printValueName);
2239 
2240   os << " + ";
2241   printAffineExprInternal(rhsExpr, BindingStrength::Weak, printValueName);
2242 
2243   if (enclosingTightness == BindingStrength::Strong)
2244     os << ')';
2245 }
2246 
2247 void ModulePrinter::printAffineConstraint(AffineExpr expr, bool isEq) {
2248   printAffineExprInternal(expr, BindingStrength::Weak);
2249   isEq ? os << " == 0" : os << " >= 0";
2250 }
2251 
2252 void ModulePrinter::printAffineMap(AffineMap map) {
2253   // Dimension identifiers.
2254   os << '(';
2255   for (int i = 0; i < (int)map.getNumDims() - 1; ++i)
2256     os << 'd' << i << ", ";
2257   if (map.getNumDims() >= 1)
2258     os << 'd' << map.getNumDims() - 1;
2259   os << ')';
2260 
2261   // Symbolic identifiers.
2262   if (map.getNumSymbols() != 0) {
2263     os << '[';
2264     for (unsigned i = 0; i < map.getNumSymbols() - 1; ++i)
2265       os << 's' << i << ", ";
2266     if (map.getNumSymbols() >= 1)
2267       os << 's' << map.getNumSymbols() - 1;
2268     os << ']';
2269   }
2270 
2271   // Result affine expressions.
2272   os << " -> (";
2273   interleaveComma(map.getResults(),
2274                   [&](AffineExpr expr) { printAffineExpr(expr); });
2275   os << ')';
2276 }
2277 
2278 void ModulePrinter::printIntegerSet(IntegerSet set) {
2279   // Dimension identifiers.
2280   os << '(';
2281   for (unsigned i = 1; i < set.getNumDims(); ++i)
2282     os << 'd' << i - 1 << ", ";
2283   if (set.getNumDims() >= 1)
2284     os << 'd' << set.getNumDims() - 1;
2285   os << ')';
2286 
2287   // Symbolic identifiers.
2288   if (set.getNumSymbols() != 0) {
2289     os << '[';
2290     for (unsigned i = 0; i < set.getNumSymbols() - 1; ++i)
2291       os << 's' << i << ", ";
2292     if (set.getNumSymbols() >= 1)
2293       os << 's' << set.getNumSymbols() - 1;
2294     os << ']';
2295   }
2296 
2297   // Print constraints.
2298   os << " : (";
2299   int numConstraints = set.getNumConstraints();
2300   for (int i = 1; i < numConstraints; ++i) {
2301     printAffineConstraint(set.getConstraint(i - 1), set.isEq(i - 1));
2302     os << ", ";
2303   }
2304   if (numConstraints >= 1)
2305     printAffineConstraint(set.getConstraint(numConstraints - 1),
2306                           set.isEq(numConstraints - 1));
2307   os << ')';
2308 }
2309 
2310 //===----------------------------------------------------------------------===//
2311 // OperationPrinter
2312 //===----------------------------------------------------------------------===//
2313 
2314 namespace {
2315 /// This class contains the logic for printing operations, regions, and blocks.
2316 class OperationPrinter : public ModulePrinter, private OpAsmPrinter {
2317 public:
2318   explicit OperationPrinter(raw_ostream &os, OpPrintingFlags flags,
2319                             AsmStateImpl &state)
2320       : ModulePrinter(os, flags, &state) {}
2321 
2322   /// Print the given top-level operation.
2323   void printTopLevelOperation(Operation *op);
2324 
2325   /// Print the given operation with its indent and location.
2326   void print(Operation *op);
2327   /// Print the bare location, not including indentation/location/etc.
2328   void printOperation(Operation *op);
2329   /// Print the given operation in the generic form.
2330   void printGenericOp(Operation *op, bool printOpName) override;
2331 
2332   /// Print the name of the given block.
2333   void printBlockName(Block *block);
2334 
2335   /// Print the given block. If 'printBlockArgs' is false, the arguments of the
2336   /// block are not printed. If 'printBlockTerminator' is false, the terminator
2337   /// operation of the block is not printed.
2338   void print(Block *block, bool printBlockArgs = true,
2339              bool printBlockTerminator = true);
2340 
2341   /// Print the ID of the given value, optionally with its result number.
2342   void printValueID(Value value, bool printResultNo = true,
2343                     raw_ostream *streamOverride = nullptr) const;
2344 
2345   //===--------------------------------------------------------------------===//
2346   // OpAsmPrinter methods
2347   //===--------------------------------------------------------------------===//
2348 
2349   /// Return the current stream of the printer.
2350   raw_ostream &getStream() const override { return os; }
2351 
2352   /// Print a newline and indent the printer to the start of the current
2353   /// operation.
2354   void printNewline() override {
2355     os << newLine;
2356     os.indent(currentIndent);
2357   }
2358 
2359   /// Print the given type.
2360   void printType(Type type) override { ModulePrinter::printType(type); }
2361 
2362   /// Print the given attribute.
2363   void printAttribute(Attribute attr) override {
2364     ModulePrinter::printAttribute(attr);
2365   }
2366 
2367   /// Print the given attribute without its type. The corresponding parser must
2368   /// provide a valid type for the attribute.
2369   void printAttributeWithoutType(Attribute attr) override {
2370     ModulePrinter::printAttribute(attr, AttrTypeElision::Must);
2371   }
2372 
2373   /// Print a block argument in the usual format of:
2374   ///   %ssaName : type {attr1=42} loc("here")
2375   /// where location printing is controlled by the standard internal option.
2376   /// You may pass omitType=true to not print a type, and pass an empty
2377   /// attribute list if you don't care for attributes.
2378   void printRegionArgument(BlockArgument arg,
2379                            ArrayRef<NamedAttribute> argAttrs = {},
2380                            bool omitType = false) override;
2381 
2382   /// Print the ID for the given value.
2383   void printOperand(Value value) override { printValueID(value); }
2384   void printOperand(Value value, raw_ostream &os) override {
2385     printValueID(value, /*printResultNo=*/true, &os);
2386   }
2387 
2388   /// Print an optional attribute dictionary with a given set of elided values.
2389   void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
2390                              ArrayRef<StringRef> elidedAttrs = {}) override {
2391     ModulePrinter::printOptionalAttrDict(attrs, elidedAttrs);
2392   }
2393   void printOptionalAttrDictWithKeyword(
2394       ArrayRef<NamedAttribute> attrs,
2395       ArrayRef<StringRef> elidedAttrs = {}) override {
2396     ModulePrinter::printOptionalAttrDict(attrs, elidedAttrs,
2397                                          /*withKeyword=*/true);
2398   }
2399 
2400   /// Print the given successor.
2401   void printSuccessor(Block *successor) override;
2402 
2403   /// Print an operation successor with the operands used for the block
2404   /// arguments.
2405   void printSuccessorAndUseList(Block *successor,
2406                                 ValueRange succOperands) override;
2407 
2408   /// Print the given region.
2409   void printRegion(Region &region, bool printEntryBlockArgs,
2410                    bool printBlockTerminators, bool printEmptyBlock) override;
2411 
2412   /// Renumber the arguments for the specified region to the same names as the
2413   /// SSA values in namesToUse. This may only be used for IsolatedFromAbove
2414   /// operations. If any entry in namesToUse is null, the corresponding
2415   /// argument name is left alone.
2416   void shadowRegionArgs(Region &region, ValueRange namesToUse) override {
2417     state->getSSANameState().shadowRegionArgs(region, namesToUse);
2418   }
2419 
2420   /// Print the given affine map with the symbol and dimension operands printed
2421   /// inline with the map.
2422   void printAffineMapOfSSAIds(AffineMapAttr mapAttr,
2423                               ValueRange operands) override;
2424 
2425   /// Print the given affine expression with the symbol and dimension operands
2426   /// printed inline with the expression.
2427   void printAffineExprOfSSAIds(AffineExpr expr, ValueRange dimOperands,
2428                                ValueRange symOperands) override;
2429 
2430   /// Print the given string as a symbol reference.
2431   void printSymbolName(StringRef symbolRef) override {
2432     ::printSymbolReference(symbolRef, os);
2433   }
2434 
2435 private:
2436   // Contains the stack of default dialects to use when printing regions.
2437   // A new dialect is pushed to the stack before parsing regions nested under an
2438   // operation implementing `OpAsmOpInterface`, and popped when done. At the
2439   // top-level we start with "builtin" as the default, so that the top-level
2440   // `module` operation prints as-is.
2441   SmallVector<StringRef> defaultDialectStack{"builtin"};
2442 
2443   /// The number of spaces used for indenting nested operations.
2444   const static unsigned indentWidth = 2;
2445 
2446   // This is the current indentation level for nested structures.
2447   unsigned currentIndent = 0;
2448 };
2449 } // end anonymous namespace
2450 
2451 void OperationPrinter::printTopLevelOperation(Operation *op) {
2452   // Output the aliases at the top level that can't be deferred.
2453   state->getAliasState().printNonDeferredAliases(os, newLine);
2454 
2455   // Print the module.
2456   print(op);
2457   os << newLine;
2458 
2459   // Output the aliases at the top level that can be deferred.
2460   state->getAliasState().printDeferredAliases(os, newLine);
2461 }
2462 
2463 /// Print a block argument in the usual format of:
2464 ///   %ssaName : type {attr1=42} loc("here")
2465 /// where location printing is controlled by the standard internal option.
2466 /// You may pass omitType=true to not print a type, and pass an empty
2467 /// attribute list if you don't care for attributes.
2468 void OperationPrinter::printRegionArgument(BlockArgument arg,
2469                                            ArrayRef<NamedAttribute> argAttrs,
2470                                            bool omitType) {
2471   printOperand(arg);
2472   if (!omitType) {
2473     os << ": ";
2474     printType(arg.getType());
2475   }
2476   printOptionalAttrDict(argAttrs);
2477   // TODO: We should allow location aliases on block arguments.
2478   printTrailingLocation(arg.getLoc(), /*allowAlias*/ false);
2479 }
2480 
2481 void OperationPrinter::print(Operation *op) {
2482   // Track the location of this operation.
2483   state->registerOperationLocation(op, newLine.curLine, currentIndent);
2484 
2485   os.indent(currentIndent);
2486   printOperation(op);
2487   printTrailingLocation(op->getLoc());
2488 }
2489 
2490 void OperationPrinter::printOperation(Operation *op) {
2491   if (size_t numResults = op->getNumResults()) {
2492     auto printResultGroup = [&](size_t resultNo, size_t resultCount) {
2493       printValueID(op->getResult(resultNo), /*printResultNo=*/false);
2494       if (resultCount > 1)
2495         os << ':' << resultCount;
2496     };
2497 
2498     // Check to see if this operation has multiple result groups.
2499     ArrayRef<int> resultGroups = state->getSSANameState().getOpResultGroups(op);
2500     if (!resultGroups.empty()) {
2501       // Interleave the groups excluding the last one, this one will be handled
2502       // separately.
2503       interleaveComma(llvm::seq<int>(0, resultGroups.size() - 1), [&](int i) {
2504         printResultGroup(resultGroups[i],
2505                          resultGroups[i + 1] - resultGroups[i]);
2506       });
2507       os << ", ";
2508       printResultGroup(resultGroups.back(), numResults - resultGroups.back());
2509 
2510     } else {
2511       printResultGroup(/*resultNo=*/0, /*resultCount=*/numResults);
2512     }
2513 
2514     os << " = ";
2515   }
2516 
2517   // If requested, always print the generic form.
2518   if (!printerFlags.shouldPrintGenericOpForm()) {
2519     // Check to see if this is a known operation.  If so, use the registered
2520     // custom printer hook.
2521     if (auto *opInfo = op->getAbstractOperation()) {
2522       opInfo->printAssembly(op, *this, defaultDialectStack.back());
2523       return;
2524     }
2525     // Otherwise try to dispatch to the dialect, if available.
2526     if (Dialect *dialect = op->getDialect()) {
2527       if (auto opPrinter = dialect->getOperationPrinter(op)) {
2528         // Print the op name first.
2529         StringRef name = op->getName().getStringRef();
2530         name.consume_front((defaultDialectStack.back() + ".").str());
2531         printEscapedString(name, os);
2532         // Print the rest of the op now.
2533         opPrinter(op, *this);
2534         return;
2535       }
2536     }
2537   }
2538 
2539   // Otherwise print with the generic assembly form.
2540   printGenericOp(op, /*printOpName=*/true);
2541 }
2542 
2543 void OperationPrinter::printGenericOp(Operation *op, bool printOpName) {
2544   if (printOpName) {
2545     os << '"';
2546     printEscapedString(op->getName().getStringRef(), os);
2547     os << '"';
2548   }
2549   os << '(';
2550   interleaveComma(op->getOperands(), [&](Value value) { printValueID(value); });
2551   os << ')';
2552 
2553   // For terminators, print the list of successors and their operands.
2554   if (op->getNumSuccessors() != 0) {
2555     os << '[';
2556     interleaveComma(op->getSuccessors(),
2557                     [&](Block *successor) { printBlockName(successor); });
2558     os << ']';
2559   }
2560 
2561   // Print regions.
2562   if (op->getNumRegions() != 0) {
2563     os << " (";
2564     interleaveComma(op->getRegions(), [&](Region &region) {
2565       printRegion(region, /*printEntryBlockArgs=*/true,
2566                   /*printBlockTerminators=*/true, /*printEmptyBlock=*/true);
2567     });
2568     os << ')';
2569   }
2570 
2571   auto attrs = op->getAttrs();
2572   printOptionalAttrDict(attrs);
2573 
2574   // Print the type signature of the operation.
2575   os << " : ";
2576   printFunctionalType(op);
2577 }
2578 
2579 void OperationPrinter::printBlockName(Block *block) {
2580   auto id = state->getSSANameState().getBlockID(block);
2581   if (id != SSANameState::NameSentinel)
2582     os << "^bb" << id;
2583   else
2584     os << "^INVALIDBLOCK";
2585 }
2586 
2587 void OperationPrinter::print(Block *block, bool printBlockArgs,
2588                              bool printBlockTerminator) {
2589   // Print the block label and argument list if requested.
2590   if (printBlockArgs) {
2591     os.indent(currentIndent);
2592     printBlockName(block);
2593 
2594     // Print the argument list if non-empty.
2595     if (!block->args_empty()) {
2596       os << '(';
2597       interleaveComma(block->getArguments(), [&](BlockArgument arg) {
2598         printValueID(arg);
2599         os << ": ";
2600         printType(arg.getType());
2601         // TODO: We should allow location aliases on block arguments.
2602         printTrailingLocation(arg.getLoc(), /*allowAlias*/ false);
2603       });
2604       os << ')';
2605     }
2606     os << ':';
2607 
2608     // Print out some context information about the predecessors of this block.
2609     if (!block->getParent()) {
2610       os << "  // block is not in a region!";
2611     } else if (block->hasNoPredecessors()) {
2612       os << "  // no predecessors";
2613     } else if (auto *pred = block->getSinglePredecessor()) {
2614       os << "  // pred: ";
2615       printBlockName(pred);
2616     } else {
2617       // We want to print the predecessors in increasing numeric order, not in
2618       // whatever order the use-list is in, so gather and sort them.
2619       SmallVector<std::pair<unsigned, Block *>, 4> predIDs;
2620       for (auto *pred : block->getPredecessors())
2621         predIDs.push_back({state->getSSANameState().getBlockID(pred), pred});
2622       llvm::array_pod_sort(predIDs.begin(), predIDs.end());
2623 
2624       os << "  // " << predIDs.size() << " preds: ";
2625 
2626       interleaveComma(predIDs, [&](std::pair<unsigned, Block *> pred) {
2627         printBlockName(pred.second);
2628       });
2629     }
2630     os << newLine;
2631   }
2632 
2633   currentIndent += indentWidth;
2634   bool hasTerminator =
2635       !block->empty() && block->back().hasTrait<OpTrait::IsTerminator>();
2636   auto range = llvm::make_range(
2637       block->begin(),
2638       std::prev(block->end(),
2639                 (!hasTerminator || printBlockTerminator) ? 0 : 1));
2640   for (auto &op : range) {
2641     print(&op);
2642     os << newLine;
2643   }
2644   currentIndent -= indentWidth;
2645 }
2646 
2647 void OperationPrinter::printValueID(Value value, bool printResultNo,
2648                                     raw_ostream *streamOverride) const {
2649   state->getSSANameState().printValueID(value, printResultNo,
2650                                         streamOverride ? *streamOverride : os);
2651 }
2652 
2653 void OperationPrinter::printSuccessor(Block *successor) {
2654   printBlockName(successor);
2655 }
2656 
2657 void OperationPrinter::printSuccessorAndUseList(Block *successor,
2658                                                 ValueRange succOperands) {
2659   printBlockName(successor);
2660   if (succOperands.empty())
2661     return;
2662 
2663   os << '(';
2664   interleaveComma(succOperands,
2665                   [this](Value operand) { printValueID(operand); });
2666   os << " : ";
2667   interleaveComma(succOperands,
2668                   [this](Value operand) { printType(operand.getType()); });
2669   os << ')';
2670 }
2671 
2672 void OperationPrinter::printRegion(Region &region, bool printEntryBlockArgs,
2673                                    bool printBlockTerminators,
2674                                    bool printEmptyBlock) {
2675   os << " {" << newLine;
2676   if (!region.empty()) {
2677     auto restoreDefaultDialect =
2678         llvm::make_scope_exit([&]() { defaultDialectStack.pop_back(); });
2679     if (auto iface = dyn_cast<OpAsmOpInterface>(region.getParentOp()))
2680       defaultDialectStack.push_back(iface.getDefaultDialect());
2681     else
2682       defaultDialectStack.push_back("");
2683 
2684     auto *entryBlock = &region.front();
2685     // Force printing the block header if printEmptyBlock is set and the block
2686     // is empty or if printEntryBlockArgs is set and there are arguments to
2687     // print.
2688     bool shouldAlwaysPrintBlockHeader =
2689         (printEmptyBlock && entryBlock->empty()) ||
2690         (printEntryBlockArgs && entryBlock->getNumArguments() != 0);
2691     print(entryBlock, shouldAlwaysPrintBlockHeader, printBlockTerminators);
2692     for (auto &b : llvm::drop_begin(region.getBlocks(), 1))
2693       print(&b);
2694   }
2695   os.indent(currentIndent) << "}";
2696 }
2697 
2698 void OperationPrinter::printAffineMapOfSSAIds(AffineMapAttr mapAttr,
2699                                               ValueRange operands) {
2700   AffineMap map = mapAttr.getValue();
2701   unsigned numDims = map.getNumDims();
2702   auto printValueName = [&](unsigned pos, bool isSymbol) {
2703     unsigned index = isSymbol ? numDims + pos : pos;
2704     assert(index < operands.size());
2705     if (isSymbol)
2706       os << "symbol(";
2707     printValueID(operands[index]);
2708     if (isSymbol)
2709       os << ')';
2710   };
2711 
2712   interleaveComma(map.getResults(), [&](AffineExpr expr) {
2713     printAffineExpr(expr, printValueName);
2714   });
2715 }
2716 
2717 void OperationPrinter::printAffineExprOfSSAIds(AffineExpr expr,
2718                                                ValueRange dimOperands,
2719                                                ValueRange symOperands) {
2720   auto printValueName = [&](unsigned pos, bool isSymbol) {
2721     if (!isSymbol)
2722       return printValueID(dimOperands[pos]);
2723     os << "symbol(";
2724     printValueID(symOperands[pos]);
2725     os << ')';
2726   };
2727   printAffineExpr(expr, printValueName);
2728 }
2729 
2730 //===----------------------------------------------------------------------===//
2731 // print and dump methods
2732 //===----------------------------------------------------------------------===//
2733 
2734 void Attribute::print(raw_ostream &os) const {
2735   ModulePrinter(os).printAttribute(*this);
2736 }
2737 
2738 void Attribute::dump() const {
2739   print(llvm::errs());
2740   llvm::errs() << "\n";
2741 }
2742 
2743 void Type::print(raw_ostream &os) const { ModulePrinter(os).printType(*this); }
2744 
2745 void Type::dump() const { print(llvm::errs()); }
2746 
2747 void AffineMap::dump() const {
2748   print(llvm::errs());
2749   llvm::errs() << "\n";
2750 }
2751 
2752 void IntegerSet::dump() const {
2753   print(llvm::errs());
2754   llvm::errs() << "\n";
2755 }
2756 
2757 void AffineExpr::print(raw_ostream &os) const {
2758   if (!expr) {
2759     os << "<<NULL AFFINE EXPR>>";
2760     return;
2761   }
2762   ModulePrinter(os).printAffineExpr(*this);
2763 }
2764 
2765 void AffineExpr::dump() const {
2766   print(llvm::errs());
2767   llvm::errs() << "\n";
2768 }
2769 
2770 void AffineMap::print(raw_ostream &os) const {
2771   if (!map) {
2772     os << "<<NULL AFFINE MAP>>";
2773     return;
2774   }
2775   ModulePrinter(os).printAffineMap(*this);
2776 }
2777 
2778 void IntegerSet::print(raw_ostream &os) const {
2779   ModulePrinter(os).printIntegerSet(*this);
2780 }
2781 
2782 void Value::print(raw_ostream &os) {
2783   if (auto *op = getDefiningOp())
2784     return op->print(os);
2785   // TODO: Improve BlockArgument print'ing.
2786   BlockArgument arg = this->cast<BlockArgument>();
2787   os << "<block argument> of type '" << arg.getType()
2788      << "' at index: " << arg.getArgNumber();
2789 }
2790 void Value::print(raw_ostream &os, AsmState &state) {
2791   if (auto *op = getDefiningOp())
2792     return op->print(os, state);
2793 
2794   // TODO: Improve BlockArgument print'ing.
2795   BlockArgument arg = this->cast<BlockArgument>();
2796   os << "<block argument> of type '" << arg.getType()
2797      << "' at index: " << arg.getArgNumber();
2798 }
2799 
2800 void Value::dump() {
2801   print(llvm::errs());
2802   llvm::errs() << "\n";
2803 }
2804 
2805 void Value::printAsOperand(raw_ostream &os, AsmState &state) {
2806   // TODO: This doesn't necessarily capture all potential cases.
2807   // Currently, region arguments can be shadowed when printing the main
2808   // operation. If the IR hasn't been printed, this will produce the old SSA
2809   // name and not the shadowed name.
2810   state.getImpl().getSSANameState().printValueID(*this, /*printResultNo=*/true,
2811                                                  os);
2812 }
2813 
2814 void Operation::print(raw_ostream &os, const OpPrintingFlags &printerFlags) {
2815   // If this is a top level operation, we also print aliases.
2816   if (!getParent() && !printerFlags.shouldUseLocalScope()) {
2817     AsmState state(this, printerFlags);
2818     state.getImpl().initializeAliases(this);
2819     print(os, state, printerFlags);
2820     return;
2821   }
2822 
2823   // Find the operation to number from based upon the provided flags.
2824   Operation *op = this;
2825   bool shouldUseLocalScope = printerFlags.shouldUseLocalScope();
2826   do {
2827     // If we are printing local scope, stop at the first operation that is
2828     // isolated from above.
2829     if (shouldUseLocalScope && op->hasTrait<OpTrait::IsIsolatedFromAbove>())
2830       break;
2831 
2832     // Otherwise, traverse up to the next parent.
2833     Operation *parentOp = op->getParentOp();
2834     if (!parentOp)
2835       break;
2836     op = parentOp;
2837   } while (true);
2838 
2839   AsmState state(op, printerFlags);
2840   print(os, state, printerFlags);
2841 }
2842 void Operation::print(raw_ostream &os, AsmState &state,
2843                       const OpPrintingFlags &flags) {
2844   OperationPrinter printer(os, flags, state.getImpl());
2845   if (!getParent() && !flags.shouldUseLocalScope())
2846     printer.printTopLevelOperation(this);
2847   else
2848     printer.print(this);
2849 }
2850 
2851 void Operation::dump() {
2852   print(llvm::errs(), OpPrintingFlags().useLocalScope());
2853   llvm::errs() << "\n";
2854 }
2855 
2856 void Block::print(raw_ostream &os) {
2857   Operation *parentOp = getParentOp();
2858   if (!parentOp) {
2859     os << "<<UNLINKED BLOCK>>\n";
2860     return;
2861   }
2862   // Get the top-level op.
2863   while (auto *nextOp = parentOp->getParentOp())
2864     parentOp = nextOp;
2865 
2866   AsmState state(parentOp);
2867   print(os, state);
2868 }
2869 void Block::print(raw_ostream &os, AsmState &state) {
2870   OperationPrinter(os, /*flags=*/llvm::None, state.getImpl()).print(this);
2871 }
2872 
2873 void Block::dump() { print(llvm::errs()); }
2874 
2875 /// Print out the name of the block without printing its body.
2876 void Block::printAsOperand(raw_ostream &os, bool printType) {
2877   Operation *parentOp = getParentOp();
2878   if (!parentOp) {
2879     os << "<<UNLINKED BLOCK>>\n";
2880     return;
2881   }
2882   AsmState state(parentOp);
2883   printAsOperand(os, state);
2884 }
2885 void Block::printAsOperand(raw_ostream &os, AsmState &state) {
2886   OperationPrinter printer(os, /*flags=*/llvm::None, state.getImpl());
2887   printer.printBlockName(this);
2888 }
2889