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