31#include "llvm/ADT/APFloat.h"
32#include "llvm/ADT/ArrayRef.h"
33#include "llvm/ADT/DenseMap.h"
34#include "llvm/ADT/MapVector.h"
35#include "llvm/ADT/STLExtras.h"
36#include "llvm/ADT/ScopeExit.h"
37#include "llvm/ADT/ScopedHashTable.h"
38#include "llvm/ADT/SetVector.h"
39#include "llvm/ADT/StringExtras.h"
40#include "llvm/ADT/StringSet.h"
41#include "llvm/ADT/TypeSwitch.h"
42#include "llvm/Support/CommandLine.h"
43#include "llvm/Support/DebugLog.h"
44#include "llvm/Support/Endian.h"
45#include "llvm/Support/ManagedStatic.h"
46#include "llvm/Support/Regex.h"
47#include "llvm/Support/SaveAndRestore.h"
48#include "llvm/Support/Threading.h"
49#include "llvm/Support/raw_ostream.h"
58#define DEBUG_TYPE "mlir-asm-printer"
99 *this << (operand ? operand.getType() : Type());
115 *this << (result ? result.getType() : Type());
127#include "mlir/IR/OpAsmAttrInterface.cpp.inc"
128#include "mlir/IR/OpAsmOpInterface.cpp.inc"
129#include "mlir/IR/OpAsmTypeInterface.cpp.inc"
133 return entry.
emitError() <<
"unknown 'resource' key '" << entry.
getKey()
134 <<
"' for dialect '" << getDialect()->getNamespace()
146struct AsmPrinterOptions {
147 llvm::cl::opt<int64_t> printElementsAttrWithHexIfLarger{
148 "mlir-print-elementsattrs-with-hex-if-larger",
150 "Print DenseElementsAttrs with a hex string that have "
151 "more elements than the given upper limit (use -1 to disable)")};
153 llvm::cl::opt<unsigned> elideElementsAttrIfLarger{
154 "mlir-elide-elementsattrs-if-larger",
155 llvm::cl::desc(
"Elide ElementsAttrs with \"...\" that have "
156 "more elements than the given upper limit")};
158 llvm::cl::opt<unsigned> elideResourceStringsIfLarger{
159 "mlir-elide-resource-strings-if-larger",
161 "Elide printing value of resources if string is too long in chars.")};
163 llvm::cl::opt<bool> printDebugInfoOpt{
164 "mlir-print-debuginfo", llvm::cl::init(
false),
165 llvm::cl::desc(
"Print debug info in MLIR output")};
167 llvm::cl::opt<bool> printPrettyDebugInfoOpt{
168 "mlir-pretty-debuginfo", llvm::cl::init(
false),
169 llvm::cl::desc(
"Print pretty debug info in MLIR output")};
173 llvm::cl::opt<bool> printGenericOpFormOpt{
174 "mlir-print-op-generic", llvm::cl::init(
false),
175 llvm::cl::desc(
"Print the generic op form"), llvm::cl::Hidden};
177 llvm::cl::opt<bool> assumeVerifiedOpt{
178 "mlir-print-assume-verified", llvm::cl::init(
false),
179 llvm::cl::desc(
"Skip op verification when using custom printers"),
182 llvm::cl::opt<bool> printLocalScopeOpt{
183 "mlir-print-local-scope", llvm::cl::init(
false),
184 llvm::cl::desc(
"Print with local scope and inline information (eliding "
185 "aliases for attributes, types, and locations)")};
187 llvm::cl::opt<bool> skipRegionsOpt{
188 "mlir-print-skip-regions", llvm::cl::init(
false),
189 llvm::cl::desc(
"Skip regions when printing ops.")};
191 llvm::cl::opt<bool> printValueUsers{
192 "mlir-print-value-users", llvm::cl::init(
false),
194 "Print users of operation results and block arguments as a comment")};
196 llvm::cl::opt<bool> printUniqueSSAIDs{
197 "mlir-print-unique-ssa-ids", llvm::cl::init(
false),
198 llvm::cl::desc(
"Print unique SSA ID numbers for values, block arguments "
199 "and naming conflicts across all regions")};
201 llvm::cl::opt<bool> useNameLocAsPrefix{
202 "mlir-use-nameloc-as-prefix", llvm::cl::init(
false),
203 llvm::cl::desc(
"Print SSA IDs using NameLocs as prefixes")};
218 : printDebugInfoFlag(
false), printDebugInfoPrettyFormFlag(
false),
219 printGenericOpFormFlag(
false), skipRegionsFlag(
false),
220 assumeVerifiedFlag(
false), printLocalScope(
false),
221 printValueUsersFlag(
false), printUniqueSSAIDsFlag(
false),
222 useNameLocAsPrefix(
false) {
226 if (
clOptions->elideElementsAttrIfLarger.getNumOccurrences())
227 elementsAttrElementLimit =
clOptions->elideElementsAttrIfLarger;
228 if (
clOptions->printElementsAttrWithHexIfLarger.getNumOccurrences())
229 elementsAttrHexElementLimit =
230 clOptions->printElementsAttrWithHexIfLarger.getValue();
231 if (
clOptions->elideResourceStringsIfLarger.getNumOccurrences())
232 resourceStringCharLimit =
clOptions->elideResourceStringsIfLarger;
233 printDebugInfoFlag =
clOptions->printDebugInfoOpt;
234 printDebugInfoPrettyFormFlag =
clOptions->printPrettyDebugInfoOpt;
235 printGenericOpFormFlag =
clOptions->printGenericOpFormOpt;
236 assumeVerifiedFlag =
clOptions->assumeVerifiedOpt;
237 printLocalScope =
clOptions->printLocalScopeOpt;
238 skipRegionsFlag =
clOptions->skipRegionsOpt;
239 printValueUsersFlag =
clOptions->printValueUsers;
240 printUniqueSSAIDsFlag =
clOptions->printUniqueSSAIDs;
241 useNameLocAsPrefix =
clOptions->useNameLocAsPrefix;
250 elementsAttrElementLimit = largeElementLimit;
256 elementsAttrHexElementLimit = largeElementLimit;
262 resourceStringCharLimit = largeResourceLimit;
270 printDebugInfoFlag = enable;
271 printDebugInfoPrettyFormFlag = prettyForm;
277 printGenericOpFormFlag = enable;
283 skipRegionsFlag = skip;
289 assumeVerifiedFlag = enable;
297 printLocalScope = enable;
303 printValueUsersFlag = enable;
310 printUniqueSSAIDsFlag = enable;
316 return elementsAttrElementLimit &&
317 *elementsAttrElementLimit <
int64_t(attr.getNumElements()) &&
318 !llvm::isa<SplatElementsAttr>(attr);
324 return (elementsAttrHexElementLimit != -1) &&
325 (elementsAttrHexElementLimit <
int64_t(attr.getNumElements())) &&
326 !llvm::isa<SplatElementsAttr>(attr);
330 useNameLocAsPrefix = enable;
336 return elementsAttrElementLimit;
341 return elementsAttrHexElementLimit;
346 return resourceStringCharLimit;
351 return printDebugInfoFlag;
356 return printDebugInfoPrettyFormFlag;
361 return printGenericOpFormFlag;
369 return assumeVerifiedFlag;
377 return printValueUsersFlag;
387 return useNameLocAsPrefix;
398struct NewLineCounter {
399 unsigned curLine = 1;
436 template <
typename Container,
typename UnaryFunctor>
438 llvm::interleaveComma(c,
os, eachFn);
485 function_ref<
void(
unsigned,
bool)> printValueName =
nullptr);
498 bool withKeyword =
false);
501 bool isTopLevel =
false);
519 DenseElementType denseEltType);
543 function_ref<
void(
unsigned,
bool)> printValueName =
nullptr);
573 SymbolAlias(StringRef name, uint32_t suffixIndex,
bool isType,
575 : name(name), suffixIndex(suffixIndex), isType(isType),
576 isDeferrable(isDeferrable) {}
580 os << (isType ?
"!" :
"#") << name;
582 if (isdigit(name.back()))
589 bool isTypeAlias()
const {
return isType; }
592 bool canBeDeferred()
const {
return isDeferrable; }
598 uint32_t suffixIndex : 30;
602 bool isDeferrable : 1;
606 bool isPrinted =
false;
612class AliasInitializer {
615 DialectInterfaceCollection<OpAsmDialectInterface> &interfaces,
616 llvm::BumpPtrAllocator &aliasAllocator)
617 : interfaces(interfaces), aliasAllocator(aliasAllocator),
618 aliasOS(aliasBuffer) {}
620 void initialize(Operation *op,
const OpPrintingFlags &printerFlags,
621 llvm::MapVector<const void *, SymbolAlias> &attrTypeToAlias);
629 std::pair<size_t, size_t>
visit(Attribute attr,
bool canBeDeferred =
false,
630 bool elideType =
false) {
631 return visitImpl(attr, aliases, canBeDeferred, elideType);
638 std::pair<size_t, size_t>
visit(Type type,
bool canBeDeferred =
false) {
639 return visitImpl(type, aliases, canBeDeferred);
643 struct InProgressAliasInfo {
644 InProgressAliasInfo()
645 : aliasDepth(0), isType(
false), canBeDeferred(
false) {}
646 InProgressAliasInfo(StringRef alias)
647 : alias(alias), aliasDepth(1), isType(
false), canBeDeferred(
false) {}
651 if (aliasDepth !=
rhs.aliasDepth)
652 return aliasDepth <
rhs.aliasDepth;
653 if (isType !=
rhs.isType)
655 return alias <
rhs.alias;
660 std::optional<StringRef> alias;
663 unsigned aliasDepth : 30;
667 bool canBeDeferred : 1;
669 SmallVector<size_t> childIndices;
677 template <
typename T,
typename... PrintArgs>
678 std::pair<size_t, size_t>
680 llvm::MapVector<const void *, InProgressAliasInfo> &aliases,
681 bool canBeDeferred, PrintArgs &&...
printArgs);
684 void markAliasNonDeferrable(
size_t aliasIndex);
688 template <
typename T>
689 void generateAlias(T symbol, InProgressAliasInfo &alias,
bool canBeDeferred);
694 uniqueAliasNameIndex(StringRef alias, llvm::StringMap<unsigned> &nameCounts,
695 llvm::StringSet<llvm::BumpPtrAllocator &> &usedAliases);
699 static void initializeAliases(
700 llvm::MapVector<const void *, InProgressAliasInfo> &visitedSymbols,
701 llvm::MapVector<const void *, SymbolAlias> &symbolToAlias);
704 DialectInterfaceCollection<OpAsmDialectInterface> &interfaces;
707 llvm::BumpPtrAllocator &aliasAllocator;
710 llvm::MapVector<const void *, InProgressAliasInfo> aliases;
713 SmallString<32> aliasBuffer;
714 llvm::raw_svector_ostream aliasOS;
722class DummyAliasOperationPrinter :
private OpAsmPrinter {
724 explicit DummyAliasOperationPrinter(
const OpPrintingFlags &printerFlags,
725 AliasInitializer &initializer)
726 : printerFlags(printerFlags), initializer(initializer) {}
730 void printCustomOrGenericOp(Operation *op)
override {
732 if (printerFlags.shouldPrintDebugInfo())
733 initializer.visit(op->
getLoc(),
true);
736 if (!printerFlags.shouldPrintGenericOpForm()) {
747 void printGenericOp(Operation *op,
bool printOpName =
true)
override {
749 if (!printerFlags.shouldSkipRegions()) {
759 if (operand && operand.getType())
766 printAttribute(attr.getValue());
768 op, [&](StringRef, Attribute &attr) { printAttribute(attr); });
774 void print(
Block *block,
bool printBlockArgs =
true,
775 bool printBlockTerminator =
true) {
778 if (printBlockArgs) {
783 if (printerFlags.shouldPrintDebugInfo())
785 initializer.visit(arg.getLoc(),
false);
793 auto range = llvm::make_range(
795 std::prev(block->
end(),
796 (!hasTerminator || printBlockTerminator) ? 0 : 1));
797 for (Operation &op : range)
798 printCustomOrGenericOp(&op);
802 void printRegion(Region ®ion,
bool printEntryBlockArgs,
803 bool printBlockTerminators,
804 bool printEmptyBlock =
false)
override {
807 if (printerFlags.shouldSkipRegions()) {
812 auto *entryBlock = ®ion.
front();
813 print(entryBlock, printEntryBlockArgs, printBlockTerminators);
814 for (
Block &
b : llvm::drop_begin(region, 1))
818 void printRegionArgument(BlockArgument arg, ArrayRef<NamedAttribute> argAttrs,
819 bool omitType)
override {
822 if (printerFlags.shouldPrintDebugInfo())
824 initializer.visit(arg.
getLoc(),
false);
830 initializer.visit(type);
834 void printAttribute(Attribute attr)
override { initializer.visit(attr); }
835 void printAttributeWithoutType(Attribute attr)
override {
836 printAttribute(attr);
838 void printNamedAttribute(NamedAttribute attr)
override {
842 LogicalResult printAlias(Attribute attr)
override {
843 initializer.visit(attr);
846 LogicalResult printAlias(Type type)
override {
847 initializer.visit(type);
852 void printOptionalLocationSpecifier(Location loc)
override {
858 void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
859 ArrayRef<StringRef> elidedAttrs = {})
override {
862 if (elidedAttrs.empty()) {
863 for (
const NamedAttribute &attr : attrs)
864 printAttribute(attr.getValue());
867 llvm::SmallDenseSet<StringRef> elidedAttrsSet(elidedAttrs.begin(),
869 for (
const NamedAttribute &attr : attrs)
870 if (!elidedAttrsSet.contains(attr.getName().strref()))
871 printAttribute(attr.getValue());
873 void printOptionalAttrDictWithKeyword(
874 ArrayRef<NamedAttribute> attrs,
875 ArrayRef<StringRef> elidedAttrs = {})
override {
876 printOptionalAttrDict(attrs, elidedAttrs);
881 raw_ostream &getStream()
const override {
return os; }
885 void printFloat(
const APFloat &)
override {}
886 void printAffineMapOfSSAIds(AffineMapAttr,
ValueRange)
override {}
889 void increaseIndent()
override {}
890 void decreaseIndent()
override {}
891 void printOperand(Value)
override {}
892 void printOperand(Value, raw_ostream &os)
override {
900 void printResourceHandle(
const AsmDialectResourceHandle &)
override {}
901 void printSymbolName(StringRef)
override {}
902 void printSuccessor(
Block *)
override {}
904 void shadowRegionArgs(Region &,
ValueRange)
override {}
907 const OpPrintingFlags &printerFlags;
910 AliasInitializer &initializer;
913 mutable llvm::raw_null_ostream os;
918 explicit DummyAliasDialectAsmPrinter(AliasInitializer &initializer,
920 SmallVectorImpl<size_t> &childIndices)
921 : initializer(initializer), canBeDeferred(canBeDeferred),
922 childIndices(childIndices) {}
927 template <
typename T,
typename... PrintArgs>
928 size_t printAndVisitNestedAliases(T value, PrintArgs &&...
printArgs) {
929 printAndVisitNestedAliasesImpl(value,
printArgs...);
930 return maxAliasDepth;
936 void printAndVisitNestedAliasesImpl(Attribute attr,
bool elideType) {
937 if (!isa<BuiltinDialect>(attr.
getDialect())) {
941 }
else if (llvm::isa<AffineMapAttr, DenseArrayAttr, FloatAttr, IntegerAttr,
942 IntegerSetAttr, UnitAttr>(attr)) {
944 }
else if (
auto distinctAttr = dyn_cast<DistinctAttr>(attr)) {
945 printAttribute(distinctAttr.getReferencedAttr());
946 }
else if (
auto dictAttr = dyn_cast<DictionaryAttr>(attr)) {
947 for (
const NamedAttribute &nestedAttr : dictAttr.getValue()) {
948 printAttribute(nestedAttr.getName());
949 printAttribute(nestedAttr.getValue());
951 }
else if (
auto arrayAttr = dyn_cast<ArrayAttr>(attr)) {
952 for (Attribute nestedAttr : arrayAttr.getValue())
953 printAttribute(nestedAttr);
954 }
else if (
auto typeAttr = dyn_cast<TypeAttr>(attr)) {
956 }
else if (
auto locAttr = dyn_cast<OpaqueLoc>(attr)) {
957 printAttribute(locAttr.getFallbackLocation());
958 }
else if (
auto locAttr = dyn_cast<NameLoc>(attr)) {
959 if (!isa<UnknownLoc>(locAttr.getChildLoc()))
960 printAttribute(locAttr.getChildLoc());
961 }
else if (
auto locAttr = dyn_cast<CallSiteLoc>(attr)) {
962 printAttribute(locAttr.getCallee());
963 printAttribute(locAttr.getCaller());
964 }
else if (
auto locAttr = dyn_cast<FusedLoc>(attr)) {
965 if (Attribute metadata = locAttr.getMetadata())
966 printAttribute(metadata);
967 for (Location nestedLoc : locAttr.getLocations())
968 printAttribute(nestedLoc);
973 if (
auto typedAttr = llvm::dyn_cast<TypedAttr>(attr)) {
974 Type attrType = typedAttr.getType();
975 if (!llvm::isa<NoneType>(attrType))
980 void printAndVisitNestedAliasesImpl(Type type) {
987 if (
auto memrefTy = llvm::dyn_cast<MemRefType>(type)) {
989 MemRefLayoutAttrInterface layout = memrefTy.getLayout();
990 if (!llvm::isa<AffineMapAttr>(layout) || !layout.isIdentity())
991 printAttribute(memrefTy.getLayout());
992 if (memrefTy.getMemorySpace())
993 printAttribute(memrefTy.getMemorySpace());
998 auto visitFn = [&](
auto element) {
1000 (void)printAlias(element);
1007 recordAliasResult(initializer.visit(type, canBeDeferred));
1011 void printAttribute(Attribute attr)
override {
1012 recordAliasResult(initializer.visit(attr, canBeDeferred));
1014 void printAttributeWithoutType(Attribute attr)
override {
1016 initializer.visit(attr, canBeDeferred,
true));
1018 void printNamedAttribute(NamedAttribute attr)
override {
1022 LogicalResult printAlias(Attribute attr)
override {
1023 printAttribute(attr);
1026 LogicalResult printAlias(Type type)
override {
1032 void recordAliasResult(std::pair<size_t, size_t> aliasDepthAndIndex) {
1033 childIndices.push_back(aliasDepthAndIndex.second);
1034 if (aliasDepthAndIndex.first > maxAliasDepth)
1035 maxAliasDepth = aliasDepthAndIndex.first;
1040 raw_ostream &getStream()
const override {
return os; }
1045 void increaseIndent()
override {}
1046 void decreaseIndent()
override {}
1047 void printFloat(
const APFloat &)
override {}
1050 void printSymbolName(StringRef)
override {}
1051 void printResourceHandle(
const AsmDialectResourceHandle &)
override {}
1053 LogicalResult pushCyclicPrinting(
const void *opaquePointer)
override {
1054 return success(cyclicPrintingStack.insert(opaquePointer));
1057 void popCyclicPrinting()
override { cyclicPrintingStack.pop_back(); }
1061 SetVector<const void *> cyclicPrintingStack;
1064 AliasInitializer &initializer;
1070 SmallVectorImpl<size_t> &childIndices;
1073 size_t maxAliasDepth = 0;
1076 mutable llvm::raw_null_ostream os;
1084 StringRef allowedPunctChars =
"$._-") {
1085 assert(!name.empty() &&
"Shouldn't have an empty name here");
1087 auto validChar = [&](
char ch) {
1088 return llvm::isAlnum(ch) || allowedPunctChars.contains(ch);
1091 auto copyNameToBuffer = [&] {
1092 for (
char ch : name) {
1094 buffer.push_back(ch);
1096 buffer.push_back(
'_');
1098 buffer.append(llvm::utohexstr((
unsigned char)ch));
1105 if (isdigit(name[0]) || (!validChar(name[0]) && name[0] !=
' ')) {
1106 buffer.push_back(
'_');
1112 for (
char ch : name) {
1113 if (!validChar(ch)) {
1123unsigned AliasInitializer::uniqueAliasNameIndex(
1124 StringRef alias, llvm::StringMap<unsigned> &nameCounts,
1125 llvm::StringSet<llvm::BumpPtrAllocator &> &usedAliases) {
1126 if (!usedAliases.count(alias)) {
1127 usedAliases.insert(alias);
1133 size_t probeSize = probeAlias.size();
1135 if (isdigit(alias.back())) {
1136 probeAlias.push_back(
'_');
1140 if (nameCounts[probeAlias] == 0)
1141 nameCounts[probeAlias] = 1;
1145 unsigned nameIndex = nameCounts[probeAlias]++;
1146 probeAlias += llvm::utostr(nameIndex);
1147 if (!usedAliases.count(probeAlias)) {
1148 usedAliases.insert(probeAlias);
1152 probeAlias.resize(probeSize);
1158void AliasInitializer::initializeAliases(
1159 llvm::MapVector<const void *, InProgressAliasInfo> &visitedSymbols,
1160 llvm::MapVector<const void *, SymbolAlias> &symbolToAlias) {
1162 unprocessedAliases = visitedSymbols.takeVector();
1163 llvm::stable_sort(unprocessedAliases, llvm::less_second());
1167 llvm::BumpPtrAllocator usedAliasAllocator;
1168 llvm::StringSet<llvm::BumpPtrAllocator &> usedAliases(usedAliasAllocator);
1170 llvm::StringMap<unsigned> nameCounts;
1171 for (
auto &[symbol, aliasInfo] : unprocessedAliases) {
1172 if (!aliasInfo.alias)
1174 StringRef alias = *aliasInfo.alias;
1175 unsigned nameIndex = uniqueAliasNameIndex(alias, nameCounts, usedAliases);
1176 symbolToAlias.insert(
1177 {symbol, SymbolAlias(alias, nameIndex, aliasInfo.isType,
1178 aliasInfo.canBeDeferred)});
1182void AliasInitializer::initialize(
1184 llvm::MapVector<const void *, SymbolAlias> &attrTypeToAlias) {
1188 DummyAliasOperationPrinter aliasPrinter(printerFlags, *
this);
1189 aliasPrinter.printCustomOrGenericOp(op);
1192 initializeAliases(aliases, attrTypeToAlias);
1195template <
typename T,
typename... PrintArgs>
1196std::pair<size_t, size_t> AliasInitializer::visitImpl(
1197 T value, llvm::MapVector<const void *, InProgressAliasInfo> &aliases,
1198 bool canBeDeferred, PrintArgs &&...
printArgs) {
1199 auto [it,
inserted] = aliases.try_emplace(value.getAsOpaquePointer());
1200 size_t aliasIndex = std::distance(aliases.begin(), it);
1204 markAliasNonDeferrable(aliasIndex);
1205 return {
static_cast<size_t>(it->second.aliasDepth), aliasIndex};
1209 generateAlias(value, it->second, canBeDeferred);
1210 it->second.isType = std::is_base_of_v<Type, T>;
1211 it->second.canBeDeferred = canBeDeferred;
1215 DummyAliasDialectAsmPrinter printer(*
this, canBeDeferred, childAliases);
1216 size_t maxAliasDepth =
1217 printer.printAndVisitNestedAliases(value,
printArgs...);
1220 it = std::next(aliases.begin(), aliasIndex);
1223 it->second.childIndices = std::move(childAliases);
1225 it->second.aliasDepth = maxAliasDepth + 1;
1228 return {(size_t)it->second.aliasDepth, aliasIndex};
1231void AliasInitializer::markAliasNonDeferrable(
size_t aliasIndex) {
1232 auto *it = std::next(aliases.begin(), aliasIndex);
1236 if (!it->second.canBeDeferred)
1239 it->second.canBeDeferred =
false;
1242 for (
size_t childIndex : it->second.childIndices)
1243 markAliasNonDeferrable(childIndex);
1246template <
typename T>
1247void AliasInitializer::generateAlias(T symbol, InProgressAliasInfo &alias,
1248 bool canBeDeferred) {
1251 OpAsmDialectInterface::AliasResult symbolInterfaceResult =
1252 OpAsmDialectInterface::AliasResult::NoAlias;
1253 using InterfaceT = std::conditional_t<std::is_base_of_v<Attribute, T>,
1254 OpAsmAttrInterface, OpAsmTypeInterface>;
1255 if (
auto symbolInterface = dyn_cast<InterfaceT>(symbol)) {
1256 symbolInterfaceResult = symbolInterface.getAlias(aliasOS);
1257 if (symbolInterfaceResult != OpAsmDialectInterface::AliasResult::NoAlias) {
1258 nameBuffer = std::move(aliasBuffer);
1259 assert(!nameBuffer.empty() &&
"expected valid alias name");
1263 if (symbolInterfaceResult != OpAsmDialectInterface::AliasResult::FinalAlias) {
1264 for (
const auto &interface : interfaces) {
1265 OpAsmDialectInterface::AliasResult
result =
1266 interface.getAlias(symbol, aliasOS);
1267 if (
result == OpAsmDialectInterface::AliasResult::NoAlias)
1269 nameBuffer = std::move(aliasBuffer);
1270 assert(!nameBuffer.empty() &&
"expected valid alias name");
1271 if (
result == OpAsmDialectInterface::AliasResult::FinalAlias)
1276 if (nameBuffer.empty())
1282 name = name.copy(aliasAllocator);
1283 alias = InProgressAliasInfo(name);
1296 initialize(Operation *op,
const OpPrintingFlags &printerFlags,
1297 DialectInterfaceCollection<OpAsmDialectInterface> &interfaces);
1301 LogicalResult getAlias(Attribute attr, raw_ostream &os)
const;
1305 LogicalResult getAlias(Type ty, raw_ostream &os)
const;
1309 void printNonDeferredAliases(AsmPrinter::Impl &p, NewLineCounter &newLine) {
1310 printAliases(p, newLine,
false);
1314 void printDeferredAliases(AsmPrinter::Impl &p, NewLineCounter &newLine) {
1315 printAliases(p, newLine,
true);
1321 void printAliases(AsmPrinter::Impl &p, NewLineCounter &newLine,
1325 llvm::MapVector<const void *, SymbolAlias> attrTypeToAlias;
1328 llvm::BumpPtrAllocator aliasAllocator;
1332void AliasState::initialize(
1335 AliasInitializer initializer(interfaces, aliasAllocator);
1336 initializer.initialize(op, printerFlags, attrTypeToAlias);
1341 if (it == attrTypeToAlias.end())
1343 it->second.print(os);
1349 if (it == attrTypeToAlias.end())
1351 if (!it->second.isPrinted)
1354 it->second.print(os);
1360 auto filterFn = [=](
const auto &aliasIt) {
1361 return aliasIt.second.canBeDeferred() == isDeferred;
1363 for (
auto &[opaqueSymbol, alias] :
1364 llvm::make_filter_range(attrTypeToAlias, filterFn)) {
1368 if (alias.isTypeAlias()) {
1371 alias.isPrinted =
true;
1401 enum :
unsigned { NameSentinel = ~0U };
1403 SSANameState(Operation *op,
const OpPrintingFlags &printerFlags);
1404 SSANameState() =
default;
1409 void printValueID(Value value,
bool printResultNo, raw_ostream &stream)
const;
1412 void printOperationID(Operation *op, raw_ostream &stream)
const;
1416 ArrayRef<int> getOpResultGroups(Operation *op);
1419 BlockInfo getBlockInfo(
Block *block);
1424 void shadowRegionArgs(Region ®ion,
ValueRange namesToUse);
1428 void numberValuesInRegion(Region ®ion);
1429 void numberValuesInBlock(
Block &block);
1430 void numberValuesInOp(Operation &op);
1436 void getResultIDAndNumber(OpResult
result, Value &lookupValue,
1437 std::optional<int> &lookupResultNo)
const;
1440 void setValueName(Value value, StringRef name);
1444 StringRef uniqueValueName(StringRef name);
1467 llvm::ScopedHashTable<StringRef, char> usedNames;
1468 llvm::BumpPtrAllocator usedNameAllocator;
1471 unsigned nextValueID = 0;
1473 unsigned nextArgumentID = 0;
1475 unsigned nextConflictID = 0;
1479 OpPrintingFlags printerFlags;
1484 : printerFlags(printerFlags) {
1485 llvm::SaveAndRestore valueIDSaver(nextValueID);
1486 llvm::SaveAndRestore argumentIDSaver(nextArgumentID);
1487 llvm::SaveAndRestore conflictIDSaver(nextConflictID);
1492 using UsedNamesScopeTy = llvm::ScopedHashTable<StringRef, char>::ScopeTy;
1493 using NamingContext =
1494 std::tuple<Region *, unsigned, unsigned, unsigned, UsedNamesScopeTy *>;
1497 llvm::BumpPtrAllocator allocator;
1500 auto *topLevelNamesScope =
1501 new (allocator.Allocate<UsedNamesScopeTy>()) UsedNamesScopeTy(usedNames);
1505 nameContext.push_back(std::make_tuple(®ion, nextValueID, nextArgumentID,
1506 nextConflictID, topLevelNamesScope));
1508 numberValuesInOp(*op);
1510 while (!nameContext.empty()) {
1512 UsedNamesScopeTy *parentScope;
1516 std::tie(region, std::ignore, std::ignore, std::ignore, parentScope) =
1517 nameContext.pop_back_val();
1519 std::tie(region, nextValueID, nextArgumentID, nextConflictID,
1520 parentScope) = nameContext.pop_back_val();
1524 while (usedNames.getCurScope() != parentScope) {
1525 usedNames.getCurScope()->~UsedNamesScopeTy();
1526 assert((usedNames.getCurScope() !=
nullptr || parentScope ==
nullptr) &&
1527 "top level parentScope must be a nullptr");
1531 auto *curNamesScope =
new (allocator.Allocate<UsedNamesScopeTy>())
1532 UsedNamesScopeTy(usedNames);
1534 numberValuesInRegion(*region);
1538 nameContext.push_back(std::make_tuple(®ion, nextValueID,
1539 nextArgumentID, nextConflictID,
1544 while (usedNames.getCurScope() !=
nullptr)
1545 usedNames.getCurScope()->~UsedNamesScopeTy();
1548void SSANameState::printValueID(
Value value,
bool printResultNo,
1551 stream <<
"<<NULL VALUE>>";
1555 std::optional<int> resultNo;
1556 auto lookupValue = value;
1560 if (OpResult
result = dyn_cast<OpResult>(value))
1561 getResultIDAndNumber(
result, lookupValue, resultNo);
1563 auto it = valueIDs.find(lookupValue);
1564 if (it == valueIDs.end()) {
1565 stream <<
"<<UNKNOWN SSA VALUE>>";
1570 if (it->second != NameSentinel) {
1571 stream << it->second;
1573 auto nameIt = valueNames.find(lookupValue);
1574 assert(nameIt != valueNames.end() &&
"Didn't have a name entry?");
1575 stream << nameIt->second;
1578 if (resultNo && printResultNo)
1579 stream <<
'#' << *resultNo;
1582void SSANameState::printOperationID(Operation *op, raw_ostream &stream)
const {
1583 auto it = operationIDs.find(op);
1584 if (it == operationIDs.end()) {
1585 stream <<
"<<UNKNOWN OPERATION>>";
1587 stream <<
'%' << it->second;
1591ArrayRef<int> SSANameState::getOpResultGroups(Operation *op) {
1592 auto it = opResultGroups.find(op);
1593 return it == opResultGroups.end() ? ArrayRef<int>() : it->second;
1596BlockInfo SSANameState::getBlockInfo(
Block *block) {
1597 auto it = blockNames.find(block);
1598 BlockInfo invalidBlock{-1,
"INVALIDBLOCK"};
1599 return it != blockNames.end() ? it->second : invalidBlock;
1602void SSANameState::shadowRegionArgs(Region ®ion,
ValueRange namesToUse) {
1603 assert(!region.
empty() &&
"cannot shadow arguments of an empty region");
1605 "incorrect number of names passed in");
1607 "only KnownIsolatedFromAbove ops can shadow names");
1609 SmallVector<char, 16> nameStr;
1610 for (
unsigned i = 0, e = namesToUse.size(); i != e; ++i) {
1611 auto nameToUse = namesToUse[i];
1612 if (nameToUse ==
nullptr)
1617 llvm::raw_svector_ostream nameStream(nameStr);
1618 printValueID(nameToUse,
true, nameStream);
1621 assert(valueIDs[nameToReplace] == NameSentinel);
1624 auto name = StringRef(nameStream.str()).drop_front();
1627 valueNames[nameToReplace] = name.copy(usedNameAllocator);
1633StringRef maybeGetValueNameFromLoc(Value value, StringRef name) {
1635 return maybeNameLoc.getName();
1640void SSANameState::numberValuesInRegion(Region ®ion) {
1642 bool opAsmOpInterfaceUsed =
false;
1643 auto setBlockArgNameFn = [&](Value arg, StringRef name) {
1644 assert(!valueIDs.count(arg) &&
"arg numbered multiple times");
1645 assert(llvm::cast<BlockArgument>(arg).getOwner()->getParent() == ®ion &&
1646 "arg not defined in current region");
1647 opAsmOpInterfaceUsed =
true;
1649 name = maybeGetValueNameFromLoc(arg, name);
1650 setValueName(arg, name);
1655 if (
auto asmInterface = dyn_cast<OpAsmOpInterface>(op))
1656 asmInterface.getAsmBlockArgumentNames(region, setBlockArgNameFn);
1658 if (!opAsmOpInterfaceUsed) {
1660 if (
auto interface = dyn_cast<OpAsmTypeInterface>(arg.
getType())) {
1661 interface.getAsmName(
1662 [&](StringRef name) { setBlockArgNameFn(arg, name); });
1670 unsigned nextBlockID = 0;
1671 for (
auto &block : region) {
1674 auto blockInfoIt = blockNames.insert({&block, {-1,
""}});
1675 if (blockInfoIt.second) {
1679 llvm::raw_string_ostream(name) <<
"^bb" << nextBlockID;
1680 blockInfoIt.first->second.name = StringRef(name).copy(usedNameAllocator);
1682 blockInfoIt.first->second.ordering = nextBlockID++;
1684 numberValuesInBlock(block);
1688void SSANameState::numberValuesInBlock(
Block &block) {
1692 SmallString<32> specialNameBuffer(isEntryBlock ?
"arg" :
"");
1693 llvm::raw_svector_ostream specialName(specialNameBuffer);
1695 if (valueIDs.count(arg))
1698 specialNameBuffer.resize(strlen(
"arg"));
1699 specialName << nextArgumentID++;
1701 StringRef specialNameStr = specialName.str();
1703 specialNameStr = maybeGetValueNameFromLoc(arg, specialNameStr);
1704 setValueName(arg, specialNameStr);
1708 for (
auto &op : block)
1709 numberValuesInOp(op);
1712void SSANameState::numberValuesInOp(Operation &op) {
1714 SmallVector<int, 2> resultGroups(1, 0);
1716 bool opAsmOpInterfaceUsed =
false;
1717 auto setResultNameFn = [&](Value
result, StringRef name) {
1718 assert(!valueIDs.count(
result) &&
"result numbered multiple times");
1719 assert(
result.getDefiningOp() == &op &&
"result not defined by 'op'");
1720 opAsmOpInterfaceUsed =
true;
1722 name = maybeGetValueNameFromLoc(
result, name);
1723 setValueName(
result, name);
1726 if (
int resultNo = llvm::cast<OpResult>(
result).getResultNumber())
1727 resultGroups.push_back(resultNo);
1730 auto setBlockNameFn = [&](
Block *block, StringRef name) {
1732 "getAsmBlockArgumentNames callback invoked on a block not directly "
1733 "nested under the current operation");
1734 assert(!blockNames.count(block) &&
"block numbered multiple times");
1735 SmallString<16> tmpBuffer{
"^"};
1737 if (name.data() != tmpBuffer.data()) {
1738 tmpBuffer.append(name);
1739 name = tmpBuffer.str();
1741 name = name.copy(usedNameAllocator);
1742 blockNames[block] = {-1, name};
1746 if (OpAsmOpInterface asmInterface = dyn_cast<OpAsmOpInterface>(&op)) {
1747 asmInterface.getAsmBlockNames(setBlockNameFn);
1748 asmInterface.getAsmResultNames(setResultNameFn);
1750 if (!opAsmOpInterfaceUsed) {
1753 bool allHaveOpAsmTypeInterface =
1755 return isa<OpAsmTypeInterface>(type);
1757 if (allHaveOpAsmTypeInterface) {
1759 auto interface = cast<OpAsmTypeInterface>(
result.
getType());
1760 interface.getAsmName(
1761 [&](StringRef name) { setResultNameFn(
result, name); });
1768 if (numResults == 0) {
1771 if (operationIDs.try_emplace(&op, nextValueID).second)
1780 setValueName(resultBegin, nameLoc.getName());
1785 if (valueIDs.try_emplace(resultBegin, nextValueID).second)
1789 if (resultGroups.size() != 1) {
1790 llvm::array_pod_sort(resultGroups.begin(), resultGroups.end());
1791 opResultGroups.try_emplace(&op, std::move(resultGroups));
1795void SSANameState::getResultIDAndNumber(
1796 OpResult
result, Value &lookupValue,
1797 std::optional<int> &lookupResultNo)
const {
1798 Operation *owner =
result.getOwner();
1801 int resultNo =
result.getResultNumber();
1805 auto resultGroupIt = opResultGroups.find(owner);
1806 if (resultGroupIt == opResultGroups.end()) {
1808 lookupResultNo = resultNo;
1814 ArrayRef<int> resultGroups = resultGroupIt->second;
1815 const auto *it = llvm::upper_bound(resultGroups, resultNo);
1816 int groupResultNo = 0, groupSize = 0;
1819 if (it == resultGroups.end()) {
1820 groupResultNo = resultGroups.back();
1821 groupSize =
static_cast<int>(owner->
getNumResults()) - resultGroups.back();
1824 groupResultNo = *std::prev(it);
1825 groupSize = *it - groupResultNo;
1830 lookupResultNo = resultNo - groupResultNo;
1831 lookupValue = owner->
getResult(groupResultNo);
1834void SSANameState::setValueName(Value value, StringRef name) {
1837 valueIDs[value] = nextValueID++;
1841 valueIDs[value] = NameSentinel;
1842 valueNames[value] = uniqueValueName(name);
1845StringRef SSANameState::uniqueValueName(StringRef name) {
1846 SmallString<16> tmpBuffer;
1850 if (!usedNames.count(name)) {
1851 name = name.copy(usedNameAllocator);
1856 SmallString<64> probeName(name);
1857 probeName.push_back(
'_');
1859 probeName += llvm::utostr(nextConflictID++);
1860 if (!usedNames.count(probeName)) {
1861 name = probeName.str().copy(usedNameAllocator);
1864 probeName.resize(name.size() + 1);
1868 usedNames.insert(name,
char());
1878class DistinctState {
1881 uint64_t getId(DistinctAttr distinctAttr);
1884 uint64_t distinctCounter = 0;
1889uint64_t DistinctState::getId(DistinctAttr distinctAttr) {
1891 distinctAttrMap.try_emplace(distinctAttr, distinctCounter);
1894 return it->getSecond();
1915 llvm_unreachable(
"unknown AsmResourceEntryKind");
1919 std::unique_ptr<ResourceCollection> &collection = keyToResources[key.str()];
1921 collection = std::make_unique<ResourceCollection>(key);
1925std::vector<std::unique_ptr<AsmResourcePrinter>>
1927 std::vector<std::unique_ptr<AsmResourcePrinter>> printers;
1928 for (
auto &it : keyToResources) {
1929 ResourceCollection *collection = it.second.get();
1931 return collection->buildResources(op, builder);
1933 printers.emplace_back(
1939LogicalResult FallbackAsmResourceMap::ResourceCollection::parseResource(
1943 FailureOr<AsmResourceBlob> blob = entry.
parseAsBlob();
1946 resources.emplace_back(entry.
getKey(), std::move(*blob));
1953 resources.emplace_back(entry.
getKey(), *value);
1956 case AsmResourceEntryKind::String: {
1960 resources.emplace_back(entry.
getKey(), std::move(*str));
1967void FallbackAsmResourceMap::ResourceCollection::buildResources(
1968 Operation *op, AsmResourceBuilder &builder)
const {
1969 for (
const auto &entry : resources) {
1970 if (
const auto *value = std::get_if<AsmResourceBlob>(&entry.value))
1972 else if (
const auto *value = std::get_if<bool>(&entry.value))
1974 else if (
const auto *value = std::get_if<std::string>(&entry.value))
1977 llvm_unreachable(
"unknown AsmResourceEntryKind");
1991 : interfaces(op->
getContext()), nameState(op, printerFlags),
1992 printerFlags(printerFlags), locationMap(locationMap) {}
1995 : interfaces(ctx), printerFlags(printerFlags), locationMap(locationMap) {}
1999 aliasState.initialize(op, printerFlags, interfaces);
2019 return llvm::make_pointee_range(externalResourcePrinters);
2029 (*locationMap)[op] = std::make_pair(line, col);
2035 return dialectResources;
2039 return success(cyclicPrintingStack.insert(opaquePointer));
2055 AliasState aliasState;
2058 SSANameState nameState;
2061 DistinctState distinctState;
2077template <
typename Range>
2081 [&stream](
const auto &dimSize) {
2082 if (ShapedType::isDynamic(dimSize))
2100 return printerFlags;
2104 auto parentThreadId = llvm::get_threadid();
2106 if (parentThreadId == llvm::get_threadid()) {
2108 diag.print(llvm::dbgs());
2109 llvm::dbgs() <<
"\n";
2117 <<
"' failed to verify and will be printed in generic form";
2121 return printerFlags;
2140 return impl->getPrinterFlags();
2144 std::unique_ptr<AsmResourcePrinter> printer) {
2145 impl->externalResourcePrinters.emplace_back(std::move(printer));
2150 return impl->getDialectResources();
2172 if (!isTopLevel && succeeded(
state.getAliasState().getAlias(loc,
os)))
2176 .Case([&](OpaqueLoc loc) {
2179 .Case([&](UnknownLoc loc) {
2187 os << loc.getFilename().getValue();
2190 if (loc.getEndColumn() == loc.getStartColumn() &&
2191 loc.getStartLine() == loc.getEndLine()) {
2192 os <<
':' << loc.getStartLine() <<
':' << loc.getStartColumn();
2195 if (loc.getStartLine() == loc.getEndLine()) {
2196 os <<
':' << loc.getStartLine() <<
':' << loc.getStartColumn()
2197 <<
" to :" << loc.getEndColumn();
2200 os <<
':' << loc.getStartLine() <<
':' << loc.getStartColumn() <<
" to "
2201 << loc.getEndLine() <<
':' << loc.getEndColumn();
2203 .Case([&](NameLoc loc) {
2207 auto childLoc = loc.getChildLoc();
2208 if (!llvm::isa<UnknownLoc>(childLoc)) {
2214 .Case([&](CallSiteLoc loc) {
2221 if (llvm::isa<NameLoc>(callee)) {
2222 if (llvm::isa<FileLineColLoc>(caller)) {
2240 if (
Attribute metadata = loc.getMetadata()) {
2247 printLocationInternal(loc, pretty);
2261 bool *printedHex =
nullptr) {
2266 bool isInf = apValue.isInfinity();
2267 bool isNaN = apValue.isNaN();
2268 if (!isInf && !isNaN) {
2270 apValue.toString(strValue, 6, 0,
2276 assert(((strValue[0] >=
'0' && strValue[0] <=
'9') ||
2277 ((strValue[0] ==
'-' || strValue[0] ==
'+') &&
2278 (strValue[1] >=
'0' && strValue[1] <=
'9'))) &&
2279 "[-+]?[0-9] regex does not match!");
2283 if (APFloat(apValue.getSemantics(), strValue).bitwiseIsEqual(apValue)) {
2291 apValue.toString(strValue);
2294 if (strValue.str().contains(
'.')) {
2305 APInt apInt = apValue.bitcastToAPInt();
2306 apInt.toString(str, 16,
false,
2326 if (symName.empty() || !isalpha(symName.front()))
2331 symName = symName.drop_while(
2332 [](
char c) {
return llvm::isAlnum(c) || c ==
'.' || c ==
'_'; });
2333 if (symName.empty())
2338 return symName.front() ==
'<' && symName.back() ==
'>';
2343 StringRef dialectName, StringRef symString) {
2344 os << symPrefix << dialectName;
2349 os <<
'.' << symString;
2353 os <<
'<' << symString <<
'>';
2362 if (name.empty() || (!isalpha(name[0]) && name[0] !=
'_'))
2364 return llvm::all_of(name.drop_front(), [](
unsigned char c) {
2365 return isalnum(c) || c ==
'_' || c ==
'$' || c ==
'.';
2380 printEscapedString(keyword, os);
2388 if (symbolRef.empty()) {
2389 os <<
"@<<INVALID EMPTY SYMBOL>>";
2402 os << R
"(dense_resource<__elided__>)";
2407 auto *
interface = cast<OpAsmDialectInterface>(resource.getDialect());
2413 return state.getAliasState().getAlias(attr,
os);
2417 return state.getAliasState().getAlias(type,
os);
2423 os <<
"<<NULL ATTRIBUTE>>";
2434 if (!isa<BuiltinDialect>(attr.
getDialect())) {
2436 }
else if (
auto opaqueAttr = llvm::dyn_cast<OpaqueAttr>(attr)) {
2438 opaqueAttr.getAttrData());
2439 }
else if (llvm::isa<UnitAttr>(attr)) {
2442 }
else if (
auto distinctAttr = llvm::dyn_cast<DistinctAttr>(attr)) {
2443 os <<
"distinct[" <<
state.getDistinctState().getId(distinctAttr) <<
"]<";
2449 }
else if (
auto dictAttr = llvm::dyn_cast<DictionaryAttr>(attr)) {
2455 }
else if (
auto intAttr = llvm::dyn_cast<IntegerAttr>(attr)) {
2456 Type intType = intAttr.getType();
2458 os << (intAttr.getValue().getBoolValue() ?
"true" :
"false");
2469 intAttr.getValue().print(
os, !isUnsigned);
2475 }
else if (
auto floatAttr = llvm::dyn_cast<FloatAttr>(attr)) {
2476 bool printedHex =
false;
2484 }
else if (
auto strAttr = llvm::dyn_cast<StringAttr>(attr)) {
2487 }
else if (
auto arrayAttr = llvm::dyn_cast<ArrayAttr>(attr)) {
2490 printAttribute(attr, AttrTypeElision::May);
2494 }
else if (
auto affineMapAttr = llvm::dyn_cast<AffineMapAttr>(attr)) {
2495 os <<
"affine_map<";
2496 affineMapAttr.getValue().print(
os);
2502 }
else if (
auto integerSetAttr = llvm::dyn_cast<IntegerSetAttr>(attr)) {
2503 os <<
"affine_set<";
2504 integerSetAttr.getValue().print(
os);
2510 }
else if (
auto typeAttr = llvm::dyn_cast<TypeAttr>(attr)) {
2513 }
else if (
auto refAttr = llvm::dyn_cast<SymbolRefAttr>(attr)) {
2520 }
else if (
auto intOrFpEltAttr =
2521 llvm::dyn_cast<DenseTypedElementsAttr>(attr)) {
2522 if (
printerFlags.shouldElideElementsAttr(intOrFpEltAttr)) {
2529 Type eltType = intOrFpEltAttr.getElementType();
2530 if (isa<FloatType, IntegerType, IndexType, ComplexType>(eltType)) {
2534 cast<DenseElementType>(eltType));
2540 }
else if (
auto strEltAttr = llvm::dyn_cast<DenseStringElementsAttr>(attr)) {
2541 if (
printerFlags.shouldElideElementsAttr(strEltAttr)) {
2549 }
else if (
auto sparseEltAttr = llvm::dyn_cast<SparseElementsAttr>(attr)) {
2550 if (
printerFlags.shouldElideElementsAttr(sparseEltAttr.getIndices()) ||
2551 printerFlags.shouldElideElementsAttr(sparseEltAttr.getValues())) {
2556 if (
indices.getNumElements() != 0) {
2563 }
else if (
auto stridedLayoutAttr = llvm::dyn_cast<StridedLayoutAttr>(attr)) {
2564 stridedLayoutAttr.print(
os);
2565 }
else if (
auto denseArrayAttr = llvm::dyn_cast<DenseArrayAttr>(attr)) {
2567 printType(denseArrayAttr.getElementType());
2568 if (!denseArrayAttr.empty()) {
2574 }
else if (
auto resourceAttr =
2575 llvm::dyn_cast<DenseResourceElementsAttr>(attr)) {
2576 os <<
"dense_resource<";
2579 }
else if (
auto locAttr = llvm::dyn_cast<LocationAttr>(attr)) {
2582 llvm::report_fatal_error(
"Unknown builtin attribute");
2586 if (
auto typedAttr = llvm::dyn_cast<TypedAttr>(attr)) {
2587 Type attrType = typedAttr.getType();
2588 if (!llvm::isa<NoneType>(attrType)) {
2600 os << (value.getBoolValue() ?
"true" :
"false");
2610 return printEltFn(0);
2613 auto numElements = type.getNumElements();
2614 if (numElements == 0)
2622 int64_t rank = type.getRank();
2625 unsigned openBrackets = 0;
2627 auto shape = type.getShape();
2628 auto bumpCounter = [&] {
2630 ++counter[rank - 1];
2632 for (
unsigned i = rank - 1; i > 0; --i)
2633 if (counter[i] >=
shape[i]) {
2642 for (
unsigned idx = 0, e = numElements; idx != e; ++idx) {
2645 while (openBrackets++ < rank)
2647 openBrackets = rank;
2651 while (openBrackets-- > 0)
2657 if (
auto stringAttr = llvm::dyn_cast<DenseStringElementsAttr>(attr))
2666 auto type = attr.getType();
2667 auto elementType = type.getElementType();
2670 if (allowHex &&
printerFlags.shouldPrintElementsAttrWithHex(attr)) {
2672 if (llvm::endianness::native == llvm::endianness::big) {
2677 DenseTypedElementsAttr::convertEndianOfArrayRefForBEmachine(
2678 rawData, convRawData, type);
2687 if (ComplexType complexTy = llvm::dyn_cast<ComplexType>(elementType)) {
2688 Type complexElementType = complexTy.getElementType();
2692 if (llvm::isa<IntegerType>(complexElementType)) {
2695 auto complexValue = *(valueIt + index);
2697 printDenseIntElement(complexValue.real(), os, complexElementType);
2699 printDenseIntElement(complexValue.imag(), os, complexElementType);
2705 auto complexValue = *(valueIt + index);
2707 printFloatValue(complexValue.real(), os);
2709 printFloatValue(complexValue.imag(), os);
2713 }
else if (elementType.isIntOrIndex()) {
2714 auto valueIt = attr.value_begin<APInt>();
2716 printDenseIntElement(*(valueIt + index), os, elementType);
2719 assert(llvm::isa<FloatType>(elementType) &&
"unexpected element type");
2720 auto valueIt = attr.value_begin<APFloat>();
2722 printFloatValue(*(valueIt + index), os);
2728 DenseStringElementsAttr attr) {
2742 size_t bitSize = denseEltType.getDenseElementBitSize();
2743 size_t byteSize = llvm::divideCeil(bitSize,
static_cast<size_t>(CHAR_BIT));
2748 size_t offset = attr.isSplat() ? 0 : index * byteSize;
2749 ArrayRef<char> elemData = rawData.slice(offset, byteSize);
2750 Attribute elemAttr = denseEltType.convertToAttribute(elemData);
2751 printAttributeImpl(elemAttr);
2756 Type type = attr.getElementType();
2758 unsigned byteSize = bitwidth / 8;
2761 auto printElementAt = [&](
unsigned i) {
2762 APInt value(bitwidth, 0);
2764 llvm::LoadIntFromMemory(
2765 value,
reinterpret_cast<const uint8_t *
>(data.begin() + byteSize * i),
2772 APFloat fltVal(llvm::cast<FloatType>(type).getFloatSemantics(), value);
2776 llvm::interleaveComma(llvm::seq<unsigned>(0, attr.size()),
getStream(),
2782 os <<
"<<NULL TYPE>>";
2794 .Case([&](OpaqueType opaqueTy) {
2796 opaqueTy.getTypeData());
2798 .Case<IndexType>([&](
Type) {
os <<
"index"; })
2799 .Case<Float4E2M1FNType>([&](
Type) {
os <<
"f4E2M1FN"; })
2800 .Case<Float6E2M3FNType>([&](
Type) {
os <<
"f6E2M3FN"; })
2801 .Case<Float6E3M2FNType>([&](
Type) {
os <<
"f6E3M2FN"; })
2802 .Case<Float8E5M2Type>([&](
Type) {
os <<
"f8E5M2"; })
2803 .Case<Float8E4M3Type>([&](
Type) {
os <<
"f8E4M3"; })
2804 .Case<Float8E4M3FNType>([&](
Type) {
os <<
"f8E4M3FN"; })
2805 .Case<Float8E5M2FNUZType>([&](
Type) {
os <<
"f8E5M2FNUZ"; })
2806 .Case<Float8E4M3FNUZType>([&](
Type) {
os <<
"f8E4M3FNUZ"; })
2807 .Case<Float8E4M3B11FNUZType>([&](
Type) {
os <<
"f8E4M3B11FNUZ"; })
2808 .Case<Float8E3M4Type>([&](
Type) {
os <<
"f8E3M4"; })
2809 .Case<Float8E8M0FNUType>([&](
Type) {
os <<
"f8E8M0FNU"; })
2810 .Case<Float8E5M3FNUType>([&](
Type) {
os <<
"f8E5M3FNU"; })
2811 .Case<BFloat16Type>([&](
Type) {
os <<
"bf16"; })
2812 .Case<Float16Type>([&](
Type) {
os <<
"f16"; })
2813 .Case<FloatTF32Type>([&](
Type) {
os <<
"tf32"; })
2814 .Case<Float32Type>([&](
Type) {
os <<
"f32"; })
2815 .Case<Float64Type>([&](
Type) {
os <<
"f64"; })
2816 .Case<Float80Type>([&](
Type) {
os <<
"f80"; })
2817 .Case<Float128Type>([&](
Type) {
os <<
"f128"; })
2818 .Case([&](IntegerType integerTy) {
2819 if (integerTy.isSigned())
2821 else if (integerTy.isUnsigned())
2823 os <<
'i' << integerTy.getWidth();
2825 .Case([&](FunctionType funcTy) {
2830 if (results.size() == 1 && !llvm::isa<FunctionType>(results[0])) {
2838 .Case([&](VectorType vectorTy) {
2839 auto scalableDims = vectorTy.getScalableDims();
2841 auto vShape = vectorTy.getShape();
2842 unsigned lastDim = vShape.size();
2843 unsigned dimIdx = 0;
2844 for (dimIdx = 0; dimIdx < lastDim; dimIdx++) {
2845 if (!scalableDims.empty() && scalableDims[dimIdx])
2847 os << vShape[dimIdx];
2848 if (!scalableDims.empty() && scalableDims[dimIdx])
2855 .Case([&](RankedTensorType tensorTy) {
2858 if (!tensorTy.getShape().empty())
2862 if (tensorTy.getEncoding()) {
2868 .Case([&](UnrankedTensorType tensorTy) {
2873 .Case([&](MemRefType memrefTy) {
2876 if (!memrefTy.getShape().empty())
2879 MemRefLayoutAttrInterface layout = memrefTy.getLayout();
2880 if (!llvm::isa<AffineMapAttr>(layout) || !layout.isIdentity()) {
2885 if (memrefTy.getMemorySpace()) {
2895 if (memrefTy.getMemorySpace()) {
2901 .Case([&](ComplexType complexTy) {
2906 .Case([&](TupleType tupleTy) {
2909 [&](
Type type) { printType(type); });
2912 .Case<NoneType>([&](
Type) {
os <<
"none"; })
2913 .Case<TokenType>([&](
Type) {
os <<
"token"; })
2914 .Case([&](GraphType graphTy) {
2919 if (results.size() == 1 && !isa<FunctionType, GraphType>(results[0])) {
2938 auto printFilteredAttributesFn = [&](
auto filteredAttrs) {
2941 os <<
" attributes";
2951 if (elidedAttrs.empty())
2952 return printFilteredAttributesFn(attrs);
2955 llvm::SmallDenseSet<StringRef> elidedAttrsSet(elidedAttrs.begin(),
2957 auto filteredAttrs = llvm::make_filter_range(attrs, [&](
NamedAttribute attr) {
2958 return !elidedAttrsSet.contains(attr.
getName().strref());
2960 if (!filteredAttrs.empty())
2961 printFilteredAttributesFn(filteredAttrs);
2968 if (llvm::isa<UnitAttr>(attr.
getValue()))
2979 std::string attrName;
2981 llvm::raw_string_ostream attrNameStr(attrName);
2991 dialect.printAttribute(attr, printer);
3000 std::string typeName;
3002 llvm::raw_string_ostream typeNameStr(typeName);
3012 dialect.printType(type, printer);
3019 llvm::printEscapedString(str,
os);
3024 os <<
"\"0x" << llvm::toHex(str) <<
"\"";
3031 return state.pushCyclicPrinting(opaquePointer);
3047 assert(
impl &&
"expected AsmPrinter::getStream to be overriden");
3048 return impl->getStream();
3052 assert(
impl &&
"expected AsmPrinter::printNewLine to be overriden");
3053 impl->printNewline();
3057 assert(
impl &&
"expected AsmPrinter::increaseIndent to be overriden");
3058 impl->increaseIndent();
3062 assert(
impl &&
"expected AsmPrinter::decreaseIndent to be overriden");
3063 impl->decreaseIndent();
3068 assert(
impl &&
"expected AsmPrinter::printFloat to be overriden");
3073 assert(
impl &&
"expected AsmPrinter::printType to be overriden");
3074 impl->printType(type);
3078 assert(
impl &&
"expected AsmPrinter::printAttribute to be overriden");
3079 impl->printAttribute(attr);
3083 assert(
impl &&
"expected AsmPrinter::printAlias to be overriden");
3084 return impl->printAlias(attr);
3088 assert(
impl &&
"expected AsmPrinter::printAlias to be overriden");
3089 return impl->printAlias(type);
3094 "expected AsmPrinter::printAttributeWithoutType to be overriden");
3099 assert(
impl &&
"expected AsmPrinter::printNamedAttribute to be overriden");
3100 impl->printNamedAttribute(attr);
3104 assert(
impl &&
"expected AsmPrinter::printKeywordOrString to be overriden");
3109 assert(
impl &&
"expected AsmPrinter::printString to be overriden");
3111 printEscapedString(keyword,
getStream());
3116 assert(
impl &&
"expected AsmPrinter::printSymbolName to be overriden");
3121 assert(
impl &&
"expected AsmPrinter::printResourceHandle to be overriden");
3122 impl->printResourceHandle(resource);
3130 return impl->pushCyclicPrinting(opaquePointer);
3147 const char *binopSpelling =
nullptr;
3150 unsigned pos = cast<AffineSymbolExpr>(expr).getPosition();
3152 printValueName(pos,
true);
3158 unsigned pos = cast<AffineDimExpr>(expr).getPosition();
3160 printValueName(pos,
false);
3166 os << cast<AffineConstantExpr>(expr).getValue();
3169 binopSpelling =
" + ";
3172 binopSpelling =
" * ";
3175 binopSpelling =
" floordiv ";
3178 binopSpelling =
" ceildiv ";
3181 binopSpelling =
" mod ";
3185 auto binOp = cast<AffineBinaryOpExpr>(expr);
3195 auto rhsConst = dyn_cast<AffineConstantExpr>(rhsExpr);
3197 rhsConst.getValue() == -1) {
3207 os << binopSpelling;
3221 if (
auto rhs = dyn_cast<AffineBinaryOpExpr>(rhsExpr)) {
3224 if (
auto rrhs = dyn_cast<AffineConstantExpr>(rrhsExpr)) {
3225 if (rrhs.getValue() == -1) {
3242 if (rrhs.getValue() < -1) {
3250 os <<
" * " << -
static_cast<uint64_t
>(rrhs.getValue());
3260 if (
auto rhsConst = dyn_cast<AffineConstantExpr>(rhsExpr)) {
3261 if (rhsConst.getValue() < 0) {
3264 os <<
" - " << -
static_cast<uint64_t
>(rhsConst.getValue());
3282 isEq ?
os <<
" == 0" :
os <<
" >= 0";
3288 for (
int i = 0; i < (int)map.
getNumDims() - 1; ++i)
3289 os <<
'd' << i <<
", ";
3298 os <<
's' << i <<
", ";
3307 [&](
AffineExpr expr) { printAffineExpr(expr); });
3314 for (
unsigned i = 1; i < set.
getNumDims(); ++i)
3315 os <<
'd' << i - 1 <<
", ";
3324 os <<
's' << i <<
", ";
3333 for (
int i = 1; i < numConstraints; ++i) {
3337 if (numConstraints >= 1)
3339 set.
isEq(numConstraints - 1));
3358 void printTopLevelOperation(
Operation *op);
3362 void printFullOpWithIndentAndLoc(
Operation *op);
3368 void printCustomOrGenericOp(
Operation *op)
override;
3370 void printGenericOp(
Operation *op,
bool printOpName)
override;
3373 void printBlockName(
Block *block);
3378 void print(
Block *block,
bool printBlockArgs =
true,
3379 bool printBlockTerminator =
true);
3382 void printValueID(
Value value,
bool printResultNo =
true,
3395 void printOptionalLocationSpecifier(
Location loc)
override {
3396 printTrailingLocation(loc);
3406 bool omitType =
false)
override;
3409 void printOperand(Value value)
override { printValueID(value); }
3410 void printOperand(Value value, raw_ostream &os)
override {
3411 printValueID(value,
true, &os);
3415 void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
3416 ArrayRef<StringRef> elidedAttrs = {})
override {
3417 Impl::printOptionalAttrDict(attrs, elidedAttrs);
3419 void printOptionalAttrDictWithKeyword(
3420 ArrayRef<NamedAttribute> attrs,
3421 ArrayRef<StringRef> elidedAttrs = {})
override {
3422 Impl::printOptionalAttrDict(attrs, elidedAttrs,
3427 void printSuccessor(
Block *successor)
override;
3431 void printSuccessorAndUseList(
Block *successor,
3435 void printRegion(Region ®ion,
bool printEntryBlockArgs,
3436 bool printBlockTerminators,
bool printEmptyBlock)
override;
3442 void shadowRegionArgs(Region ®ion,
ValueRange namesToUse)
override {
3448 void printAffineMapOfSSAIds(AffineMapAttr mapAttr,
3453 void printAffineExprOfSSAIds(AffineExpr expr,
ValueRange dimOperands,
3457 void printUsersComment(Operation *op);
3460 void printUsersComment(BlockArgument arg);
3463 void printValueUsers(Value value);
3467 void printUserIDs(Operation *user,
bool prefixComma =
false);
3472 class ResourceBuilder :
public AsmResourceBuilder {
3478 using PrintFn =
function_ref<void(StringRef, ValueFn, int64_t sizeHint)>;
3480 ResourceBuilder(PrintFn printFn) : printFn(printFn) {}
3481 ~ResourceBuilder()
override =
default;
3483 void buildBool(StringRef key,
bool data)
final {
3485 key, [&](raw_ostream &os) { os << (data ?
"true" :
"false"); },
3489 void buildString(StringRef key, StringRef data)
final {
3492 [&](raw_ostream &os) {
3494 llvm::printEscapedString(data, os);
3500 void buildBlob(StringRef key, ArrayRef<char> data,
3501 uint32_t dataAlignment)
final {
3504 int64_t sizeHint = 2 * int64_t(
sizeof(dataAlignment) + data.size()) + 4;
3507 [&](raw_ostream &os) {
3510 llvm::support::ulittle32_t dataAlignmentLE(dataAlignment);
3513 StringRef(
reinterpret_cast<char *
>(&dataAlignmentLE),
3514 sizeof(dataAlignment)))
3515 << llvm::toHex(StringRef(data.data(), data.size())) <<
"\"";
3525 void printFileMetadataDictionary(Operation *op);
3531 void printResourceFileMetadata(
function_ref<
void()> checkAddMetadataDict,
3539 SmallVector<StringRef> defaultDialectStack{
"builtin"};
3543void OperationPrinter::printTopLevelOperation(Operation *op) {
3545 state.
getAliasState().printNonDeferredAliases(*
this, newLine);
3548 printFullOpWithIndentAndLoc(op);
3555 printFileMetadataDictionary(op);
3558void OperationPrinter::printFileMetadataDictionary(Operation *op) {
3559 bool sawMetadataEntry =
false;
3560 auto checkAddMetadataDict = [&] {
3561 if (!std::exchange(sawMetadataEntry,
true))
3562 os << newLine <<
"{-#" << newLine;
3566 printResourceFileMetadata(checkAddMetadataDict, op);
3569 if (sawMetadataEntry)
3570 os << newLine <<
"#-}" << newLine;
3573void OperationPrinter::printResourceFileMetadata(
3574 function_ref<
void()> checkAddMetadataDict, Operation *op) {
3576 bool hadResource =
false;
3577 bool needResourceComma =
false;
3578 bool needEntryComma =
false;
3579 auto processProvider = [&](StringRef dictName, StringRef name,
auto &provider,
3580 auto &&...providerArgs) {
3581 bool hadEntry =
false;
3582 auto printFn = [&](StringRef key, ResourceBuilder::ValueFn valueFn,
3584 checkAddMetadataDict();
3586 std::string resourceStr;
3587 auto printResourceStr = [&](raw_ostream &os) { os << resourceStr; };
3588 std::optional<uint64_t> charLimit =
3590 if (charLimit.has_value()) {
3592 if (charLimit.value() == 0)
3597 if (sizeHint >= 0 && uint64_t(sizeHint) > charLimit.value())
3600 llvm::raw_string_ostream ss(resourceStr);
3604 if (resourceStr.size() > charLimit.value())
3608 valueFn = printResourceStr;
3612 if (!std::exchange(hadResource,
true)) {
3613 if (needResourceComma)
3614 os <<
"," << newLine;
3615 os <<
" " << dictName <<
"_resources: {" << newLine;
3618 if (!std::exchange(hadEntry,
true)) {
3620 os <<
"," << newLine;
3621 os <<
" " << name <<
": {" << newLine;
3623 os <<
"," << newLine;
3631 ResourceBuilder entryBuilder(printFn);
3632 provider.buildResources(op, providerArgs..., entryBuilder);
3634 needEntryComma |= hadEntry;
3636 os << newLine <<
" }";
3643 StringRef name = interface.getDialect()->getNamespace();
3644 auto it = dialectResources.find(interface.getDialect());
3645 if (it != dialectResources.end())
3646 processProvider(
"dialect", name, interface, it->second);
3648 processProvider(
"dialect", name, interface,
3652 os << newLine <<
" }";
3656 needEntryComma =
false;
3657 needResourceComma = hadResource;
3658 hadResource =
false;
3660 processProvider(
"external", printer.getName(), printer);
3662 os << newLine <<
" }";
3670void OperationPrinter::printRegionArgument(BlockArgument arg,
3671 ArrayRef<NamedAttribute> argAttrs,
3678 printOptionalAttrDict(argAttrs);
3680 printTrailingLocation(arg.
getLoc(),
false);
3683void OperationPrinter::printFullOpWithIndentAndLoc(Operation *op) {
3687 os.indent(currentIndent);
3689 printTrailingLocation(op->
getLoc());
3691 printUsersComment(op);
3694void OperationPrinter::printFullOp(Operation *op) {
3696 auto printResultGroup = [&](
size_t resultNo,
size_t resultCount) {
3697 printValueID(op->
getResult(resultNo),
false);
3698 if (resultCount > 1)
3699 os <<
':' << resultCount;
3703 ArrayRef<int> resultGroups = state.
getSSANameState().getOpResultGroups(op);
3704 if (!resultGroups.empty()) {
3707 interleaveComma(llvm::seq<int>(0, resultGroups.size() - 1), [&](
int i) {
3708 printResultGroup(resultGroups[i],
3709 resultGroups[i + 1] - resultGroups[i]);
3712 printResultGroup(resultGroups.back(), numResults - resultGroups.back());
3715 printResultGroup(0, numResults);
3721 printCustomOrGenericOp(op);
3724void OperationPrinter::printUsersComment(Operation *op) {
3728 printOperationID(op);
3729 }
else if (numResults && op->
use_empty()) {
3731 }
else if (numResults && !op->
use_empty()) {
3734 unsigned usedInNResults = 0;
3735 unsigned usedInNOperations = 0;
3736 SmallPtrSet<Operation *, 1> userSet;
3737 for (Operation *user : op->
getUsers()) {
3738 if (userSet.insert(user).second) {
3739 ++usedInNOperations;
3740 usedInNResults += user->getNumResults();
3745 bool exactlyOneUniqueUse =
3746 usedInNResults <= 1 && usedInNOperations <= 1 && numResults == 1;
3747 os <<
" // " << (exactlyOneUniqueUse ?
"user" :
"users") <<
": ";
3748 bool shouldPrintBrackets = numResults > 1;
3749 auto printOpResult = [&](OpResult opResult) {
3750 if (shouldPrintBrackets)
3752 printValueUsers(opResult);
3753 if (shouldPrintBrackets)
3757 interleaveComma(op->
getResults(), printOpResult);
3761void OperationPrinter::printUsersComment(BlockArgument arg) {
3767 os <<
" is used by ";
3768 printValueUsers(arg);
3773void OperationPrinter::printValueUsers(Value value) {
3779 SmallPtrSet<Operation *, 1> userSet;
3781 if (userSet.insert(user).second)
3782 printUserIDs(user, index);
3786void OperationPrinter::printUserIDs(Operation *user,
bool prefixComma) {
3791 printOperationID(user);
3794 [
this](Value
result) { printValueID(result); });
3798void OperationPrinter::printCustomOrGenericOp(Operation *op) {
3804 opInfo->printAssembly(op, *
this, defaultDialectStack.back());
3809 if (
auto opPrinter = dialect->getOperationPrinter(op)) {
3814 if (name.count(
'.') == 1)
3815 name.consume_front((defaultDialectStack.back() +
".").str());
3819 opPrinter(op, *
this);
3826 printGenericOp(op,
true);
3829void OperationPrinter::printGenericOp(Operation *op,
bool printOpName) {
3833 interleaveComma(op->
getOperands(), [&](Value value) { printValueID(value); });
3840 [&](
Block *successor) { printBlockName(successor); });
3854 interleaveComma(op->
getRegions(), [&](Region ®ion) {
3855 printRegion(region, true,
3868void OperationPrinter::printBlockName(
Block *block) {
3872void OperationPrinter::print(
Block *block,
bool printBlockArgs,
3873 bool printBlockTerminator) {
3875 if (printBlockArgs) {
3876 os.indent(currentIndent);
3877 printBlockName(block);
3882 interleaveComma(block->
getArguments(), [&](BlockArgument arg) {
3885 printType(arg.getType());
3887 printTrailingLocation(arg.getLoc(), false);
3895 os <<
" // block is not in a region!";
3898 os <<
" // no predecessors";
3901 printBlockName(pred);
3905 SmallVector<BlockInfo, 4> predIDs;
3908 llvm::sort(predIDs, [](BlockInfo
lhs, BlockInfo
rhs) {
3909 return lhs.ordering <
rhs.ordering;
3912 os <<
" // " << predIDs.size() <<
" preds: ";
3914 interleaveComma(predIDs, [&](BlockInfo pred) { os << pred.name; });
3919 currentIndent += indentWidth;
3923 os.indent(currentIndent);
3924 printUsersComment(arg);
3928 bool hasTerminator =
3930 auto range = llvm::make_range(
3932 std::prev(block->
end(),
3933 (!hasTerminator || printBlockTerminator) ? 0 : 1));
3934 for (
auto &op : range) {
3935 printFullOpWithIndentAndLoc(&op);
3938 currentIndent -= indentWidth;
3941void OperationPrinter::printValueID(Value value,
bool printResultNo,
3942 raw_ostream *streamOverride)
const {
3944 streamOverride ? *streamOverride : os);
3947void OperationPrinter::printOperationID(Operation *op,
3948 raw_ostream *streamOverride)
const {
3949 state.
getSSANameState().printOperationID(op, streamOverride ? *streamOverride
3953void OperationPrinter::printSuccessor(
Block *successor) {
3954 printBlockName(successor);
3957void OperationPrinter::printSuccessorAndUseList(
Block *successor,
3959 printBlockName(successor);
3960 if (succOperands.empty())
3964 interleaveComma(succOperands,
3965 [
this](Value operand) { printValueID(operand); });
3967 interleaveComma(succOperands,
3972void OperationPrinter::printRegion(Region ®ion,
bool printEntryBlockArgs,
3973 bool printBlockTerminators,
3974 bool printEmptyBlock) {
3979 os <<
"{" << newLine;
3980 if (!region.
empty()) {
3981 llvm::scope_exit restoreDefaultDialect(
3982 [&]() { defaultDialectStack.pop_back(); });
3983 if (
auto iface = dyn_cast<OpAsmOpInterface>(region.
getParentOp()))
3984 defaultDialectStack.push_back(iface.getDefaultDialect());
3986 defaultDialectStack.push_back(
"");
3988 auto *entryBlock = ®ion.
front();
3992 bool shouldAlwaysPrintBlockHeader =
3993 (printEmptyBlock && entryBlock->empty()) ||
3994 (printEntryBlockArgs && entryBlock->getNumArguments() != 0);
3995 print(entryBlock, shouldAlwaysPrintBlockHeader, printBlockTerminators);
3996 for (
auto &
b : llvm::drop_begin(region.
getBlocks(), 1))
3999 os.indent(currentIndent) <<
"}";
4002void OperationPrinter::printAffineMapOfSSAIds(AffineMapAttr mapAttr,
4005 os <<
"<<NULL AFFINE MAP>>";
4008 AffineMap map = mapAttr.getValue();
4010 auto printValueName = [&](
unsigned pos,
bool isSymbol) {
4011 unsigned index = isSymbol ? numDims + pos : pos;
4012 assert(index < operands.size());
4015 printValueID(operands[index]);
4020 interleaveComma(map.
getResults(), [&](AffineExpr expr) {
4021 printAffineExpr(expr, printValueName);
4025void OperationPrinter::printAffineExprOfSSAIds(AffineExpr expr,
4028 auto printValueName = [&](
unsigned pos,
bool isSymbol) {
4030 return printValueID(dimOperands[pos]);
4032 printValueID(symOperands[pos]);
4035 printAffineExpr(expr, printValueName);
4044 os <<
"<<NULL ATTRIBUTE>>";
4049 print(os, state, elideType);
4055 : AttrTypeElision::Never);
4059 print(llvm::errs());
4060 llvm::errs() <<
"\n";
4065 os <<
"<<NULL ATTRIBUTE>>";
4074 uint64_t posPrior = os.tell();
4076 dialect.printAttribute(*
this, printer);
4077 if (posPrior != os.tell())
4086 os <<
"<<NULL ATTRIBUTE>>";
4096 os <<
"<<NULL TYPE>>";
4108 print(llvm::errs());
4109 llvm::errs() <<
"\n";
4113 print(llvm::errs());
4114 llvm::errs() <<
"\n";
4118 print(llvm::errs());
4119 llvm::errs() <<
"\n";
4124 os <<
"<<NULL AFFINE EXPR>>";
4132 print(llvm::errs());
4133 llvm::errs() <<
"\n";
4138 os <<
"<<NULL AFFINE MAP>>";
4153 os <<
"<<NULL VALUE>>";
4158 return op->
print(os, flags);
4161 os <<
"<block argument> of type '" << arg.
getType()
4166 os <<
"<<NULL VALUE>>";
4171 return op->
print(os, state);
4175 os <<
"<block argument> of type '" << arg.
getType()
4186 llvm::errs() <<
"\n";
4217 if (
auto result = llvm::dyn_cast<OpResult>(*
this)) {
4220 op = llvm::cast<BlockArgument>(*this).getOwner()->
getParentOp();
4222 os <<
"<<UNKNOWN SSA VALUE>>";
4238 OperationPrinter printer(os, state.
getImpl());
4241 printer.printTopLevelOperation(
this);
4243 printer.printFullOpWithIndentAndLoc(
this);
4249 llvm::errs() <<
"\n";
4254 llvm::errs() <<
"\n";
4260 os <<
"<<UNLINKED BLOCK>>\n";
4271 OperationPrinter(os, state.
getImpl()).print(
this);
4280 os <<
"<<UNLINKED BLOCK>>\n";
4287 OperationPrinter printer(os, state.
getImpl());
4288 printer.printBlockName(
this);
4303 if (dimensions.empty())
4306 if (dimensions.empty())
4316 <<
"Failed parsing dimension list.";
4327 <<
"Failed parsing dimension list.";
4329 if (shapeArr.empty()) {
4331 <<
"Failed parsing dimension list. Did you mean an empty list? It "
4332 "must be denoted by \"[]\".";
if(failed(verifyVectorMemoryOp(getOperation(), memrefType, getVectorType()))) return failure()
static void printSymbolReference(StringRef symbolRef, raw_ostream &os)
Print the given string as a symbol reference.
static void printFloatValue(const APFloat &apValue, raw_ostream &os, bool *printedHex=nullptr)
Print a floating point value in a way that the parser will be able to round-trip losslessly.
static StringRef sanitizeIdentifier(StringRef name, SmallString< 16 > &buffer, StringRef allowedPunctChars="$._-")
Sanitize the given name such that it can be used as a valid identifier.
static void printElidedElementsAttr(raw_ostream &os)
static bool isBareIdentifier(StringRef name)
Returns true if the given string can be represented as a bare identifier.
static void printDenseElementsAttrImpl(bool isSplat, ShapedType type, raw_ostream &os, function_ref< void(unsigned)> printEltFn)
static void printKeywordOrString(StringRef keyword, raw_ostream &os)
Print the given string as a keyword, or a quoted and escaped string if it has any special or non-prin...
static bool isDialectSymbolSimpleEnoughForPrettyForm(StringRef symName)
Returns true if the given dialect symbol data is simple enough to print in the pretty form.
static void printDialectSymbol(raw_ostream &os, StringRef symPrefix, StringRef dialectName, StringRef symString)
Print the given dialect symbol to the stream.
static OpPrintingFlags verifyOpAndAdjustFlags(Operation *op, OpPrintingFlags printerFlags)
Verifies the operation and switches to generic op printing if verification fails.
static void printDenseIntElement(const APInt &value, raw_ostream &os, Type type)
Print the integer element of a DenseElementsAttr.
MLIR_CRUNNERUTILS_EXPORT void printString(char const *s)
MLIR_CRUNNERUTILS_EXPORT void printNewline()
static llvm::ManagedStatic< DebugCounterOptions > clOptions
static void visit(Operation *op, DenseSet< Operation * > &visited)
Visits all the pdl.operand(s), pdl.result(s), and pdl.operation(s) connected to the given operation.
LogicalResult initialize(unsigned origNumLoops, ArrayRef< ReassociationIndices > foldedIterationDims)
static Operation * findParent(Operation *op, bool shouldUseLocalScope)
*if copies could not be generated due to yet unimplemented cases *copyInPlacementStart and copyOutPlacementStart in copyPlacementBlock *specify the insertion points where the incoming copies and outgoing should be inserted(the insertion happens right before the *insertion point). Since `begin` can itself be invalidated due to the memref *rewriting done from this method
static std::string diag(const llvm::Value &value)
false
Parses a map_entries map type from a string format back into its numeric value.
static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
static void printRegion(llvm::raw_ostream &os, Region *region, OpPrintingFlags &flags)
Base type for affine expression.
AffineExprKind getKind() const
Return the classification for this type.
void print(raw_ostream &os) const
A multi-dimensional affine map Affine map's are immutable like Type's, and they are uniqued.
unsigned getNumSymbols() const
unsigned getNumDims() const
ArrayRef< AffineExpr > getResults() const
void print(raw_ostream &os) const
This class represents an opaque handle to a dialect resource entry.
Dialect * getDialect() const
Return the dialect that owns the resource.
This class represents a single parsed resource entry.
virtual InFlightDiagnostic emitError() const =0
Emit an error at the location of this entry.
virtual AsmResourceEntryKind getKind() const =0
Return the kind of this value.
virtual FailureOr< AsmResourceBlob > parseAsBlob(BlobAllocatorFn allocator) const =0
Parse the resource entry represented by a binary blob.
virtual ~AsmParsedResourceEntry()
virtual FailureOr< bool > parseAsBool() const =0
Parse the resource entry represented by a boolean.
virtual StringRef getKey() const =0
Return the key of the resource entry.
virtual FailureOr< std::string > parseAsString() const =0
Parse the resource entry represented by a human-readable string.
virtual Builder & getBuilder() const =0
Return a builder which provides useful access to MLIRContext, global objects like types and attribute...
virtual ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())=0
Parse a list of comma-separated items with an optional delimiter.
MLIRContext * getContext() const
virtual InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
virtual ParseResult parseRSquare()=0
Parse a ] token.
virtual ParseResult parseDimensionList(SmallVectorImpl< int64_t > &dimensions, bool allowDynamic=true, bool withTrailingX=true)=0
Parse a dimension list of a tensor or memref type.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
virtual ParseResult parseType(Type &result)=0
Parse a type.
ParseResult parseTypeList(SmallVectorImpl< Type > &result)
Parse a type list.
virtual ParseResult parseOptionalLSquare()=0
Parse a [ token if present.
Impl(raw_ostream &os, AsmStateImpl &state)
BindingStrength
This enum is used to represent the binding strength of the enclosing context that an AffineExprStorag...
void printHexString(StringRef str)
Print a hex string, wrapped with "".
void printDenseArrayAttr(DenseArrayAttr attr)
Print a dense array attribute.
void printDenseElementsAttr(DenseElementsAttr attr, bool allowHex)
Print a dense elements attribute.
unsigned currentIndent
This is the current indentation level for nested structures.
void printAttribute(Attribute attr, AttrTypeElision typeElision=AttrTypeElision::Never)
Print the given attribute or an alias.
void printDimensionList(ArrayRef< int64_t > shape)
void printTypeFirstDenseElementsAttr(DenseElementsAttr attr, DenseElementType denseEltType)
Print a dense elements attribute using the type-first syntax and the DenseElementTypeInterface,...
OpPrintingFlags printerFlags
A set of flags to control the printer's behavior.
void printNewline()
Print a newline and indent the printer to the start of the current operation/attribute/type.
raw_ostream & os
The output stream for the printer.
void printResourceHandle(const AsmDialectResourceHandle &resource)
Print a reference to the given resource that is owned by the given dialect.
LogicalResult printAlias(Attribute attr)
Print the alias for the given attribute, return failure if no alias could be printed.
void printDialectAttribute(Attribute attr)
void interleaveComma(const Container &c, UnaryFunctor eachFn) const
void printDialectType(Type type)
void printLocation(LocationAttr loc, bool allowAlias=false)
Print the given location to the stream.
AsmStateImpl & state
An underlying assembly printer state.
void printAffineMap(AffineMap map)
void printTrailingLocation(Location loc, bool allowAlias=true)
void printAffineExprInternal(AffineExpr expr, BindingStrength enclosingTightness, function_ref< void(unsigned, bool)> printValueName=nullptr)
void decreaseIndent()
Decrease indentation.
static const unsigned indentWidth
The number of spaces used as an indent.
void printEscapedString(StringRef str)
Print an escaped string, wrapped with "".
raw_ostream & getStream()
Returns the output stream of the printer.
void printAffineExpr(AffineExpr expr, function_ref< void(unsigned, bool)> printValueName=nullptr)
void printDenseStringElementsAttr(DenseStringElementsAttr attr)
Print a dense string elements attribute.
void printAttributeImpl(Attribute attr, AttrTypeElision typeElision=AttrTypeElision::Never)
Print the given attribute without considering an alias.
void printAffineConstraint(AffineExpr expr, bool isEq)
AttrTypeElision
This enum describes the different kinds of elision for the type of an attribute when printing it.
@ May
The type may be elided when it matches the default used in the parser (for example i64 is the default...
@ Never
The type must not be elided,.
@ Must
The type must be elided.
LogicalResult pushCyclicPrinting(const void *opaquePointer)
void printIntegerSet(IntegerSet set)
NewLineCounter newLine
A tracker for the number of new lines emitted during printing.
void printOptionalAttrDict(ArrayRef< NamedAttribute > attrs, ArrayRef< StringRef > elidedAttrs={}, bool withKeyword=false)
void printType(Type type)
Print the given type or an alias.
void printLocationInternal(LocationAttr loc, bool pretty=false, bool isTopLevel=false)
void printTypeImpl(Type type)
Print the given type.
void printDenseTypedElementsAttr(DenseTypedElementsAttr attr, bool allowHex)
Print a dense elements attribute in the literal-first syntax.
void printNamedAttribute(NamedAttribute attr)
void increaseIndent()
Increase indentation.
virtual void decreaseIndent()
Decrease indentation.
virtual void printAttributeWithoutType(Attribute attr)
Print the given attribute without its type.
virtual LogicalResult printAlias(Attribute attr)
Print the alias for the given attribute, return failure if no alias could be printed.
virtual void popCyclicPrinting()
Removes the element that was last inserted with a successful call to pushCyclicPrinting.
virtual void increaseIndent()
Increase indentation.
void printFunctionalType(InputRangeT &&inputs, ResultRangeT &&results)
Print the two given type ranges in a functional form.
virtual LogicalResult pushCyclicPrinting(const void *opaquePointer)
Pushes a new attribute or type in the form of a type erased pointer into an internal set.
virtual void printType(Type type)
virtual void printKeywordOrString(StringRef keyword)
Print the given string as a keyword, or a quoted and escaped string if it has any special or non-prin...
virtual void printSymbolName(StringRef symbolRef)
Print the given string as a symbol reference, i.e.
virtual void printString(StringRef string)
Print the given string as a quoted string, escaping any special or non-printable characters in it.
virtual void printAttribute(Attribute attr)
void printDimensionList(ArrayRef< int64_t > shape)
virtual raw_ostream & getStream() const
Return the raw output stream used by this printer.
virtual void printResourceHandle(const AsmDialectResourceHandle &resource)
Print a handle to the given dialect resource.
virtual void printFloat(const APFloat &value)
Print the given floating point value in a stabilized form that can be roundtripped through the IR.
virtual void printNamedAttribute(NamedAttribute attr)
Print the given named attribute.
virtual void printNewline()
Print a newline and indent the printer to the start of the current operation/attribute/type.
This class is used to build resource entries for use by the printer.
virtual void buildString(StringRef key, StringRef data)=0
Build a resource entry represented by the given human-readable string value.
virtual void buildBool(StringRef key, bool data)=0
Build a resource entry represented by the given bool.
virtual ~AsmResourceBuilder()
virtual void buildBlob(StringRef key, ArrayRef< char > data, uint32_t dataAlignment)=0
Build an resource entry represented by the given binary blob data.
This class represents an instance of a resource parser.
StringRef getName() const
Return the name of this parser.
virtual ~AsmResourceParser()
virtual ~AsmResourcePrinter()
static std::unique_ptr< AsmResourcePrinter > fromCallable(StringRef name, CallableT &&printFn)
Return a resource printer implemented via the given callable, whose form should match that of buildRe...
This class provides management for the lifetime of the state used when printing the IR.
DenseMap< Operation *, std::pair< unsigned, unsigned > > LocationMap
This map represents the raw locations of operations within the output stream.
detail::AsmStateImpl & getImpl()
Return an instance of the internal implementation.
void attachResourcePrinter(std::unique_ptr< AsmResourcePrinter > printer)
Attach the given resource printer to the AsmState.
DenseMap< Dialect *, SetVector< AsmDialectResourceHandle > > & getDialectResources() const
Returns a map of dialect resources that were referenced when using this state to print IR.
void attachFallbackResourcePrinter(FallbackAsmResourceMap &map)
Attach resource printers to the AsmState for the fallback resources in the given map.
const OpPrintingFlags & getPrinterFlags() const
Get the printer flags.
AsmState(Operation *op, const OpPrintingFlags &printerFlags=OpPrintingFlags(), LocationMap *locationMap=nullptr, FallbackAsmResourceMap *map=nullptr)
Initialize the asm state at the level of the given operation.
Attributes are known-constant values of operations.
Dialect & getDialect() const
Get the dialect this attribute is registered to.
const void * getAsOpaquePointer() const
Get an opaque pointer to the attribute.
void printStripped(raw_ostream &os) const
Print the attribute without dialect wrapping.
void print(raw_ostream &os, bool elideType=false) const
Print the attribute.
bool hasTrait()
Returns true if the type was registered with a particular trait.
static Attribute getFromOpaquePointer(const void *ptr)
Construct an attribute from the opaque pointer representation.
This class represents an argument of a Block.
Location getLoc() const
Return the location for this argument.
unsigned getArgNumber() const
Returns the number of this argument.
Block represents an ordered list of Operations.
iterator_range< pred_iterator > getPredecessors()
Region * getParent() const
Provide a 'getParent' method for ilist_node_with_parent methods.
Block * getSinglePredecessor()
If this block has exactly one predecessor, return it.
void printAsOperand(raw_ostream &os, bool printType=true)
Print out the name of the block without printing its body.
void print(raw_ostream &os)
BlockArgListType getArguments()
bool isEntryBlock()
Return if this block is the entry block in the parent region.
bool hasNoPredecessors()
Return true if this block has no predecessors.
Operation * getParentOp()
Returns the closest surrounding operation that contains this block.
MLIRContext * getContext() const
An attribute that represents a reference to a dense vector or tensor object.
bool isSplat() const
Returns true if this attribute corresponds to a splat, i.e.
ArrayRef< char > getRawData() const
Return the raw storage data held by this attribute.
ShapedType getType() const
Return the type of this ElementsAttr, guaranteed to be a vector or tensor with static shape.
An attribute that represents a reference to a dense integer vector or tensor object.
This class contains all of the information necessary to report a diagnostic to the DiagnosticEngine.
~DialectAsmParser() override
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
~DialectAsmPrinter() override
A collection of dialect interfaces within a context, for a given concrete interface type.
virtual void printAttribute(Attribute, DialectAsmPrinter &) const
Print an attribute registered to this dialect.
virtual void printType(Type, DialectAsmPrinter &) const
Print a type registered to this dialect.
Attribute getReferencedAttr() const
Returns the referenced attribute.
A fallback map containing external resources not explicitly handled by another parser/printer.
AsmResourceParser & getParserFor(StringRef key)
Return a parser than can be used for parsing entries for the given identifier key.
std::vector< std::unique_ptr< AsmResourcePrinter > > getPrinters()
Build a set of resource printers to print the resources within this map.
A symbol reference with a reference path containing a single element.
An integer set representing a conjunction of one or more affine equalities and inequalities.
unsigned getNumDims() const
unsigned getNumConstraints() const
AffineExpr getConstraint(unsigned idx) const
void print(raw_ostream &os) const
bool isEq(unsigned idx) const
Returns true if the idx^th constraint is an equality, false if it is an inequality.
unsigned getNumSymbols() const
Location objects represent source locations information in MLIR.
T findInstanceOf()
Return an instance of the given location type if one is nested under the current location.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
NamedAttribute represents a combination of a name and an Attribute value.
StringAttr getName() const
Return the name of the attribute.
Attribute getValue() const
Return the value of the attribute.
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
void printFunctionalType(Operation *op)
Print the complete type of an operation in functional form.
Set of flags used to control the behavior of the various IR print methods (e.g.
bool shouldElideElementsAttr(ElementsAttr attr) const
Return if the given ElementsAttr should be elided.
std::optional< int64_t > getLargeElementsAttrLimit() const
Return the size limit for printing large ElementsAttr.
bool shouldUseNameLocAsPrefix() const
Return if the printer should use NameLocs as prefixes when printing SSA IDs.
bool shouldAssumeVerified() const
Return if operation verification should be skipped.
OpPrintingFlags & printLargeElementsAttrWithHex(int64_t largeElementLimit=100)
Enables the printing of large element attributes with a hex string.
bool shouldUseLocalScope() const
Return if the printer should use local scope when dumping the IR.
bool shouldPrintDebugInfoPrettyForm() const
Return if debug information should be printed in the pretty form.
bool shouldPrintElementsAttrWithHex(ElementsAttr attr) const
Return if the given ElementsAttr should be printed as hex string.
bool shouldPrintUniqueSSAIDs() const
Return if printer should use unique SSA IDs.
bool shouldPrintValueUsers() const
Return if the printer should print users of values.
int64_t getLargeElementsAttrHexLimit() const
Return the size limit for printing large ElementsAttr as hex string.
bool shouldPrintGenericOpForm() const
Return if operations should be printed in the generic form.
OpPrintingFlags & elideLargeResourceString(int64_t largeResourceLimit=64)
Enables the elision of large resources strings by omitting them from the dialect_resources section.
bool shouldPrintDebugInfo() const
Return if debug information should be printed.
OpPrintingFlags & elideLargeElementsAttrs(int64_t largeElementLimit=16)
Enables the elision of large elements attributes by printing a lexically valid but otherwise meaningl...
OpPrintingFlags & printNameLocAsPrefix(bool enable=true)
Print SSA IDs using their NameLoc, if provided, as prefix.
OpPrintingFlags & printValueUsers(bool enable=true)
Print users of values as comments.
OpPrintingFlags & enableDebugInfo(bool enable=true, bool prettyForm=false)
Enable or disable printing of debug information (based on enable).
OpPrintingFlags()
Initialize the printing flags with default supplied by the cl::opts above.
bool shouldSkipRegions() const
Return if regions should be skipped.
OpPrintingFlags & printGenericOpForm(bool enable=true)
Always print operations in the generic form.
OpPrintingFlags & useLocalScope(bool enable=true)
Use local scope when printing the operation.
std::optional< uint64_t > getLargeResourceStringLimit() const
Return the size limit in chars for printing large resources.
OpPrintingFlags & assumeVerified(bool enable=true)
Do not verify the operation when using custom operation printers.
OpPrintingFlags & skipRegions(bool skip=true)
Skip printing regions.
OpPrintingFlags & printUniqueSSAIDs(bool enable=true)
Print unique SSA ID numbers for values, block arguments and naming conflicts across all regions.
This is a value defined by a result of an operation.
This class provides the API for ops that are known to be isolated from above.
StringRef getStringRef() const
Return the name of this operation. This always succeeds.
void walkInherentAttrs(Operation *op, InherentAttrVisitor visitor) const
Visit the inherent attributes stored in the properties of op.
void printAssembly(Operation *op, OpAsmPrinter &p, StringRef defaultDialect) const
This hook implements the AsmPrinter for this operation.
void print(raw_ostream &os) const
Operation is the basic unit of execution within MLIR.
Dialect * getDialect()
Return the dialect this operation is associated with, or nullptr if the associated dialect is not loa...
bool use_empty()
Returns true if this operation has no uses.
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
unsigned getNumSuccessors()
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
unsigned getNumRegions()
Returns the number of regions held by this operation.
Location getLoc()
The source location the operation was defined or derived from.
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
std::optional< RegisteredOperationName > getRegisteredInfo()
If this operation has a registered operation description, return it.
DictionaryAttr getRawDictionaryAttrs()
Return all attributes that are not stored as properties.
unsigned getNumOperands()
Attribute getPropertiesAsAttribute()
Return the properties converted to an attribute.
OperationName getName()
The name of an operation is the key identifier for it.
void print(raw_ostream &os, const OpPrintingFlags &flags={})
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
result_type_range getResultTypes()
LLVM_DUMP_METHOD void dumpPretty()
operand_range getOperands()
Returns an iterator on the underlying Value's.
user_range getUsers()
Returns a range of all users.
SuccessorRange getSuccessors()
result_range getResults()
MLIRContext * getContext()
Return the context this operation is associated with.
unsigned getNumResults()
Return the number of results held by this operation.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
BlockArgListType getArguments()
iterator_range< OpIterator > getOps()
unsigned getNumArguments()
BlockArgument getArgument(unsigned i)
Operation * getParentOp()
Return the parent operation this region is attached to.
BlockListType & getBlocks()
This diagnostic handler is a simple RAII class that registers and erases a diagnostic handler on a gi...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
void print(raw_ostream &os) const
Print the current type.
Dialect & getDialect() const
Get the dialect this type is registered to.
bool isSignlessInteger() const
Return true if this is a signless integer type (with the specified width).
static Type getFromOpaquePointer(const void *pointer)
const void * getAsOpaquePointer() const
Methods for supporting PointerLikeTypeTraits.
void walkImmediateSubElements(function_ref< void(Attribute)> walkAttrsFn, function_ref< void(Type)> walkTypesFn) const
Walk all of the immediately nested sub-attributes and sub-types.
bool isUnsignedInteger() const
Return true if this is an unsigned integer type (with the specified width).
bool isIntOrIndex() const
Return true if this is an integer (of any signedness) or an index type.
bool isInteger() const
Return true if this is an integer type (with the specified width).
unsigned getIntOrFloatBitWidth() const
Return the bit width of an integer or a float type, assert failure on other types.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
bool use_empty() const
Returns true if this value has no uses.
void print(raw_ostream &os) const
Type getType() const
Return the type of this value.
void printAsOperand(raw_ostream &os, AsmState &state) const
Print this value as if it were an operand.
user_range getUsers() const
Location getLoc() const
Return the location of this value.
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
SSANameState & getSSANameState()
Get the state used for SSA names.
void registerOperationLocation(Operation *op, unsigned line, unsigned col)
Register the location, line and column, within the buffer that the given operation was printed at.
auto getResourcePrinters()
Return the non-dialect resource printers.
LogicalResult pushCyclicPrinting(const void *opaquePointer)
AliasState & getAliasState()
Get the state used for aliases.
void initializeAliases(Operation *op)
Initialize the alias state to enable the printing of aliases.
const OpPrintingFlags & getPrinterFlags() const
Get the printer flags.
DenseMap< Dialect *, SetVector< AsmDialectResourceHandle > > & getDialectResources()
Return the referenced dialect resources within the printer.
AsmStateImpl(Operation *op, const OpPrintingFlags &printerFlags, AsmState::LocationMap *locationMap)
AsmStateImpl(MLIRContext *ctx, const OpPrintingFlags &printerFlags, AsmState::LocationMap *locationMap)
DistinctState & getDistinctState()
Get the state used for distinct attribute identifiers.
DialectInterfaceCollection< OpAsmDialectInterface > & getDialectInterfaces()
Return the dialects within the context that implement OpAsmDialectInterface.
static DenseArrayAttrImpl get(MLIRContext *context, ArrayRef< int64_t > content)
detail::StorageUserTrait::IsMutable< ConcreteType > IsMutable
This trait is used to determine if an attribute is mutable or not.
void printType(Type type, AsmPrinter &printer)
Prints an LLVM Dialect type.
static void printDimensionList(raw_ostream &stream, Range &&shape)
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
bool operator<(const Fraction &x, const Fraction &y)
Include the generated interface declarations.
detail::DenseArrayAttrImpl< int64_t > DenseI64ArrayAttr
ParseResult parseDimensionList(OpAsmParser &parser, DenseI64ArrayAttr &dimensions)
StringRef toString(AsmResourceEntryKind kind)
raw_ostream & operator<<(raw_ostream &os, const AliasResult &result)
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
void printDimensionList(OpAsmPrinter &printer, Operation *op, ArrayRef< int64_t > dimensions)
@ CeilDiv
RHS of ceildiv is always a constant or a symbolic expression.
@ Mul
RHS of mul is always a constant or a symbolic expression.
@ Mod
RHS of mod is always a constant or a symbolic expression with a positive value.
@ DimId
Dimensional identifier.
@ FloorDiv
RHS of floordiv is always a constant or a symbolic expression.
@ Constant
Constant integer.
@ SymbolId
Symbolic identifier.
llvm::SetVector< T, Vector, Set, N > SetVector
std::conditional_t< std::is_floating_point_v< T >, std::complex< T >, NonFloatComplex< T > > Complex
void registerAsmPrinterCLOptions()
Register a set of useful command-line options that can be used to configure various flags within the ...
llvm::TypeSwitch< T, ResultT > TypeSwitch
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
AsmResourceEntryKind
This enum represents the different kinds of resource values.
@ Blob
A blob of data with an accompanying alignment.
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
llvm::function_ref< Fn > function_ref
Represents a range (offset, size, and stride) where each element of the triple may be dynamic or stat...