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