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 describes 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 if (!type) { 1494 os << "<<NULL TYPE>>"; 1495 return; 1496 } 1497 1498 // Check for an alias for this type. 1499 if (state) { 1500 StringRef alias = state->getAliasState().getTypeAlias(type); 1501 if (!alias.empty()) { 1502 os << '!' << alias; 1503 return; 1504 } 1505 } 1506 1507 switch (type.getKind()) { 1508 default: 1509 return printDialectType(type); 1510 1511 case Type::Kind::Opaque: { 1512 auto opaqueTy = type.cast<OpaqueType>(); 1513 printDialectSymbol(os, "!", opaqueTy.getDialectNamespace(), 1514 opaqueTy.getTypeData()); 1515 return; 1516 } 1517 case StandardTypes::Index: 1518 os << "index"; 1519 return; 1520 case StandardTypes::BF16: 1521 os << "bf16"; 1522 return; 1523 case StandardTypes::F16: 1524 os << "f16"; 1525 return; 1526 case StandardTypes::F32: 1527 os << "f32"; 1528 return; 1529 case StandardTypes::F64: 1530 os << "f64"; 1531 return; 1532 1533 case StandardTypes::Integer: { 1534 auto integer = type.cast<IntegerType>(); 1535 if (integer.isSigned()) 1536 os << 's'; 1537 else if (integer.isUnsigned()) 1538 os << 'u'; 1539 os << 'i' << integer.getWidth(); 1540 return; 1541 } 1542 case Type::Kind::Function: { 1543 auto func = type.cast<FunctionType>(); 1544 os << '('; 1545 interleaveComma(func.getInputs(), [&](Type type) { printType(type); }); 1546 os << ") -> "; 1547 auto results = func.getResults(); 1548 if (results.size() == 1 && !results[0].isa<FunctionType>()) 1549 os << results[0]; 1550 else { 1551 os << '('; 1552 interleaveComma(results, [&](Type type) { printType(type); }); 1553 os << ')'; 1554 } 1555 return; 1556 } 1557 case StandardTypes::Vector: { 1558 auto v = type.cast<VectorType>(); 1559 os << "vector<"; 1560 for (auto dim : v.getShape()) 1561 os << dim << 'x'; 1562 os << v.getElementType() << '>'; 1563 return; 1564 } 1565 case StandardTypes::RankedTensor: { 1566 auto v = type.cast<RankedTensorType>(); 1567 os << "tensor<"; 1568 for (auto dim : v.getShape()) { 1569 if (dim < 0) 1570 os << '?'; 1571 else 1572 os << dim; 1573 os << 'x'; 1574 } 1575 os << v.getElementType() << '>'; 1576 return; 1577 } 1578 case StandardTypes::UnrankedTensor: { 1579 auto v = type.cast<UnrankedTensorType>(); 1580 os << "tensor<*x"; 1581 printType(v.getElementType()); 1582 os << '>'; 1583 return; 1584 } 1585 case StandardTypes::MemRef: { 1586 auto v = type.cast<MemRefType>(); 1587 os << "memref<"; 1588 for (auto dim : v.getShape()) { 1589 if (dim < 0) 1590 os << '?'; 1591 else 1592 os << dim; 1593 os << 'x'; 1594 } 1595 printType(v.getElementType()); 1596 for (auto map : v.getAffineMaps()) { 1597 os << ", "; 1598 printAttribute(AffineMapAttr::get(map)); 1599 } 1600 // Only print the memory space if it is the non-default one. 1601 if (v.getMemorySpace()) 1602 os << ", " << v.getMemorySpace(); 1603 os << '>'; 1604 return; 1605 } 1606 case StandardTypes::UnrankedMemRef: { 1607 auto v = type.cast<UnrankedMemRefType>(); 1608 os << "memref<*x"; 1609 printType(v.getElementType()); 1610 os << '>'; 1611 return; 1612 } 1613 case StandardTypes::Complex: 1614 os << "complex<"; 1615 printType(type.cast<ComplexType>().getElementType()); 1616 os << '>'; 1617 return; 1618 case StandardTypes::Tuple: { 1619 auto tuple = type.cast<TupleType>(); 1620 os << "tuple<"; 1621 interleaveComma(tuple.getTypes(), [&](Type type) { printType(type); }); 1622 os << '>'; 1623 return; 1624 } 1625 case StandardTypes::None: 1626 os << "none"; 1627 return; 1628 } 1629 } 1630 1631 void ModulePrinter::printOptionalAttrDict(ArrayRef<NamedAttribute> attrs, 1632 ArrayRef<StringRef> elidedAttrs, 1633 bool withKeyword) { 1634 // If there are no attributes, then there is nothing to be done. 1635 if (attrs.empty()) 1636 return; 1637 1638 // Filter out any attributes that shouldn't be included. 1639 SmallVector<NamedAttribute, 8> filteredAttrs( 1640 llvm::make_filter_range(attrs, [&](NamedAttribute attr) { 1641 return !llvm::is_contained(elidedAttrs, attr.first.strref()); 1642 })); 1643 1644 // If there are no attributes left to print after filtering, then we're done. 1645 if (filteredAttrs.empty()) 1646 return; 1647 1648 // Print the 'attributes' keyword if necessary. 1649 if (withKeyword) 1650 os << " attributes"; 1651 1652 // Otherwise, print them all out in braces. 1653 os << " {"; 1654 interleaveComma(filteredAttrs, 1655 [&](NamedAttribute attr) { printNamedAttribute(attr); }); 1656 os << '}'; 1657 } 1658 1659 void ModulePrinter::printNamedAttribute(NamedAttribute attr) { 1660 if (isBareIdentifier(attr.first)) { 1661 os << attr.first; 1662 } else { 1663 os << '"'; 1664 printEscapedString(attr.first.strref(), os); 1665 os << '"'; 1666 } 1667 1668 // Pretty printing elides the attribute value for unit attributes. 1669 if (attr.second.isa<UnitAttr>()) 1670 return; 1671 1672 os << " = "; 1673 printAttribute(attr.second); 1674 } 1675 1676 //===----------------------------------------------------------------------===// 1677 // CustomDialectAsmPrinter 1678 //===----------------------------------------------------------------------===// 1679 1680 namespace { 1681 /// This class provides the main specialization of the DialectAsmPrinter that is 1682 /// used to provide support for print attributes and types. This hooks allows 1683 /// for dialects to hook into the main ModulePrinter. 1684 struct CustomDialectAsmPrinter : public DialectAsmPrinter { 1685 public: 1686 CustomDialectAsmPrinter(ModulePrinter &printer) : printer(printer) {} 1687 ~CustomDialectAsmPrinter() override {} 1688 1689 raw_ostream &getStream() const override { return printer.getStream(); } 1690 1691 /// Print the given attribute to the stream. 1692 void printAttribute(Attribute attr) override { printer.printAttribute(attr); } 1693 1694 /// Print the given floating point value in a stablized form. 1695 void printFloat(const APFloat &value) override { 1696 printFloatValue(value, getStream()); 1697 } 1698 1699 /// Print the given type to the stream. 1700 void printType(Type type) override { printer.printType(type); } 1701 1702 /// The main module printer. 1703 ModulePrinter &printer; 1704 }; 1705 } // end anonymous namespace 1706 1707 void ModulePrinter::printDialectAttribute(Attribute attr) { 1708 auto &dialect = attr.getDialect(); 1709 1710 // Ask the dialect to serialize the attribute to a string. 1711 std::string attrName; 1712 { 1713 llvm::raw_string_ostream attrNameStr(attrName); 1714 ModulePrinter subPrinter(attrNameStr, printerFlags, state); 1715 CustomDialectAsmPrinter printer(subPrinter); 1716 dialect.printAttribute(attr, printer); 1717 } 1718 printDialectSymbol(os, "#", dialect.getNamespace(), attrName); 1719 } 1720 1721 void ModulePrinter::printDialectType(Type type) { 1722 auto &dialect = type.getDialect(); 1723 1724 // Ask the dialect to serialize the type to a string. 1725 std::string typeName; 1726 { 1727 llvm::raw_string_ostream typeNameStr(typeName); 1728 ModulePrinter subPrinter(typeNameStr, printerFlags, state); 1729 CustomDialectAsmPrinter printer(subPrinter); 1730 dialect.printType(type, printer); 1731 } 1732 printDialectSymbol(os, "!", dialect.getNamespace(), typeName); 1733 } 1734 1735 //===----------------------------------------------------------------------===// 1736 // Affine expressions and maps 1737 //===----------------------------------------------------------------------===// 1738 1739 void ModulePrinter::printAffineExpr( 1740 AffineExpr expr, function_ref<void(unsigned, bool)> printValueName) { 1741 printAffineExprInternal(expr, BindingStrength::Weak, printValueName); 1742 } 1743 1744 void ModulePrinter::printAffineExprInternal( 1745 AffineExpr expr, BindingStrength enclosingTightness, 1746 function_ref<void(unsigned, bool)> printValueName) { 1747 const char *binopSpelling = nullptr; 1748 switch (expr.getKind()) { 1749 case AffineExprKind::SymbolId: { 1750 unsigned pos = expr.cast<AffineSymbolExpr>().getPosition(); 1751 if (printValueName) 1752 printValueName(pos, /*isSymbol=*/true); 1753 else 1754 os << 's' << pos; 1755 return; 1756 } 1757 case AffineExprKind::DimId: { 1758 unsigned pos = expr.cast<AffineDimExpr>().getPosition(); 1759 if (printValueName) 1760 printValueName(pos, /*isSymbol=*/false); 1761 else 1762 os << 'd' << pos; 1763 return; 1764 } 1765 case AffineExprKind::Constant: 1766 os << expr.cast<AffineConstantExpr>().getValue(); 1767 return; 1768 case AffineExprKind::Add: 1769 binopSpelling = " + "; 1770 break; 1771 case AffineExprKind::Mul: 1772 binopSpelling = " * "; 1773 break; 1774 case AffineExprKind::FloorDiv: 1775 binopSpelling = " floordiv "; 1776 break; 1777 case AffineExprKind::CeilDiv: 1778 binopSpelling = " ceildiv "; 1779 break; 1780 case AffineExprKind::Mod: 1781 binopSpelling = " mod "; 1782 break; 1783 } 1784 1785 auto binOp = expr.cast<AffineBinaryOpExpr>(); 1786 AffineExpr lhsExpr = binOp.getLHS(); 1787 AffineExpr rhsExpr = binOp.getRHS(); 1788 1789 // Handle tightly binding binary operators. 1790 if (binOp.getKind() != AffineExprKind::Add) { 1791 if (enclosingTightness == BindingStrength::Strong) 1792 os << '('; 1793 1794 // Pretty print multiplication with -1. 1795 auto rhsConst = rhsExpr.dyn_cast<AffineConstantExpr>(); 1796 if (rhsConst && binOp.getKind() == AffineExprKind::Mul && 1797 rhsConst.getValue() == -1) { 1798 os << "-"; 1799 printAffineExprInternal(lhsExpr, BindingStrength::Strong, printValueName); 1800 if (enclosingTightness == BindingStrength::Strong) 1801 os << ')'; 1802 return; 1803 } 1804 1805 printAffineExprInternal(lhsExpr, BindingStrength::Strong, printValueName); 1806 1807 os << binopSpelling; 1808 printAffineExprInternal(rhsExpr, BindingStrength::Strong, printValueName); 1809 1810 if (enclosingTightness == BindingStrength::Strong) 1811 os << ')'; 1812 return; 1813 } 1814 1815 // Print out special "pretty" forms for add. 1816 if (enclosingTightness == BindingStrength::Strong) 1817 os << '('; 1818 1819 // Pretty print addition to a product that has a negative operand as a 1820 // subtraction. 1821 if (auto rhs = rhsExpr.dyn_cast<AffineBinaryOpExpr>()) { 1822 if (rhs.getKind() == AffineExprKind::Mul) { 1823 AffineExpr rrhsExpr = rhs.getRHS(); 1824 if (auto rrhs = rrhsExpr.dyn_cast<AffineConstantExpr>()) { 1825 if (rrhs.getValue() == -1) { 1826 printAffineExprInternal(lhsExpr, BindingStrength::Weak, 1827 printValueName); 1828 os << " - "; 1829 if (rhs.getLHS().getKind() == AffineExprKind::Add) { 1830 printAffineExprInternal(rhs.getLHS(), BindingStrength::Strong, 1831 printValueName); 1832 } else { 1833 printAffineExprInternal(rhs.getLHS(), BindingStrength::Weak, 1834 printValueName); 1835 } 1836 1837 if (enclosingTightness == BindingStrength::Strong) 1838 os << ')'; 1839 return; 1840 } 1841 1842 if (rrhs.getValue() < -1) { 1843 printAffineExprInternal(lhsExpr, BindingStrength::Weak, 1844 printValueName); 1845 os << " - "; 1846 printAffineExprInternal(rhs.getLHS(), BindingStrength::Strong, 1847 printValueName); 1848 os << " * " << -rrhs.getValue(); 1849 if (enclosingTightness == BindingStrength::Strong) 1850 os << ')'; 1851 return; 1852 } 1853 } 1854 } 1855 } 1856 1857 // Pretty print addition to a negative number as a subtraction. 1858 if (auto rhsConst = rhsExpr.dyn_cast<AffineConstantExpr>()) { 1859 if (rhsConst.getValue() < 0) { 1860 printAffineExprInternal(lhsExpr, BindingStrength::Weak, printValueName); 1861 os << " - " << -rhsConst.getValue(); 1862 if (enclosingTightness == BindingStrength::Strong) 1863 os << ')'; 1864 return; 1865 } 1866 } 1867 1868 printAffineExprInternal(lhsExpr, BindingStrength::Weak, printValueName); 1869 1870 os << " + "; 1871 printAffineExprInternal(rhsExpr, BindingStrength::Weak, printValueName); 1872 1873 if (enclosingTightness == BindingStrength::Strong) 1874 os << ')'; 1875 } 1876 1877 void ModulePrinter::printAffineConstraint(AffineExpr expr, bool isEq) { 1878 printAffineExprInternal(expr, BindingStrength::Weak); 1879 isEq ? os << " == 0" : os << " >= 0"; 1880 } 1881 1882 void ModulePrinter::printAffineMap(AffineMap map) { 1883 // Dimension identifiers. 1884 os << '('; 1885 for (int i = 0; i < (int)map.getNumDims() - 1; ++i) 1886 os << 'd' << i << ", "; 1887 if (map.getNumDims() >= 1) 1888 os << 'd' << map.getNumDims() - 1; 1889 os << ')'; 1890 1891 // Symbolic identifiers. 1892 if (map.getNumSymbols() != 0) { 1893 os << '['; 1894 for (unsigned i = 0; i < map.getNumSymbols() - 1; ++i) 1895 os << 's' << i << ", "; 1896 if (map.getNumSymbols() >= 1) 1897 os << 's' << map.getNumSymbols() - 1; 1898 os << ']'; 1899 } 1900 1901 // Result affine expressions. 1902 os << " -> ("; 1903 interleaveComma(map.getResults(), 1904 [&](AffineExpr expr) { printAffineExpr(expr); }); 1905 os << ')'; 1906 } 1907 1908 void ModulePrinter::printIntegerSet(IntegerSet set) { 1909 // Dimension identifiers. 1910 os << '('; 1911 for (unsigned i = 1; i < set.getNumDims(); ++i) 1912 os << 'd' << i - 1 << ", "; 1913 if (set.getNumDims() >= 1) 1914 os << 'd' << set.getNumDims() - 1; 1915 os << ')'; 1916 1917 // Symbolic identifiers. 1918 if (set.getNumSymbols() != 0) { 1919 os << '['; 1920 for (unsigned i = 0; i < set.getNumSymbols() - 1; ++i) 1921 os << 's' << i << ", "; 1922 if (set.getNumSymbols() >= 1) 1923 os << 's' << set.getNumSymbols() - 1; 1924 os << ']'; 1925 } 1926 1927 // Print constraints. 1928 os << " : ("; 1929 int numConstraints = set.getNumConstraints(); 1930 for (int i = 1; i < numConstraints; ++i) { 1931 printAffineConstraint(set.getConstraint(i - 1), set.isEq(i - 1)); 1932 os << ", "; 1933 } 1934 if (numConstraints >= 1) 1935 printAffineConstraint(set.getConstraint(numConstraints - 1), 1936 set.isEq(numConstraints - 1)); 1937 os << ')'; 1938 } 1939 1940 //===----------------------------------------------------------------------===// 1941 // OperationPrinter 1942 //===----------------------------------------------------------------------===// 1943 1944 namespace { 1945 /// This class contains the logic for printing operations, regions, and blocks. 1946 class OperationPrinter : public ModulePrinter, private OpAsmPrinter { 1947 public: 1948 explicit OperationPrinter(raw_ostream &os, OpPrintingFlags flags, 1949 AsmStateImpl &state) 1950 : ModulePrinter(os, flags, &state) {} 1951 1952 /// Print the given top-level module. 1953 void print(ModuleOp op); 1954 /// Print the given operation with its indent and location. 1955 void print(Operation *op); 1956 /// Print the bare location, not including indentation/location/etc. 1957 void printOperation(Operation *op); 1958 /// Print the given operation in the generic form. 1959 void printGenericOp(Operation *op) override; 1960 1961 /// Print the name of the given block. 1962 void printBlockName(Block *block); 1963 1964 /// Print the given block. If 'printBlockArgs' is false, the arguments of the 1965 /// block are not printed. If 'printBlockTerminator' is false, the terminator 1966 /// operation of the block is not printed. 1967 void print(Block *block, bool printBlockArgs = true, 1968 bool printBlockTerminator = true); 1969 1970 /// Print the ID of the given value, optionally with its result number. 1971 void printValueID(Value value, bool printResultNo = true, 1972 raw_ostream *streamOverride = nullptr) const; 1973 1974 //===--------------------------------------------------------------------===// 1975 // OpAsmPrinter methods 1976 //===--------------------------------------------------------------------===// 1977 1978 /// Return the current stream of the printer. 1979 raw_ostream &getStream() const override { return os; } 1980 1981 /// Print the given type. 1982 void printType(Type type) override { ModulePrinter::printType(type); } 1983 1984 /// Print the given attribute. 1985 void printAttribute(Attribute attr) override { 1986 ModulePrinter::printAttribute(attr); 1987 } 1988 1989 /// Print the given attribute without its type. The corresponding parser must 1990 /// provide a valid type for the attribute. 1991 void printAttributeWithoutType(Attribute attr) override { 1992 ModulePrinter::printAttribute(attr, AttrTypeElision::Must); 1993 } 1994 1995 /// Print the ID for the given value. 1996 void printOperand(Value value) override { printValueID(value); } 1997 void printOperand(Value value, raw_ostream &os) override { 1998 printValueID(value, /*printResultNo=*/true, &os); 1999 } 2000 2001 /// Print an optional attribute dictionary with a given set of elided values. 2002 void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs, 2003 ArrayRef<StringRef> elidedAttrs = {}) override { 2004 ModulePrinter::printOptionalAttrDict(attrs, elidedAttrs); 2005 } 2006 void printOptionalAttrDictWithKeyword( 2007 ArrayRef<NamedAttribute> attrs, 2008 ArrayRef<StringRef> elidedAttrs = {}) override { 2009 ModulePrinter::printOptionalAttrDict(attrs, elidedAttrs, 2010 /*withKeyword=*/true); 2011 } 2012 2013 /// Print the given successor. 2014 void printSuccessor(Block *successor) override; 2015 2016 /// Print an operation successor with the operands used for the block 2017 /// arguments. 2018 void printSuccessorAndUseList(Block *successor, 2019 ValueRange succOperands) override; 2020 2021 /// Print the given region. 2022 void printRegion(Region ®ion, bool printEntryBlockArgs, 2023 bool printBlockTerminators) override; 2024 2025 /// Renumber the arguments for the specified region to the same names as the 2026 /// SSA values in namesToUse. This may only be used for IsolatedFromAbove 2027 /// operations. If any entry in namesToUse is null, the corresponding 2028 /// argument name is left alone. 2029 void shadowRegionArgs(Region ®ion, ValueRange namesToUse) override { 2030 state->getSSANameState().shadowRegionArgs(region, namesToUse); 2031 } 2032 2033 /// Print the given affine map with the symbol and dimension operands printed 2034 /// inline with the map. 2035 void printAffineMapOfSSAIds(AffineMapAttr mapAttr, 2036 ValueRange operands) override; 2037 2038 /// Print the given string as a symbol reference. 2039 void printSymbolName(StringRef symbolRef) override { 2040 ::printSymbolReference(symbolRef, os); 2041 } 2042 2043 private: 2044 /// The number of spaces used for indenting nested operations. 2045 const static unsigned indentWidth = 2; 2046 2047 // This is the current indentation level for nested structures. 2048 unsigned currentIndent = 0; 2049 }; 2050 } // end anonymous namespace 2051 2052 void OperationPrinter::print(ModuleOp op) { 2053 // Output the aliases at the top level. 2054 state->getAliasState().printAttributeAliases(os, newLine); 2055 state->getAliasState().printTypeAliases(os, newLine); 2056 2057 // Print the module. 2058 print(op.getOperation()); 2059 } 2060 2061 void OperationPrinter::print(Operation *op) { 2062 // Track the location of this operation. 2063 state->registerOperationLocation(op, newLine.curLine, currentIndent); 2064 2065 os.indent(currentIndent); 2066 printOperation(op); 2067 printTrailingLocation(op->getLoc()); 2068 } 2069 2070 void OperationPrinter::printOperation(Operation *op) { 2071 if (size_t numResults = op->getNumResults()) { 2072 auto printResultGroup = [&](size_t resultNo, size_t resultCount) { 2073 printValueID(op->getResult(resultNo), /*printResultNo=*/false); 2074 if (resultCount > 1) 2075 os << ':' << resultCount; 2076 }; 2077 2078 // Check to see if this operation has multiple result groups. 2079 ArrayRef<int> resultGroups = state->getSSANameState().getOpResultGroups(op); 2080 if (!resultGroups.empty()) { 2081 // Interleave the groups excluding the last one, this one will be handled 2082 // separately. 2083 interleaveComma(llvm::seq<int>(0, resultGroups.size() - 1), [&](int i) { 2084 printResultGroup(resultGroups[i], 2085 resultGroups[i + 1] - resultGroups[i]); 2086 }); 2087 os << ", "; 2088 printResultGroup(resultGroups.back(), numResults - resultGroups.back()); 2089 2090 } else { 2091 printResultGroup(/*resultNo=*/0, /*resultCount=*/numResults); 2092 } 2093 2094 os << " = "; 2095 } 2096 2097 // If requested, always print the generic form. 2098 if (!printerFlags.shouldPrintGenericOpForm()) { 2099 // Check to see if this is a known operation. If so, use the registered 2100 // custom printer hook. 2101 if (auto *opInfo = op->getAbstractOperation()) { 2102 opInfo->printAssembly(op, *this); 2103 return; 2104 } 2105 } 2106 2107 // Otherwise print with the generic assembly form. 2108 printGenericOp(op); 2109 } 2110 2111 void OperationPrinter::printGenericOp(Operation *op) { 2112 os << '"'; 2113 printEscapedString(op->getName().getStringRef(), os); 2114 os << "\"("; 2115 interleaveComma(op->getOperands(), [&](Value value) { printValueID(value); }); 2116 os << ')'; 2117 2118 // For terminators, print the list of successors and their operands. 2119 if (op->getNumSuccessors() != 0) { 2120 os << '['; 2121 interleaveComma(op->getSuccessors(), 2122 [&](Block *successor) { printBlockName(successor); }); 2123 os << ']'; 2124 } 2125 2126 // Print regions. 2127 if (op->getNumRegions() != 0) { 2128 os << " ("; 2129 interleaveComma(op->getRegions(), [&](Region ®ion) { 2130 printRegion(region, /*printEntryBlockArgs=*/true, 2131 /*printBlockTerminators=*/true); 2132 }); 2133 os << ')'; 2134 } 2135 2136 auto attrs = op->getAttrs(); 2137 printOptionalAttrDict(attrs); 2138 2139 // Print the type signature of the operation. 2140 os << " : "; 2141 printFunctionalType(op); 2142 } 2143 2144 void OperationPrinter::printBlockName(Block *block) { 2145 auto id = state->getSSANameState().getBlockID(block); 2146 if (id != SSANameState::NameSentinel) 2147 os << "^bb" << id; 2148 else 2149 os << "^INVALIDBLOCK"; 2150 } 2151 2152 void OperationPrinter::print(Block *block, bool printBlockArgs, 2153 bool printBlockTerminator) { 2154 // Print the block label and argument list if requested. 2155 if (printBlockArgs) { 2156 os.indent(currentIndent); 2157 printBlockName(block); 2158 2159 // Print the argument list if non-empty. 2160 if (!block->args_empty()) { 2161 os << '('; 2162 interleaveComma(block->getArguments(), [&](BlockArgument arg) { 2163 printValueID(arg); 2164 os << ": "; 2165 printType(arg.getType()); 2166 }); 2167 os << ')'; 2168 } 2169 os << ':'; 2170 2171 // Print out some context information about the predecessors of this block. 2172 if (!block->getParent()) { 2173 os << "\t// block is not in a region!"; 2174 } else if (block->hasNoPredecessors()) { 2175 os << "\t// no predecessors"; 2176 } else if (auto *pred = block->getSinglePredecessor()) { 2177 os << "\t// pred: "; 2178 printBlockName(pred); 2179 } else { 2180 // We want to print the predecessors in increasing numeric order, not in 2181 // whatever order the use-list is in, so gather and sort them. 2182 SmallVector<std::pair<unsigned, Block *>, 4> predIDs; 2183 for (auto *pred : block->getPredecessors()) 2184 predIDs.push_back({state->getSSANameState().getBlockID(pred), pred}); 2185 llvm::array_pod_sort(predIDs.begin(), predIDs.end()); 2186 2187 os << "\t// " << predIDs.size() << " preds: "; 2188 2189 interleaveComma(predIDs, [&](std::pair<unsigned, Block *> pred) { 2190 printBlockName(pred.second); 2191 }); 2192 } 2193 os << newLine; 2194 } 2195 2196 currentIndent += indentWidth; 2197 auto range = llvm::make_range( 2198 block->getOperations().begin(), 2199 std::prev(block->getOperations().end(), printBlockTerminator ? 0 : 1)); 2200 for (auto &op : range) { 2201 print(&op); 2202 os << newLine; 2203 } 2204 currentIndent -= indentWidth; 2205 } 2206 2207 void OperationPrinter::printValueID(Value value, bool printResultNo, 2208 raw_ostream *streamOverride) const { 2209 state->getSSANameState().printValueID(value, printResultNo, 2210 streamOverride ? *streamOverride : os); 2211 } 2212 2213 void OperationPrinter::printSuccessor(Block *successor) { 2214 printBlockName(successor); 2215 } 2216 2217 void OperationPrinter::printSuccessorAndUseList(Block *successor, 2218 ValueRange succOperands) { 2219 printBlockName(successor); 2220 if (succOperands.empty()) 2221 return; 2222 2223 os << '('; 2224 interleaveComma(succOperands, 2225 [this](Value operand) { printValueID(operand); }); 2226 os << " : "; 2227 interleaveComma(succOperands, 2228 [this](Value operand) { printType(operand.getType()); }); 2229 os << ')'; 2230 } 2231 2232 void OperationPrinter::printRegion(Region ®ion, bool printEntryBlockArgs, 2233 bool printBlockTerminators) { 2234 os << " {" << newLine; 2235 if (!region.empty()) { 2236 auto *entryBlock = ®ion.front(); 2237 print(entryBlock, printEntryBlockArgs && entryBlock->getNumArguments() != 0, 2238 printBlockTerminators); 2239 for (auto &b : llvm::drop_begin(region.getBlocks(), 1)) 2240 print(&b); 2241 } 2242 os.indent(currentIndent) << "}"; 2243 } 2244 2245 void OperationPrinter::printAffineMapOfSSAIds(AffineMapAttr mapAttr, 2246 ValueRange operands) { 2247 AffineMap map = mapAttr.getValue(); 2248 unsigned numDims = map.getNumDims(); 2249 auto printValueName = [&](unsigned pos, bool isSymbol) { 2250 unsigned index = isSymbol ? numDims + pos : pos; 2251 assert(index < operands.size()); 2252 if (isSymbol) 2253 os << "symbol("; 2254 printValueID(operands[index]); 2255 if (isSymbol) 2256 os << ')'; 2257 }; 2258 2259 interleaveComma(map.getResults(), [&](AffineExpr expr) { 2260 printAffineExpr(expr, printValueName); 2261 }); 2262 } 2263 2264 //===----------------------------------------------------------------------===// 2265 // print and dump methods 2266 //===----------------------------------------------------------------------===// 2267 2268 void Attribute::print(raw_ostream &os) const { 2269 ModulePrinter(os).printAttribute(*this); 2270 } 2271 2272 void Attribute::dump() const { 2273 print(llvm::errs()); 2274 llvm::errs() << "\n"; 2275 } 2276 2277 void Type::print(raw_ostream &os) { ModulePrinter(os).printType(*this); } 2278 2279 void Type::dump() { print(llvm::errs()); } 2280 2281 void AffineMap::dump() const { 2282 print(llvm::errs()); 2283 llvm::errs() << "\n"; 2284 } 2285 2286 void IntegerSet::dump() const { 2287 print(llvm::errs()); 2288 llvm::errs() << "\n"; 2289 } 2290 2291 void AffineExpr::print(raw_ostream &os) const { 2292 if (!expr) { 2293 os << "<<NULL AFFINE EXPR>>"; 2294 return; 2295 } 2296 ModulePrinter(os).printAffineExpr(*this); 2297 } 2298 2299 void AffineExpr::dump() const { 2300 print(llvm::errs()); 2301 llvm::errs() << "\n"; 2302 } 2303 2304 void AffineMap::print(raw_ostream &os) const { 2305 if (!map) { 2306 os << "<<NULL AFFINE MAP>>"; 2307 return; 2308 } 2309 ModulePrinter(os).printAffineMap(*this); 2310 } 2311 2312 void IntegerSet::print(raw_ostream &os) const { 2313 ModulePrinter(os).printIntegerSet(*this); 2314 } 2315 2316 void Value::print(raw_ostream &os) { 2317 if (auto *op = getDefiningOp()) 2318 return op->print(os); 2319 // TODO: Improve this. 2320 assert(isa<BlockArgument>()); 2321 os << "<block argument>\n"; 2322 } 2323 void Value::print(raw_ostream &os, AsmState &state) { 2324 if (auto *op = getDefiningOp()) 2325 return op->print(os, state); 2326 2327 // TODO: Improve this. 2328 assert(isa<BlockArgument>()); 2329 os << "<block argument>\n"; 2330 } 2331 2332 void Value::dump() { 2333 print(llvm::errs()); 2334 llvm::errs() << "\n"; 2335 } 2336 2337 void Value::printAsOperand(raw_ostream &os, AsmState &state) { 2338 // TODO(riverriddle) This doesn't necessarily capture all potential cases. 2339 // Currently, region arguments can be shadowed when printing the main 2340 // operation. If the IR hasn't been printed, this will produce the old SSA 2341 // name and not the shadowed name. 2342 state.getImpl().getSSANameState().printValueID(*this, /*printResultNo=*/true, 2343 os); 2344 } 2345 2346 void Operation::print(raw_ostream &os, OpPrintingFlags flags) { 2347 // Handle top-level operations or local printing. 2348 if (!getParent() || flags.shouldUseLocalScope()) { 2349 AsmState state(this); 2350 OperationPrinter(os, flags, state.getImpl()).print(this); 2351 return; 2352 } 2353 2354 Operation *parentOp = getParentOp(); 2355 if (!parentOp) { 2356 os << "<<UNLINKED OPERATION>>\n"; 2357 return; 2358 } 2359 // Get the top-level op. 2360 while (auto *nextOp = parentOp->getParentOp()) 2361 parentOp = nextOp; 2362 2363 AsmState state(parentOp); 2364 print(os, state, flags); 2365 } 2366 void Operation::print(raw_ostream &os, AsmState &state, OpPrintingFlags flags) { 2367 OperationPrinter(os, flags, state.getImpl()).print(this); 2368 } 2369 2370 void Operation::dump() { 2371 print(llvm::errs(), OpPrintingFlags().useLocalScope()); 2372 llvm::errs() << "\n"; 2373 } 2374 2375 void Block::print(raw_ostream &os) { 2376 Operation *parentOp = getParentOp(); 2377 if (!parentOp) { 2378 os << "<<UNLINKED BLOCK>>\n"; 2379 return; 2380 } 2381 // Get the top-level op. 2382 while (auto *nextOp = parentOp->getParentOp()) 2383 parentOp = nextOp; 2384 2385 AsmState state(parentOp); 2386 print(os, state); 2387 } 2388 void Block::print(raw_ostream &os, AsmState &state) { 2389 OperationPrinter(os, /*flags=*/llvm::None, state.getImpl()).print(this); 2390 } 2391 2392 void Block::dump() { print(llvm::errs()); } 2393 2394 /// Print out the name of the block without printing its body. 2395 void Block::printAsOperand(raw_ostream &os, bool printType) { 2396 Operation *parentOp = getParentOp(); 2397 if (!parentOp) { 2398 os << "<<UNLINKED BLOCK>>\n"; 2399 return; 2400 } 2401 AsmState state(parentOp); 2402 printAsOperand(os, state); 2403 } 2404 void Block::printAsOperand(raw_ostream &os, AsmState &state) { 2405 OperationPrinter printer(os, /*flags=*/llvm::None, state.getImpl()); 2406 printer.printBlockName(this); 2407 } 2408 2409 void ModuleOp::print(raw_ostream &os, OpPrintingFlags flags) { 2410 AsmState state(*this); 2411 2412 // Don't populate aliases when printing at local scope. 2413 if (!flags.shouldUseLocalScope()) 2414 state.getImpl().initializeAliases(*this); 2415 print(os, state, flags); 2416 } 2417 void ModuleOp::print(raw_ostream &os, AsmState &state, OpPrintingFlags flags) { 2418 OperationPrinter(os, flags, state.getImpl()).print(*this); 2419 } 2420 2421 void ModuleOp::dump() { print(llvm::errs()); } 2422