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