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()
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);
537 function_ref<
void(
unsigned,
bool)> printValueName =
nullptr);
567 SymbolAlias(StringRef name, uint32_t suffixIndex,
bool isType,
569 : name(name), suffixIndex(suffixIndex), isType(isType),
570 isDeferrable(isDeferrable) {}
574 os << (isType ?
"!" :
"#") << name;
576 if (isdigit(name.back()))
583 bool isTypeAlias()
const {
return isType; }
586 bool canBeDeferred()
const {
return isDeferrable; }
592 uint32_t suffixIndex : 30;
596 bool isDeferrable : 1;
600 bool isPrinted =
false;
606class AliasInitializer {
609 DialectInterfaceCollection<OpAsmDialectInterface> &interfaces,
610 llvm::BumpPtrAllocator &aliasAllocator)
611 : interfaces(interfaces), aliasAllocator(aliasAllocator),
612 aliasOS(aliasBuffer) {}
614 void initialize(Operation *op,
const OpPrintingFlags &printerFlags,
615 llvm::MapVector<const void *, SymbolAlias> &attrTypeToAlias);
623 std::pair<size_t, size_t>
visit(Attribute attr,
bool canBeDeferred =
false,
624 bool elideType =
false) {
625 return visitImpl(attr, aliases, canBeDeferred, elideType);
632 std::pair<size_t, size_t>
visit(Type type,
bool canBeDeferred =
false) {
633 return visitImpl(type, aliases, canBeDeferred);
637 struct InProgressAliasInfo {
638 InProgressAliasInfo()
639 : aliasDepth(0), isType(
false), canBeDeferred(
false) {}
640 InProgressAliasInfo(StringRef alias)
641 : alias(alias), aliasDepth(1), isType(
false), canBeDeferred(
false) {}
645 if (aliasDepth !=
rhs.aliasDepth)
646 return aliasDepth <
rhs.aliasDepth;
647 if (isType !=
rhs.isType)
649 return alias <
rhs.alias;
654 std::optional<StringRef> alias;
657 unsigned aliasDepth : 30;
661 bool canBeDeferred : 1;
663 SmallVector<size_t> childIndices;
671 template <
typename T,
typename... PrintArgs>
672 std::pair<size_t, size_t>
674 llvm::MapVector<const void *, InProgressAliasInfo> &aliases,
675 bool canBeDeferred, PrintArgs &&...
printArgs);
678 void markAliasNonDeferrable(
size_t aliasIndex);
682 template <
typename T>
683 void generateAlias(T symbol, InProgressAliasInfo &alias,
bool canBeDeferred);
688 uniqueAliasNameIndex(StringRef alias, llvm::StringMap<unsigned> &nameCounts,
689 llvm::StringSet<llvm::BumpPtrAllocator &> &usedAliases);
693 static void initializeAliases(
694 llvm::MapVector<const void *, InProgressAliasInfo> &visitedSymbols,
695 llvm::MapVector<const void *, SymbolAlias> &symbolToAlias);
698 DialectInterfaceCollection<OpAsmDialectInterface> &interfaces;
701 llvm::BumpPtrAllocator &aliasAllocator;
704 llvm::MapVector<const void *, InProgressAliasInfo> aliases;
707 SmallString<32> aliasBuffer;
708 llvm::raw_svector_ostream aliasOS;
716class DummyAliasOperationPrinter :
private OpAsmPrinter {
718 explicit DummyAliasOperationPrinter(
const OpPrintingFlags &printerFlags,
719 AliasInitializer &initializer)
720 : printerFlags(printerFlags), initializer(initializer) {}
724 void printCustomOrGenericOp(Operation *op)
override {
726 if (printerFlags.shouldPrintDebugInfo())
727 initializer.visit(op->
getLoc(),
true);
730 if (!printerFlags.shouldPrintGenericOpForm()) {
741 void printGenericOp(Operation *op,
bool printOpName =
true)
override {
743 if (!printerFlags.shouldSkipRegions()) {
756 for (
const NamedAttribute &attr : op->
getAttrs())
757 printAttribute(attr.getValue());
763 void print(
Block *block,
bool printBlockArgs =
true,
764 bool printBlockTerminator =
true) {
767 if (printBlockArgs) {
772 if (printerFlags.shouldPrintDebugInfo())
774 initializer.visit(arg.getLoc(),
false);
782 auto range = llvm::make_range(
784 std::prev(block->
end(),
785 (!hasTerminator || printBlockTerminator) ? 0 : 1));
786 for (Operation &op : range)
787 printCustomOrGenericOp(&op);
791 void printRegion(Region ®ion,
bool printEntryBlockArgs,
792 bool printBlockTerminators,
793 bool printEmptyBlock =
false)
override {
796 if (printerFlags.shouldSkipRegions()) {
801 auto *entryBlock = ®ion.
front();
802 print(entryBlock, printEntryBlockArgs, printBlockTerminators);
803 for (
Block &
b : llvm::drop_begin(region, 1))
807 void printRegionArgument(BlockArgument arg, ArrayRef<NamedAttribute> argAttrs,
808 bool omitType)
override {
811 if (printerFlags.shouldPrintDebugInfo())
813 initializer.visit(arg.
getLoc(),
false);
817 void printType(Type type)
override { initializer.visit(type); }
820 void printAttribute(Attribute attr)
override { initializer.visit(attr); }
821 void printAttributeWithoutType(Attribute attr)
override {
822 printAttribute(attr);
824 void printNamedAttribute(NamedAttribute attr)
override {
828 LogicalResult printAlias(Attribute attr)
override {
829 initializer.visit(attr);
832 LogicalResult printAlias(Type type)
override {
833 initializer.visit(type);
838 void printOptionalLocationSpecifier(Location loc)
override {
844 void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
845 ArrayRef<StringRef> elidedAttrs = {})
override {
848 if (elidedAttrs.empty()) {
849 for (
const NamedAttribute &attr : attrs)
850 printAttribute(attr.getValue());
853 llvm::SmallDenseSet<StringRef> elidedAttrsSet(elidedAttrs.begin(),
855 for (
const NamedAttribute &attr : attrs)
856 if (!elidedAttrsSet.contains(attr.getName().strref()))
857 printAttribute(attr.getValue());
859 void printOptionalAttrDictWithKeyword(
860 ArrayRef<NamedAttribute> attrs,
861 ArrayRef<StringRef> elidedAttrs = {})
override {
862 printOptionalAttrDict(attrs, elidedAttrs);
867 raw_ostream &getStream()
const override {
return os; }
871 void printFloat(
const APFloat &)
override {}
872 void printAffineMapOfSSAIds(AffineMapAttr,
ValueRange)
override {}
875 void increaseIndent()
override {}
876 void decreaseIndent()
override {}
877 void printOperand(Value)
override {}
878 void printOperand(Value, raw_ostream &os)
override {
886 void printResourceHandle(
const AsmDialectResourceHandle &)
override {}
887 void printSymbolName(StringRef)
override {}
888 void printSuccessor(
Block *)
override {}
890 void shadowRegionArgs(Region &,
ValueRange)
override {}
893 const OpPrintingFlags &printerFlags;
896 AliasInitializer &initializer;
899 mutable llvm::raw_null_ostream os;
904 explicit DummyAliasDialectAsmPrinter(AliasInitializer &initializer,
906 SmallVectorImpl<size_t> &childIndices)
907 : initializer(initializer), canBeDeferred(canBeDeferred),
908 childIndices(childIndices) {}
913 template <
typename T,
typename... PrintArgs>
914 size_t printAndVisitNestedAliases(T value, PrintArgs &&...
printArgs) {
915 printAndVisitNestedAliasesImpl(value,
printArgs...);
916 return maxAliasDepth;
922 void printAndVisitNestedAliasesImpl(Attribute attr,
bool elideType) {
923 if (!isa<BuiltinDialect>(attr.
getDialect())) {
927 }
else if (llvm::isa<AffineMapAttr, DenseArrayAttr, FloatAttr, IntegerAttr,
928 IntegerSetAttr, UnitAttr>(attr)) {
930 }
else if (
auto distinctAttr = dyn_cast<DistinctAttr>(attr)) {
931 printAttribute(distinctAttr.getReferencedAttr());
932 }
else if (
auto dictAttr = dyn_cast<DictionaryAttr>(attr)) {
933 for (
const NamedAttribute &nestedAttr : dictAttr.getValue()) {
934 printAttribute(nestedAttr.getName());
935 printAttribute(nestedAttr.getValue());
937 }
else if (
auto arrayAttr = dyn_cast<ArrayAttr>(attr)) {
938 for (Attribute nestedAttr : arrayAttr.getValue())
939 printAttribute(nestedAttr);
940 }
else if (
auto typeAttr = dyn_cast<TypeAttr>(attr)) {
942 }
else if (
auto locAttr = dyn_cast<OpaqueLoc>(attr)) {
943 printAttribute(locAttr.getFallbackLocation());
944 }
else if (
auto locAttr = dyn_cast<NameLoc>(attr)) {
945 if (!isa<UnknownLoc>(locAttr.getChildLoc()))
946 printAttribute(locAttr.getChildLoc());
947 }
else if (
auto locAttr = dyn_cast<CallSiteLoc>(attr)) {
948 printAttribute(locAttr.getCallee());
949 printAttribute(locAttr.getCaller());
950 }
else if (
auto locAttr = dyn_cast<FusedLoc>(attr)) {
951 if (Attribute metadata = locAttr.getMetadata())
952 printAttribute(metadata);
953 for (Location nestedLoc : locAttr.getLocations())
954 printAttribute(nestedLoc);
959 if (
auto typedAttr = llvm::dyn_cast<TypedAttr>(attr)) {
960 Type attrType = typedAttr.getType();
961 if (!llvm::isa<NoneType>(attrType))
966 void printAndVisitNestedAliasesImpl(Type type) {
971 if (
auto memrefTy = llvm::dyn_cast<MemRefType>(type)) {
973 MemRefLayoutAttrInterface layout = memrefTy.getLayout();
974 if (!llvm::isa<AffineMapAttr>(layout) || !layout.isIdentity())
975 printAttribute(memrefTy.getLayout());
976 if (memrefTy.getMemorySpace())
977 printAttribute(memrefTy.getMemorySpace());
982 auto visitFn = [&](
auto element) {
984 (void)printAlias(element);
991 recordAliasResult(initializer.visit(type, canBeDeferred));
995 void printAttribute(Attribute attr)
override {
996 recordAliasResult(initializer.visit(attr, canBeDeferred));
998 void printAttributeWithoutType(Attribute attr)
override {
1000 initializer.visit(attr, canBeDeferred,
true));
1002 void printNamedAttribute(NamedAttribute attr)
override {
1006 LogicalResult printAlias(Attribute attr)
override {
1007 printAttribute(attr);
1010 LogicalResult printAlias(Type type)
override {
1016 void recordAliasResult(std::pair<size_t, size_t> aliasDepthAndIndex) {
1017 childIndices.push_back(aliasDepthAndIndex.second);
1018 if (aliasDepthAndIndex.first > maxAliasDepth)
1019 maxAliasDepth = aliasDepthAndIndex.first;
1024 raw_ostream &getStream()
const override {
return os; }
1029 void increaseIndent()
override {}
1030 void decreaseIndent()
override {}
1031 void printFloat(
const APFloat &)
override {}
1034 void printSymbolName(StringRef)
override {}
1035 void printResourceHandle(
const AsmDialectResourceHandle &)
override {}
1037 LogicalResult pushCyclicPrinting(
const void *opaquePointer)
override {
1038 return success(cyclicPrintingStack.insert(opaquePointer));
1041 void popCyclicPrinting()
override { cyclicPrintingStack.pop_back(); }
1045 SetVector<const void *> cyclicPrintingStack;
1048 AliasInitializer &initializer;
1054 SmallVectorImpl<size_t> &childIndices;
1057 size_t maxAliasDepth = 0;
1060 mutable llvm::raw_null_ostream os;
1068 StringRef allowedPunctChars =
"$._-") {
1069 assert(!name.empty() &&
"Shouldn't have an empty name here");
1071 auto validChar = [&](
char ch) {
1072 return llvm::isAlnum(ch) || allowedPunctChars.contains(ch);
1075 auto copyNameToBuffer = [&] {
1076 for (
char ch : name) {
1078 buffer.push_back(ch);
1080 buffer.push_back(
'_');
1082 buffer.append(llvm::utohexstr((
unsigned char)ch));
1089 if (isdigit(name[0]) || (!validChar(name[0]) && name[0] !=
' ')) {
1090 buffer.push_back(
'_');
1096 for (
char ch : name) {
1097 if (!validChar(ch)) {
1107unsigned AliasInitializer::uniqueAliasNameIndex(
1108 StringRef alias, llvm::StringMap<unsigned> &nameCounts,
1109 llvm::StringSet<llvm::BumpPtrAllocator &> &usedAliases) {
1110 if (!usedAliases.count(alias)) {
1111 usedAliases.insert(alias);
1117 size_t probeSize = probeAlias.size();
1119 if (isdigit(alias.back())) {
1120 probeAlias.push_back(
'_');
1124 if (nameCounts[probeAlias] == 0)
1125 nameCounts[probeAlias] = 1;
1129 unsigned nameIndex = nameCounts[probeAlias]++;
1130 probeAlias += llvm::utostr(nameIndex);
1131 if (!usedAliases.count(probeAlias)) {
1132 usedAliases.insert(probeAlias);
1136 probeAlias.resize(probeSize);
1142void AliasInitializer::initializeAliases(
1143 llvm::MapVector<const void *, InProgressAliasInfo> &visitedSymbols,
1144 llvm::MapVector<const void *, SymbolAlias> &symbolToAlias) {
1146 unprocessedAliases = visitedSymbols.takeVector();
1147 llvm::stable_sort(unprocessedAliases, llvm::less_second());
1151 llvm::BumpPtrAllocator usedAliasAllocator;
1152 llvm::StringSet<llvm::BumpPtrAllocator &> usedAliases(usedAliasAllocator);
1154 llvm::StringMap<unsigned> nameCounts;
1155 for (
auto &[symbol, aliasInfo] : unprocessedAliases) {
1156 if (!aliasInfo.alias)
1158 StringRef alias = *aliasInfo.alias;
1159 unsigned nameIndex = uniqueAliasNameIndex(alias, nameCounts, usedAliases);
1160 symbolToAlias.insert(
1161 {symbol, SymbolAlias(alias, nameIndex, aliasInfo.isType,
1162 aliasInfo.canBeDeferred)});
1166void AliasInitializer::initialize(
1168 llvm::MapVector<const void *, SymbolAlias> &attrTypeToAlias) {
1172 DummyAliasOperationPrinter aliasPrinter(printerFlags, *
this);
1173 aliasPrinter.printCustomOrGenericOp(op);
1176 initializeAliases(aliases, attrTypeToAlias);
1179template <
typename T,
typename... PrintArgs>
1180std::pair<size_t, size_t> AliasInitializer::visitImpl(
1181 T value, llvm::MapVector<const void *, InProgressAliasInfo> &aliases,
1182 bool canBeDeferred, PrintArgs &&...
printArgs) {
1183 auto [it,
inserted] = aliases.try_emplace(value.getAsOpaquePointer());
1184 size_t aliasIndex = std::distance(aliases.begin(), it);
1188 markAliasNonDeferrable(aliasIndex);
1189 return {
static_cast<size_t>(it->second.aliasDepth), aliasIndex};
1193 generateAlias(value, it->second, canBeDeferred);
1194 it->second.isType = std::is_base_of_v<Type, T>;
1195 it->second.canBeDeferred = canBeDeferred;
1199 DummyAliasDialectAsmPrinter printer(*
this, canBeDeferred, childAliases);
1200 size_t maxAliasDepth =
1201 printer.printAndVisitNestedAliases(value,
printArgs...);
1204 it = std::next(aliases.begin(), aliasIndex);
1207 it->second.childIndices = std::move(childAliases);
1209 it->second.aliasDepth = maxAliasDepth + 1;
1212 return {(size_t)it->second.aliasDepth, aliasIndex};
1215void AliasInitializer::markAliasNonDeferrable(
size_t aliasIndex) {
1216 auto *it = std::next(aliases.begin(), aliasIndex);
1220 if (!it->second.canBeDeferred)
1223 it->second.canBeDeferred =
false;
1226 for (
size_t childIndex : it->second.childIndices)
1227 markAliasNonDeferrable(childIndex);
1230template <
typename T>
1231void AliasInitializer::generateAlias(T symbol, InProgressAliasInfo &alias,
1232 bool canBeDeferred) {
1236 OpAsmDialectInterface::AliasResult::NoAlias;
1237 using InterfaceT = std::conditional_t<std::is_base_of_v<Attribute, T>,
1238 OpAsmAttrInterface, OpAsmTypeInterface>;
1239 if (
auto symbolInterface = dyn_cast<InterfaceT>(symbol)) {
1240 symbolInterfaceResult = symbolInterface.getAlias(aliasOS);
1241 if (symbolInterfaceResult != OpAsmDialectInterface::AliasResult::NoAlias) {
1242 nameBuffer = std::move(aliasBuffer);
1243 assert(!nameBuffer.empty() &&
"expected valid alias name");
1247 if (symbolInterfaceResult != OpAsmDialectInterface::AliasResult::FinalAlias) {
1248 for (
const auto &interface : interfaces) {
1250 interface.getAlias(symbol, aliasOS);
1251 if (
result == OpAsmDialectInterface::AliasResult::NoAlias)
1253 nameBuffer = std::move(aliasBuffer);
1254 assert(!nameBuffer.empty() &&
"expected valid alias name");
1255 if (
result == OpAsmDialectInterface::AliasResult::FinalAlias)
1260 if (nameBuffer.empty())
1266 name = name.copy(aliasAllocator);
1267 alias = InProgressAliasInfo(name);
1280 initialize(Operation *op,
const OpPrintingFlags &printerFlags,
1281 DialectInterfaceCollection<OpAsmDialectInterface> &interfaces);
1285 LogicalResult getAlias(Attribute attr, raw_ostream &os)
const;
1289 LogicalResult getAlias(Type ty, raw_ostream &os)
const;
1293 void printNonDeferredAliases(AsmPrinter::Impl &p, NewLineCounter &newLine) {
1294 printAliases(p, newLine,
false);
1298 void printDeferredAliases(AsmPrinter::Impl &p, NewLineCounter &newLine) {
1299 printAliases(p, newLine,
true);
1305 void printAliases(AsmPrinter::Impl &p, NewLineCounter &newLine,
1309 llvm::MapVector<const void *, SymbolAlias> attrTypeToAlias;
1312 llvm::BumpPtrAllocator aliasAllocator;
1316void AliasState::initialize(
1319 AliasInitializer initializer(interfaces, aliasAllocator);
1320 initializer.initialize(op, printerFlags, attrTypeToAlias);
1325 if (it == attrTypeToAlias.end())
1327 it->second.print(os);
1333 if (it == attrTypeToAlias.end())
1335 if (!it->second.isPrinted)
1338 it->second.print(os);
1344 auto filterFn = [=](
const auto &aliasIt) {
1345 return aliasIt.second.canBeDeferred() == isDeferred;
1347 for (
auto &[opaqueSymbol, alias] :
1348 llvm::make_filter_range(attrTypeToAlias, filterFn)) {
1352 if (alias.isTypeAlias()) {
1355 alias.isPrinted =
true;
1385 enum :
unsigned { NameSentinel = ~0U };
1387 SSANameState(Operation *op,
const OpPrintingFlags &printerFlags);
1388 SSANameState() =
default;
1393 void printValueID(Value value,
bool printResultNo, raw_ostream &stream)
const;
1396 void printOperationID(Operation *op, raw_ostream &stream)
const;
1400 ArrayRef<int> getOpResultGroups(Operation *op);
1403 BlockInfo getBlockInfo(
Block *block);
1408 void shadowRegionArgs(Region ®ion,
ValueRange namesToUse);
1412 void numberValuesInRegion(Region ®ion);
1413 void numberValuesInBlock(
Block &block);
1414 void numberValuesInOp(Operation &op);
1420 void getResultIDAndNumber(OpResult
result, Value &lookupValue,
1421 std::optional<int> &lookupResultNo)
const;
1424 void setValueName(Value value, StringRef name);
1428 StringRef uniqueValueName(StringRef name);
1451 llvm::ScopedHashTable<StringRef, char> usedNames;
1452 llvm::BumpPtrAllocator usedNameAllocator;
1455 unsigned nextValueID = 0;
1457 unsigned nextArgumentID = 0;
1459 unsigned nextConflictID = 0;
1463 OpPrintingFlags printerFlags;
1468 : printerFlags(printerFlags) {
1469 llvm::SaveAndRestore valueIDSaver(nextValueID);
1470 llvm::SaveAndRestore argumentIDSaver(nextArgumentID);
1471 llvm::SaveAndRestore conflictIDSaver(nextConflictID);
1476 using UsedNamesScopeTy = llvm::ScopedHashTable<StringRef, char>::ScopeTy;
1477 using NamingContext =
1478 std::tuple<Region *, unsigned, unsigned, unsigned, UsedNamesScopeTy *>;
1481 llvm::BumpPtrAllocator allocator;
1484 auto *topLevelNamesScope =
1485 new (allocator.Allocate<UsedNamesScopeTy>()) UsedNamesScopeTy(usedNames);
1489 nameContext.push_back(std::make_tuple(®ion, nextValueID, nextArgumentID,
1490 nextConflictID, topLevelNamesScope));
1492 numberValuesInOp(*op);
1494 while (!nameContext.empty()) {
1496 UsedNamesScopeTy *parentScope;
1500 std::tie(region, std::ignore, std::ignore, std::ignore, parentScope) =
1501 nameContext.pop_back_val();
1503 std::tie(region, nextValueID, nextArgumentID, nextConflictID,
1504 parentScope) = nameContext.pop_back_val();
1508 while (usedNames.getCurScope() != parentScope) {
1509 usedNames.getCurScope()->~UsedNamesScopeTy();
1510 assert((usedNames.getCurScope() !=
nullptr || parentScope ==
nullptr) &&
1511 "top level parentScope must be a nullptr");
1515 auto *curNamesScope =
new (allocator.Allocate<UsedNamesScopeTy>())
1516 UsedNamesScopeTy(usedNames);
1518 numberValuesInRegion(*region);
1522 nameContext.push_back(std::make_tuple(®ion, nextValueID,
1523 nextArgumentID, nextConflictID,
1528 while (usedNames.getCurScope() !=
nullptr)
1529 usedNames.getCurScope()->~UsedNamesScopeTy();
1532void SSANameState::printValueID(
Value value,
bool printResultNo,
1535 stream <<
"<<NULL VALUE>>";
1539 std::optional<int> resultNo;
1540 auto lookupValue = value;
1544 if (OpResult
result = dyn_cast<OpResult>(value))
1545 getResultIDAndNumber(
result, lookupValue, resultNo);
1547 auto it = valueIDs.find(lookupValue);
1548 if (it == valueIDs.end()) {
1549 stream <<
"<<UNKNOWN SSA VALUE>>";
1554 if (it->second != NameSentinel) {
1555 stream << it->second;
1557 auto nameIt = valueNames.find(lookupValue);
1558 assert(nameIt != valueNames.end() &&
"Didn't have a name entry?");
1559 stream << nameIt->second;
1562 if (resultNo && printResultNo)
1563 stream <<
'#' << *resultNo;
1566void SSANameState::printOperationID(Operation *op, raw_ostream &stream)
const {
1567 auto it = operationIDs.find(op);
1568 if (it == operationIDs.end()) {
1569 stream <<
"<<UNKNOWN OPERATION>>";
1571 stream <<
'%' << it->second;
1575ArrayRef<int> SSANameState::getOpResultGroups(Operation *op) {
1576 auto it = opResultGroups.find(op);
1577 return it == opResultGroups.end() ? ArrayRef<int>() : it->second;
1580BlockInfo SSANameState::getBlockInfo(
Block *block) {
1581 auto it = blockNames.find(block);
1582 BlockInfo invalidBlock{-1,
"INVALIDBLOCK"};
1583 return it != blockNames.end() ? it->second : invalidBlock;
1586void SSANameState::shadowRegionArgs(Region ®ion,
ValueRange namesToUse) {
1587 assert(!region.
empty() &&
"cannot shadow arguments of an empty region");
1589 "incorrect number of names passed in");
1591 "only KnownIsolatedFromAbove ops can shadow names");
1593 SmallVector<char, 16> nameStr;
1594 for (
unsigned i = 0, e = namesToUse.size(); i != e; ++i) {
1595 auto nameToUse = namesToUse[i];
1596 if (nameToUse ==
nullptr)
1601 llvm::raw_svector_ostream nameStream(nameStr);
1602 printValueID(nameToUse,
true, nameStream);
1605 assert(valueIDs[nameToReplace] == NameSentinel);
1608 auto name = StringRef(nameStream.str()).drop_front();
1611 valueNames[nameToReplace] = name.copy(usedNameAllocator);
1617StringRef maybeGetValueNameFromLoc(Value value, StringRef name) {
1619 return maybeNameLoc.getName();
1624void SSANameState::numberValuesInRegion(Region ®ion) {
1626 bool opAsmOpInterfaceUsed =
false;
1627 auto setBlockArgNameFn = [&](Value arg, StringRef name) {
1628 assert(!valueIDs.count(arg) &&
"arg numbered multiple times");
1629 assert(llvm::cast<BlockArgument>(arg).getOwner()->getParent() == ®ion &&
1630 "arg not defined in current region");
1631 opAsmOpInterfaceUsed =
true;
1633 name = maybeGetValueNameFromLoc(arg, name);
1634 setValueName(arg, name);
1639 if (
auto asmInterface = dyn_cast<OpAsmOpInterface>(op))
1640 asmInterface.getAsmBlockArgumentNames(region, setBlockArgNameFn);
1642 if (!opAsmOpInterfaceUsed) {
1644 if (
auto interface = dyn_cast<OpAsmTypeInterface>(arg.
getType())) {
1645 interface.getAsmName(
1646 [&](StringRef name) { setBlockArgNameFn(arg, name); });
1654 unsigned nextBlockID = 0;
1655 for (
auto &block : region) {
1658 auto blockInfoIt = blockNames.insert({&block, {-1,
""}});
1659 if (blockInfoIt.second) {
1663 llvm::raw_string_ostream(name) <<
"^bb" << nextBlockID;
1664 blockInfoIt.first->second.name = StringRef(name).copy(usedNameAllocator);
1666 blockInfoIt.first->second.ordering = nextBlockID++;
1668 numberValuesInBlock(block);
1672void SSANameState::numberValuesInBlock(
Block &block) {
1676 SmallString<32> specialNameBuffer(isEntryBlock ?
"arg" :
"");
1677 llvm::raw_svector_ostream specialName(specialNameBuffer);
1679 if (valueIDs.count(arg))
1682 specialNameBuffer.resize(strlen(
"arg"));
1683 specialName << nextArgumentID++;
1685 StringRef specialNameStr = specialName.str();
1687 specialNameStr = maybeGetValueNameFromLoc(arg, specialNameStr);
1688 setValueName(arg, specialNameStr);
1692 for (
auto &op : block)
1693 numberValuesInOp(op);
1696void SSANameState::numberValuesInOp(Operation &op) {
1698 SmallVector<int, 2> resultGroups(1, 0);
1700 bool opAsmOpInterfaceUsed =
false;
1701 auto setResultNameFn = [&](Value
result, StringRef name) {
1702 assert(!valueIDs.count(
result) &&
"result numbered multiple times");
1703 assert(
result.getDefiningOp() == &op &&
"result not defined by 'op'");
1704 opAsmOpInterfaceUsed =
true;
1706 name = maybeGetValueNameFromLoc(
result, name);
1707 setValueName(
result, name);
1710 if (
int resultNo = llvm::cast<OpResult>(
result).getResultNumber())
1711 resultGroups.push_back(resultNo);
1714 auto setBlockNameFn = [&](
Block *block, StringRef name) {
1716 "getAsmBlockArgumentNames callback invoked on a block not directly "
1717 "nested under the current operation");
1718 assert(!blockNames.count(block) &&
"block numbered multiple times");
1719 SmallString<16> tmpBuffer{
"^"};
1721 if (name.data() != tmpBuffer.data()) {
1722 tmpBuffer.append(name);
1723 name = tmpBuffer.str();
1725 name = name.copy(usedNameAllocator);
1726 blockNames[block] = {-1, name};
1730 if (OpAsmOpInterface asmInterface = dyn_cast<OpAsmOpInterface>(&op)) {
1731 asmInterface.getAsmBlockNames(setBlockNameFn);
1732 asmInterface.getAsmResultNames(setResultNameFn);
1734 if (!opAsmOpInterfaceUsed) {
1737 bool allHaveOpAsmTypeInterface =
1739 return isa<OpAsmTypeInterface>(type);
1741 if (allHaveOpAsmTypeInterface) {
1743 auto interface = cast<OpAsmTypeInterface>(
result.
getType());
1744 interface.getAsmName(
1745 [&](StringRef name) { setResultNameFn(
result, name); });
1752 if (numResults == 0) {
1755 if (operationIDs.try_emplace(&op, nextValueID).second)
1764 setValueName(resultBegin, nameLoc.getName());
1769 if (valueIDs.try_emplace(resultBegin, nextValueID).second)
1773 if (resultGroups.size() != 1) {
1774 llvm::array_pod_sort(resultGroups.begin(), resultGroups.end());
1775 opResultGroups.try_emplace(&op, std::move(resultGroups));
1779void SSANameState::getResultIDAndNumber(
1780 OpResult
result, Value &lookupValue,
1781 std::optional<int> &lookupResultNo)
const {
1782 Operation *owner =
result.getOwner();
1785 int resultNo =
result.getResultNumber();
1789 auto resultGroupIt = opResultGroups.find(owner);
1790 if (resultGroupIt == opResultGroups.end()) {
1792 lookupResultNo = resultNo;
1798 ArrayRef<int> resultGroups = resultGroupIt->second;
1799 const auto *it = llvm::upper_bound(resultGroups, resultNo);
1800 int groupResultNo = 0, groupSize = 0;
1803 if (it == resultGroups.end()) {
1804 groupResultNo = resultGroups.back();
1805 groupSize =
static_cast<int>(owner->
getNumResults()) - resultGroups.back();
1808 groupResultNo = *std::prev(it);
1809 groupSize = *it - groupResultNo;
1814 lookupResultNo = resultNo - groupResultNo;
1815 lookupValue = owner->
getResult(groupResultNo);
1818void SSANameState::setValueName(Value value, StringRef name) {
1821 valueIDs[value] = nextValueID++;
1825 valueIDs[value] = NameSentinel;
1826 valueNames[value] = uniqueValueName(name);
1829StringRef SSANameState::uniqueValueName(StringRef name) {
1830 SmallString<16> tmpBuffer;
1834 if (!usedNames.count(name)) {
1835 name = name.copy(usedNameAllocator);
1840 SmallString<64> probeName(name);
1841 probeName.push_back(
'_');
1843 probeName += llvm::utostr(nextConflictID++);
1844 if (!usedNames.count(probeName)) {
1845 name = probeName.str().copy(usedNameAllocator);
1848 probeName.resize(name.size() + 1);
1852 usedNames.insert(name,
char());
1862class DistinctState {
1865 uint64_t getId(DistinctAttr distinctAttr);
1868 uint64_t distinctCounter = 0;
1873uint64_t DistinctState::getId(DistinctAttr distinctAttr) {
1875 distinctAttrMap.try_emplace(distinctAttr, distinctCounter);
1878 return it->getSecond();
1899 llvm_unreachable(
"unknown AsmResourceEntryKind");
1903 std::unique_ptr<ResourceCollection> &collection = keyToResources[key.str()];
1905 collection = std::make_unique<ResourceCollection>(key);
1909std::vector<std::unique_ptr<AsmResourcePrinter>>
1911 std::vector<std::unique_ptr<AsmResourcePrinter>> printers;
1912 for (
auto &it : keyToResources) {
1913 ResourceCollection *collection = it.second.get();
1915 return collection->buildResources(op, builder);
1917 printers.emplace_back(
1923LogicalResult FallbackAsmResourceMap::ResourceCollection::parseResource(
1927 FailureOr<AsmResourceBlob> blob = entry.
parseAsBlob();
1930 resources.emplace_back(entry.
getKey(), std::move(*blob));
1937 resources.emplace_back(entry.
getKey(), *value);
1940 case AsmResourceEntryKind::String: {
1944 resources.emplace_back(entry.
getKey(), std::move(*str));
1951void FallbackAsmResourceMap::ResourceCollection::buildResources(
1952 Operation *op, AsmResourceBuilder &builder)
const {
1953 for (
const auto &entry : resources) {
1954 if (
const auto *value = std::get_if<AsmResourceBlob>(&entry.value))
1956 else if (
const auto *value = std::get_if<bool>(&entry.value))
1958 else if (
const auto *value = std::get_if<std::string>(&entry.value))
1961 llvm_unreachable(
"unknown AsmResourceEntryKind");
1975 : interfaces(op->
getContext()), nameState(op, printerFlags),
1976 printerFlags(printerFlags), locationMap(locationMap) {}
1979 : interfaces(ctx), printerFlags(printerFlags), locationMap(locationMap) {}
1983 aliasState.initialize(op, printerFlags, interfaces);
2003 return llvm::make_pointee_range(externalResourcePrinters);
2013 (*locationMap)[op] = std::make_pair(line, col);
2019 return dialectResources;
2023 return success(cyclicPrintingStack.insert(opaquePointer));
2039 AliasState aliasState;
2042 SSANameState nameState;
2045 DistinctState distinctState;
2061template <
typename Range>
2065 [&stream](
const auto &dimSize) {
2066 if (ShapedType::isDynamic(dimSize))
2084 return printerFlags;
2088 auto parentThreadId = llvm::get_threadid();
2090 if (parentThreadId == llvm::get_threadid()) {
2092 diag.print(llvm::dbgs());
2093 llvm::dbgs() <<
"\n";
2101 <<
"' failed to verify and will be printed in generic form";
2105 return printerFlags;
2124 return impl->getPrinterFlags();
2128 std::unique_ptr<AsmResourcePrinter> printer) {
2129 impl->externalResourcePrinters.emplace_back(std::move(printer));
2134 return impl->getDialectResources();
2156 if (!isTopLevel && succeeded(
state.getAliasState().getAlias(loc,
os)))
2160 .Case<OpaqueLoc>([&](OpaqueLoc loc) {
2163 .Case<UnknownLoc>([&](UnknownLoc loc) {
2171 os << loc.getFilename().getValue();
2174 if (loc.getEndColumn() == loc.getStartColumn() &&
2175 loc.getStartLine() == loc.getEndLine()) {
2176 os <<
':' << loc.getStartLine() <<
':' << loc.getStartColumn();
2179 if (loc.getStartLine() == loc.getEndLine()) {
2180 os <<
':' << loc.getStartLine() <<
':' << loc.getStartColumn()
2181 <<
" to :" << loc.getEndColumn();
2184 os <<
':' << loc.getStartLine() <<
':' << loc.getStartColumn() <<
" to "
2185 << loc.getEndLine() <<
':' << loc.getEndColumn();
2187 .Case<NameLoc>([&](NameLoc loc) {
2191 auto childLoc = loc.getChildLoc();
2192 if (!llvm::isa<UnknownLoc>(childLoc)) {
2198 .Case<CallSiteLoc>([&](CallSiteLoc loc) {
2205 if (llvm::isa<NameLoc>(callee)) {
2206 if (llvm::isa<FileLineColLoc>(caller)) {
2221 .Case<FusedLoc>([&](
FusedLoc loc) {
2224 if (
Attribute metadata = loc.getMetadata()) {
2231 printLocationInternal(loc, pretty);
2245 bool *printedHex =
nullptr) {
2250 bool isInf = apValue.isInfinity();
2251 bool isNaN = apValue.isNaN();
2252 if (!isInf && !isNaN) {
2254 apValue.toString(strValue, 6, 0,
2260 assert(((strValue[0] >=
'0' && strValue[0] <=
'9') ||
2261 ((strValue[0] ==
'-' || strValue[0] ==
'+') &&
2262 (strValue[1] >=
'0' && strValue[1] <=
'9'))) &&
2263 "[-+]?[0-9] regex does not match!");
2267 if (APFloat(apValue.getSemantics(), strValue).bitwiseIsEqual(apValue)) {
2275 apValue.toString(strValue);
2278 if (strValue.str().contains(
'.')) {
2289 APInt apInt = apValue.bitcastToAPInt();
2290 apInt.toString(str, 16,
false,
2310 if (symName.empty() || !isalpha(symName.front()))
2315 symName = symName.drop_while(
2316 [](
char c) {
return llvm::isAlnum(c) || c ==
'.' || c ==
'_'; });
2317 if (symName.empty())
2322 return symName.front() ==
'<' && symName.back() ==
'>';
2327 StringRef dialectName, StringRef symString) {
2328 os << symPrefix << dialectName;
2333 os <<
'.' << symString;
2337 os <<
'<' << symString <<
'>';
2346 if (name.empty() || (!isalpha(name[0]) && name[0] !=
'_'))
2348 return llvm::all_of(name.drop_front(), [](
unsigned char c) {
2349 return isalnum(c) || c ==
'_' || c ==
'$' || c ==
'.';
2364 printEscapedString(keyword, os);
2372 if (symbolRef.empty()) {
2373 os <<
"@<<INVALID EMPTY SYMBOL>>";
2386 os << R
"(dense_resource<__elided__>)";
2397 return state.getAliasState().getAlias(attr,
os);
2401 return state.getAliasState().getAlias(type,
os);
2407 os <<
"<<NULL ATTRIBUTE>>";
2418 if (!isa<BuiltinDialect>(attr.
getDialect())) {
2420 }
else if (
auto opaqueAttr = llvm::dyn_cast<OpaqueAttr>(attr)) {
2422 opaqueAttr.getAttrData());
2423 }
else if (llvm::isa<UnitAttr>(attr)) {
2426 }
else if (
auto distinctAttr = llvm::dyn_cast<DistinctAttr>(attr)) {
2427 os <<
"distinct[" <<
state.getDistinctState().getId(distinctAttr) <<
"]<";
2433 }
else if (
auto dictAttr = llvm::dyn_cast<DictionaryAttr>(attr)) {
2439 }
else if (
auto intAttr = llvm::dyn_cast<IntegerAttr>(attr)) {
2440 Type intType = intAttr.getType();
2442 os << (intAttr.getValue().getBoolValue() ?
"true" :
"false");
2453 intAttr.getValue().print(
os, !isUnsigned);
2459 }
else if (
auto floatAttr = llvm::dyn_cast<FloatAttr>(attr)) {
2460 bool printedHex =
false;
2468 }
else if (
auto strAttr = llvm::dyn_cast<StringAttr>(attr)) {
2471 }
else if (
auto arrayAttr = llvm::dyn_cast<ArrayAttr>(attr)) {
2474 printAttribute(attr, AttrTypeElision::May);
2478 }
else if (
auto affineMapAttr = llvm::dyn_cast<AffineMapAttr>(attr)) {
2479 os <<
"affine_map<";
2480 affineMapAttr.getValue().print(
os);
2486 }
else if (
auto integerSetAttr = llvm::dyn_cast<IntegerSetAttr>(attr)) {
2487 os <<
"affine_set<";
2488 integerSetAttr.getValue().print(
os);
2494 }
else if (
auto typeAttr = llvm::dyn_cast<TypeAttr>(attr)) {
2497 }
else if (
auto refAttr = llvm::dyn_cast<SymbolRefAttr>(attr)) {
2504 }
else if (
auto intOrFpEltAttr =
2505 llvm::dyn_cast<DenseIntOrFPElementsAttr>(attr)) {
2506 if (
printerFlags.shouldElideElementsAttr(intOrFpEltAttr)) {
2514 }
else if (
auto strEltAttr = llvm::dyn_cast<DenseStringElementsAttr>(attr)) {
2515 if (
printerFlags.shouldElideElementsAttr(strEltAttr)) {
2523 }
else if (
auto sparseEltAttr = llvm::dyn_cast<SparseElementsAttr>(attr)) {
2524 if (
printerFlags.shouldElideElementsAttr(sparseEltAttr.getIndices()) ||
2525 printerFlags.shouldElideElementsAttr(sparseEltAttr.getValues())) {
2530 if (
indices.getNumElements() != 0) {
2537 }
else if (
auto stridedLayoutAttr = llvm::dyn_cast<StridedLayoutAttr>(attr)) {
2538 stridedLayoutAttr.print(
os);
2539 }
else if (
auto denseArrayAttr = llvm::dyn_cast<DenseArrayAttr>(attr)) {
2541 printType(denseArrayAttr.getElementType());
2542 if (!denseArrayAttr.empty()) {
2548 }
else if (
auto resourceAttr =
2549 llvm::dyn_cast<DenseResourceElementsAttr>(attr)) {
2550 os <<
"dense_resource<";
2553 }
else if (
auto locAttr = llvm::dyn_cast<LocationAttr>(attr)) {
2556 llvm::report_fatal_error(
"Unknown builtin attribute");
2560 if (
auto typedAttr = llvm::dyn_cast<TypedAttr>(attr)) {
2561 Type attrType = typedAttr.getType();
2562 if (!llvm::isa<NoneType>(attrType)) {
2574 os << (value.getBoolValue() ?
"true" :
"false");
2584 return printEltFn(0);
2587 auto numElements = type.getNumElements();
2588 if (numElements == 0)
2596 int64_t rank = type.getRank();
2599 unsigned openBrackets = 0;
2601 auto shape = type.getShape();
2602 auto bumpCounter = [&] {
2604 ++counter[rank - 1];
2606 for (
unsigned i = rank - 1; i > 0; --i)
2607 if (counter[i] >=
shape[i]) {
2616 for (
unsigned idx = 0, e = numElements; idx != e; ++idx) {
2619 while (openBrackets++ < rank)
2621 openBrackets = rank;
2625 while (openBrackets-- > 0)
2631 if (
auto stringAttr = llvm::dyn_cast<DenseStringElementsAttr>(attr))
2640 auto type = attr.getType();
2641 auto elementType = type.getElementType();
2644 if (allowHex &&
printerFlags.shouldPrintElementsAttrWithHex(attr)) {
2646 if (llvm::endianness::native == llvm::endianness::big) {
2651 DenseIntOrFPElementsAttr::convertEndianOfArrayRefForBEmachine(
2652 rawData, convRawData, type);
2661 if (ComplexType complexTy = llvm::dyn_cast<ComplexType>(elementType)) {
2662 Type complexElementType = complexTy.getElementType();
2666 if (llvm::isa<IntegerType>(complexElementType)) {
2667 auto valueIt = attr.value_begin<std::complex<APInt>>();
2669 auto complexValue = *(valueIt + index);
2671 printDenseIntElement(complexValue.real(), os, complexElementType);
2673 printDenseIntElement(complexValue.imag(), os, complexElementType);
2677 auto valueIt = attr.value_begin<std::complex<APFloat>>();
2679 auto complexValue = *(valueIt + index);
2681 printFloatValue(complexValue.real(), os);
2683 printFloatValue(complexValue.imag(), os);
2687 }
else if (elementType.isIntOrIndex()) {
2688 auto valueIt = attr.value_begin<APInt>();
2690 printDenseIntElement(*(valueIt + index), os, elementType);
2693 assert(llvm::isa<FloatType>(elementType) &&
"unexpected element type");
2694 auto valueIt = attr.value_begin<APFloat>();
2696 printFloatValue(*(valueIt + index), os);
2702 DenseStringElementsAttr attr) {
2709 Type type = attr.getElementType();
2711 unsigned byteSize = bitwidth / 8;
2714 auto printElementAt = [&](
unsigned i) {
2715 APInt value(bitwidth, 0);
2717 llvm::LoadIntFromMemory(
2718 value,
reinterpret_cast<const uint8_t *
>(data.begin() + byteSize * i),
2725 APFloat fltVal(llvm::cast<FloatType>(type).getFloatSemantics(), value);
2729 llvm::interleaveComma(llvm::seq<unsigned>(0, attr.size()),
getStream(),
2735 os <<
"<<NULL TYPE>>";
2747 .Case<OpaqueType>([&](OpaqueType opaqueTy) {
2749 opaqueTy.getTypeData());
2751 .Case<IndexType>([&](
Type) {
os <<
"index"; })
2752 .Case<Float4E2M1FNType>([&](
Type) {
os <<
"f4E2M1FN"; })
2753 .Case<Float6E2M3FNType>([&](
Type) {
os <<
"f6E2M3FN"; })
2754 .Case<Float6E3M2FNType>([&](
Type) {
os <<
"f6E3M2FN"; })
2755 .Case<Float8E5M2Type>([&](
Type) {
os <<
"f8E5M2"; })
2756 .Case<Float8E4M3Type>([&](
Type) {
os <<
"f8E4M3"; })
2757 .Case<Float8E4M3FNType>([&](
Type) {
os <<
"f8E4M3FN"; })
2758 .Case<Float8E5M2FNUZType>([&](
Type) {
os <<
"f8E5M2FNUZ"; })
2759 .Case<Float8E4M3FNUZType>([&](
Type) {
os <<
"f8E4M3FNUZ"; })
2760 .Case<Float8E4M3B11FNUZType>([&](
Type) {
os <<
"f8E4M3B11FNUZ"; })
2761 .Case<Float8E3M4Type>([&](
Type) {
os <<
"f8E3M4"; })
2762 .Case<Float8E8M0FNUType>([&](
Type) {
os <<
"f8E8M0FNU"; })
2763 .Case<BFloat16Type>([&](
Type) {
os <<
"bf16"; })
2764 .Case<Float16Type>([&](
Type) {
os <<
"f16"; })
2765 .Case<FloatTF32Type>([&](
Type) {
os <<
"tf32"; })
2766 .Case<Float32Type>([&](
Type) {
os <<
"f32"; })
2767 .Case<Float64Type>([&](
Type) {
os <<
"f64"; })
2768 .Case<Float80Type>([&](
Type) {
os <<
"f80"; })
2769 .Case<Float128Type>([&](
Type) {
os <<
"f128"; })
2770 .Case<IntegerType>([&](IntegerType integerTy) {
2771 if (integerTy.isSigned())
2773 else if (integerTy.isUnsigned())
2775 os <<
'i' << integerTy.getWidth();
2777 .Case<FunctionType>([&](FunctionType funcTy) {
2782 if (results.size() == 1 && !llvm::isa<FunctionType>(results[0])) {
2790 .Case<VectorType>([&](VectorType vectorTy) {
2791 auto scalableDims = vectorTy.getScalableDims();
2793 auto vShape = vectorTy.getShape();
2794 unsigned lastDim = vShape.size();
2795 unsigned dimIdx = 0;
2796 for (dimIdx = 0; dimIdx < lastDim; dimIdx++) {
2797 if (!scalableDims.empty() && scalableDims[dimIdx])
2799 os << vShape[dimIdx];
2800 if (!scalableDims.empty() && scalableDims[dimIdx])
2807 .Case<RankedTensorType>([&](RankedTensorType tensorTy) {
2810 if (!tensorTy.getShape().empty())
2814 if (tensorTy.getEncoding()) {
2820 .Case<UnrankedTensorType>([&](UnrankedTensorType tensorTy) {
2825 .Case<MemRefType>([&](MemRefType memrefTy) {
2828 if (!memrefTy.getShape().empty())
2831 MemRefLayoutAttrInterface layout = memrefTy.getLayout();
2832 if (!llvm::isa<AffineMapAttr>(layout) || !layout.isIdentity()) {
2837 if (memrefTy.getMemorySpace()) {
2847 if (memrefTy.getMemorySpace()) {
2853 .Case<ComplexType>([&](ComplexType complexTy) {
2858 .Case<TupleType>([&](TupleType tupleTy) {
2861 [&](
Type type) { printType(type); });
2864 .Case<NoneType>([&](
Type) {
os <<
"none"; })
2865 .Case<GraphType>([&](GraphType graphTy) {
2870 if (results.size() == 1 && !isa<FunctionType, GraphType>(results[0])) {
2889 auto printFilteredAttributesFn = [&](
auto filteredAttrs) {
2892 os <<
" attributes";
2902 if (elidedAttrs.empty())
2903 return printFilteredAttributesFn(attrs);
2906 llvm::SmallDenseSet<StringRef> elidedAttrsSet(elidedAttrs.begin(),
2908 auto filteredAttrs = llvm::make_filter_range(attrs, [&](
NamedAttribute attr) {
2909 return !elidedAttrsSet.contains(attr.
getName().strref());
2911 if (!filteredAttrs.empty())
2912 printFilteredAttributesFn(filteredAttrs);
2919 if (llvm::isa<UnitAttr>(attr.
getValue()))
2930 std::string attrName;
2932 llvm::raw_string_ostream attrNameStr(attrName);
2942 dialect.printAttribute(attr, printer);
2951 std::string typeName;
2953 llvm::raw_string_ostream typeNameStr(typeName);
2963 dialect.printType(type, printer);
2970 llvm::printEscapedString(str,
os);
2975 os <<
"\"0x" << llvm::toHex(str) <<
"\"";
2982 return state.pushCyclicPrinting(opaquePointer);
2998 assert(
impl &&
"expected AsmPrinter::getStream to be overriden");
2999 return impl->getStream();
3003 assert(
impl &&
"expected AsmPrinter::printNewLine to be overriden");
3004 impl->printNewline();
3008 assert(
impl &&
"expected AsmPrinter::increaseIndent to be overriden");
3009 impl->increaseIndent();
3013 assert(
impl &&
"expected AsmPrinter::decreaseIndent to be overriden");
3014 impl->decreaseIndent();
3019 assert(
impl &&
"expected AsmPrinter::printFloat to be overriden");
3024 assert(
impl &&
"expected AsmPrinter::printType to be overriden");
3025 impl->printType(type);
3029 assert(
impl &&
"expected AsmPrinter::printAttribute to be overriden");
3030 impl->printAttribute(attr);
3034 assert(
impl &&
"expected AsmPrinter::printAlias to be overriden");
3035 return impl->printAlias(attr);
3039 assert(
impl &&
"expected AsmPrinter::printAlias to be overriden");
3040 return impl->printAlias(type);
3045 "expected AsmPrinter::printAttributeWithoutType to be overriden");
3050 assert(
impl &&
"expected AsmPrinter::printNamedAttribute to be overriden");
3051 impl->printNamedAttribute(attr);
3055 assert(
impl &&
"expected AsmPrinter::printKeywordOrString to be overriden");
3060 assert(
impl &&
"expected AsmPrinter::printString to be overriden");
3062 printEscapedString(keyword,
getStream());
3067 assert(
impl &&
"expected AsmPrinter::printSymbolName to be overriden");
3072 assert(
impl &&
"expected AsmPrinter::printResourceHandle to be overriden");
3073 impl->printResourceHandle(resource);
3081 return impl->pushCyclicPrinting(opaquePointer);
3098 const char *binopSpelling =
nullptr;
3101 unsigned pos = cast<AffineSymbolExpr>(expr).getPosition();
3103 printValueName(pos,
true);
3109 unsigned pos = cast<AffineDimExpr>(expr).getPosition();
3111 printValueName(pos,
false);
3117 os << cast<AffineConstantExpr>(expr).getValue();
3120 binopSpelling =
" + ";
3123 binopSpelling =
" * ";
3126 binopSpelling =
" floordiv ";
3129 binopSpelling =
" ceildiv ";
3132 binopSpelling =
" mod ";
3136 auto binOp = cast<AffineBinaryOpExpr>(expr);
3146 auto rhsConst = dyn_cast<AffineConstantExpr>(rhsExpr);
3148 rhsConst.getValue() == -1) {
3158 os << binopSpelling;
3172 if (
auto rhs = dyn_cast<AffineBinaryOpExpr>(rhsExpr)) {
3175 if (
auto rrhs = dyn_cast<AffineConstantExpr>(rrhsExpr)) {
3176 if (rrhs.getValue() == -1) {
3193 if (rrhs.getValue() < -1) {
3199 os <<
" * " << -rrhs.getValue();
3209 if (
auto rhsConst = dyn_cast<AffineConstantExpr>(rhsExpr)) {
3210 if (rhsConst.getValue() < 0) {
3212 os <<
" - " << -rhsConst.getValue();
3230 isEq ?
os <<
" == 0" :
os <<
" >= 0";
3236 for (
int i = 0; i < (int)map.
getNumDims() - 1; ++i)
3237 os <<
'd' << i <<
", ";
3246 os <<
's' << i <<
", ";
3255 [&](
AffineExpr expr) { printAffineExpr(expr); });
3262 for (
unsigned i = 1; i < set.
getNumDims(); ++i)
3263 os <<
'd' << i - 1 <<
", ";
3272 os <<
's' << i <<
", ";
3281 for (
int i = 1; i < numConstraints; ++i) {
3285 if (numConstraints >= 1)
3287 set.
isEq(numConstraints - 1));
3306 void printTopLevelOperation(
Operation *op);
3310 void printFullOpWithIndentAndLoc(
Operation *op);
3316 void printCustomOrGenericOp(
Operation *op)
override;
3318 void printGenericOp(
Operation *op,
bool printOpName)
override;
3321 void printBlockName(
Block *block);
3326 void print(
Block *block,
bool printBlockArgs =
true,
3327 bool printBlockTerminator =
true);
3330 void printValueID(
Value value,
bool printResultNo =
true,
3343 void printOptionalLocationSpecifier(
Location loc)
override {
3344 printTrailingLocation(loc);
3354 bool omitType =
false)
override;
3357 void printOperand(Value value)
override { printValueID(value); }
3358 void printOperand(Value value, raw_ostream &os)
override {
3359 printValueID(value,
true, &os);
3363 void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
3364 ArrayRef<StringRef> elidedAttrs = {})
override {
3365 Impl::printOptionalAttrDict(attrs, elidedAttrs);
3367 void printOptionalAttrDictWithKeyword(
3368 ArrayRef<NamedAttribute> attrs,
3369 ArrayRef<StringRef> elidedAttrs = {})
override {
3370 Impl::printOptionalAttrDict(attrs, elidedAttrs,
3375 void printSuccessor(
Block *successor)
override;
3379 void printSuccessorAndUseList(
Block *successor,
3383 void printRegion(Region ®ion,
bool printEntryBlockArgs,
3384 bool printBlockTerminators,
bool printEmptyBlock)
override;
3390 void shadowRegionArgs(Region ®ion,
ValueRange namesToUse)
override {
3396 void printAffineMapOfSSAIds(AffineMapAttr mapAttr,
3401 void printAffineExprOfSSAIds(AffineExpr expr,
ValueRange dimOperands,
3405 void printUsersComment(Operation *op);
3408 void printUsersComment(BlockArgument arg);
3411 void printValueUsers(Value value);
3415 void printUserIDs(Operation *user,
bool prefixComma =
false);
3420 class ResourceBuilder :
public AsmResourceBuilder {
3423 using PrintFn =
function_ref<void(StringRef, ValueFn)>;
3425 ResourceBuilder(PrintFn printFn) : printFn(printFn) {}
3426 ~ResourceBuilder()
override =
default;
3428 void buildBool(StringRef key,
bool data)
final {
3429 printFn(key, [&](raw_ostream &os) { os << (data ?
"true" :
"false"); });
3432 void buildString(StringRef key, StringRef data)
final {
3433 printFn(key, [&](raw_ostream &os) {
3435 llvm::printEscapedString(data, os);
3440 void buildBlob(StringRef key, ArrayRef<char> data,
3441 uint32_t dataAlignment)
final {
3442 printFn(key, [&](raw_ostream &os) {
3444 llvm::support::ulittle32_t dataAlignmentLE(dataAlignment);
3446 << llvm::toHex(StringRef(
reinterpret_cast<char *
>(&dataAlignmentLE),
3447 sizeof(dataAlignment)))
3448 << llvm::toHex(StringRef(data.data(), data.size())) <<
"\"";
3457 void printFileMetadataDictionary(Operation *op);
3463 void printResourceFileMetadata(
function_ref<
void()> checkAddMetadataDict,
3471 SmallVector<StringRef> defaultDialectStack{
"builtin"};
3475void OperationPrinter::printTopLevelOperation(Operation *op) {
3477 state.
getAliasState().printNonDeferredAliases(*
this, newLine);
3480 printFullOpWithIndentAndLoc(op);
3487 printFileMetadataDictionary(op);
3490void OperationPrinter::printFileMetadataDictionary(Operation *op) {
3491 bool sawMetadataEntry =
false;
3492 auto checkAddMetadataDict = [&] {
3493 if (!std::exchange(sawMetadataEntry,
true))
3494 os << newLine <<
"{-#" << newLine;
3498 printResourceFileMetadata(checkAddMetadataDict, op);
3501 if (sawMetadataEntry)
3502 os << newLine <<
"#-}" << newLine;
3505void OperationPrinter::printResourceFileMetadata(
3506 function_ref<
void()> checkAddMetadataDict, Operation *op) {
3508 bool hadResource =
false;
3509 bool needResourceComma =
false;
3510 bool needEntryComma =
false;
3511 auto processProvider = [&](StringRef dictName, StringRef name,
auto &provider,
3512 auto &&...providerArgs) {
3513 bool hadEntry =
false;
3514 auto printFn = [&](StringRef key, ResourceBuilder::ValueFn valueFn) {
3515 checkAddMetadataDict();
3517 std::string resourceStr;
3518 auto printResourceStr = [&](raw_ostream &os) { os << resourceStr; };
3519 std::optional<uint64_t> charLimit =
3521 if (charLimit.has_value()) {
3523 if (charLimit.value() == 0)
3526 llvm::raw_string_ostream ss(resourceStr);
3530 if (resourceStr.size() > charLimit.value())
3534 valueFn = printResourceStr;
3538 if (!std::exchange(hadResource,
true)) {
3539 if (needResourceComma)
3540 os <<
"," << newLine;
3541 os <<
" " << dictName <<
"_resources: {" << newLine;
3544 if (!std::exchange(hadEntry,
true)) {
3546 os <<
"," << newLine;
3547 os <<
" " << name <<
": {" << newLine;
3549 os <<
"," << newLine;
3557 ResourceBuilder entryBuilder(printFn);
3558 provider.buildResources(op, providerArgs..., entryBuilder);
3560 needEntryComma |= hadEntry;
3562 os << newLine <<
" }";
3569 StringRef name = interface.getDialect()->getNamespace();
3570 auto it = dialectResources.find(interface.getDialect());
3571 if (it != dialectResources.end())
3572 processProvider(
"dialect", name, interface, it->second);
3574 processProvider(
"dialect", name, interface,
3578 os << newLine <<
" }";
3582 needEntryComma =
false;
3583 needResourceComma = hadResource;
3584 hadResource =
false;
3586 processProvider(
"external", printer.getName(), printer);
3588 os << newLine <<
" }";
3596void OperationPrinter::printRegionArgument(BlockArgument arg,
3597 ArrayRef<NamedAttribute> argAttrs,
3604 printOptionalAttrDict(argAttrs);
3606 printTrailingLocation(arg.
getLoc(),
false);
3609void OperationPrinter::printFullOpWithIndentAndLoc(Operation *op) {
3613 os.indent(currentIndent);
3615 printTrailingLocation(op->
getLoc());
3617 printUsersComment(op);
3620void OperationPrinter::printFullOp(Operation *op) {
3622 auto printResultGroup = [&](
size_t resultNo,
size_t resultCount) {
3623 printValueID(op->
getResult(resultNo),
false);
3624 if (resultCount > 1)
3625 os <<
':' << resultCount;
3629 ArrayRef<int> resultGroups = state.
getSSANameState().getOpResultGroups(op);
3630 if (!resultGroups.empty()) {
3633 interleaveComma(llvm::seq<int>(0, resultGroups.size() - 1), [&](
int i) {
3634 printResultGroup(resultGroups[i],
3635 resultGroups[i + 1] - resultGroups[i]);
3638 printResultGroup(resultGroups.back(), numResults - resultGroups.back());
3641 printResultGroup(0, numResults);
3647 printCustomOrGenericOp(op);
3650void OperationPrinter::printUsersComment(Operation *op) {
3654 printOperationID(op);
3655 }
else if (numResults && op->
use_empty()) {
3657 }
else if (numResults && !op->
use_empty()) {
3660 unsigned usedInNResults = 0;
3661 unsigned usedInNOperations = 0;
3662 SmallPtrSet<Operation *, 1> userSet;
3663 for (Operation *user : op->
getUsers()) {
3664 if (userSet.insert(user).second) {
3665 ++usedInNOperations;
3666 usedInNResults += user->getNumResults();
3671 bool exactlyOneUniqueUse =
3672 usedInNResults <= 1 && usedInNOperations <= 1 && numResults == 1;
3673 os <<
" // " << (exactlyOneUniqueUse ?
"user" :
"users") <<
": ";
3674 bool shouldPrintBrackets = numResults > 1;
3675 auto printOpResult = [&](OpResult opResult) {
3676 if (shouldPrintBrackets)
3678 printValueUsers(opResult);
3679 if (shouldPrintBrackets)
3683 interleaveComma(op->
getResults(), printOpResult);
3687void OperationPrinter::printUsersComment(BlockArgument arg) {
3693 os <<
" is used by ";
3694 printValueUsers(arg);
3699void OperationPrinter::printValueUsers(Value value) {
3705 SmallPtrSet<Operation *, 1> userSet;
3707 if (userSet.insert(user).second)
3708 printUserIDs(user, index);
3712void OperationPrinter::printUserIDs(Operation *user,
bool prefixComma) {
3717 printOperationID(user);
3720 [
this](Value
result) { printValueID(result); });
3724void OperationPrinter::printCustomOrGenericOp(Operation *op) {
3730 opInfo->printAssembly(op, *
this, defaultDialectStack.back());
3735 if (
auto opPrinter = dialect->getOperationPrinter(op)) {
3740 if (name.count(
'.') == 1)
3741 name.consume_front((defaultDialectStack.back() +
".").str());
3745 opPrinter(op, *
this);
3752 printGenericOp(op,
true);
3755void OperationPrinter::printGenericOp(Operation *op,
bool printOpName) {
3759 interleaveComma(op->
getOperands(), [&](Value value) { printValueID(value); });
3766 [&](
Block *successor) { printBlockName(successor); });
3780 interleaveComma(op->
getRegions(), [&](Region ®ion) {
3781 printRegion(region, true,
3796void OperationPrinter::printBlockName(
Block *block) {
3800void OperationPrinter::print(
Block *block,
bool printBlockArgs,
3801 bool printBlockTerminator) {
3803 if (printBlockArgs) {
3804 os.indent(currentIndent);
3805 printBlockName(block);
3810 interleaveComma(block->
getArguments(), [&](BlockArgument arg) {
3813 printType(arg.getType());
3815 printTrailingLocation(arg.getLoc(), false);
3823 os <<
" // block is not in a region!";
3826 os <<
" // no predecessors";
3829 printBlockName(pred);
3833 SmallVector<BlockInfo, 4> predIDs;
3836 llvm::sort(predIDs, [](BlockInfo
lhs, BlockInfo
rhs) {
3837 return lhs.ordering <
rhs.ordering;
3840 os <<
" // " << predIDs.size() <<
" preds: ";
3842 interleaveComma(predIDs, [&](BlockInfo pred) { os << pred.name; });
3847 currentIndent += indentWidth;
3851 os.indent(currentIndent);
3852 printUsersComment(arg);
3856 bool hasTerminator =
3858 auto range = llvm::make_range(
3860 std::prev(block->
end(),
3861 (!hasTerminator || printBlockTerminator) ? 0 : 1));
3862 for (
auto &op : range) {
3863 printFullOpWithIndentAndLoc(&op);
3866 currentIndent -= indentWidth;
3869void OperationPrinter::printValueID(Value value,
bool printResultNo,
3870 raw_ostream *streamOverride)
const {
3872 streamOverride ? *streamOverride : os);
3875void OperationPrinter::printOperationID(Operation *op,
3876 raw_ostream *streamOverride)
const {
3877 state.
getSSANameState().printOperationID(op, streamOverride ? *streamOverride
3881void OperationPrinter::printSuccessor(
Block *successor) {
3882 printBlockName(successor);
3885void OperationPrinter::printSuccessorAndUseList(
Block *successor,
3887 printBlockName(successor);
3888 if (succOperands.empty())
3892 interleaveComma(succOperands,
3893 [
this](Value operand) { printValueID(operand); });
3895 interleaveComma(succOperands,
3900void OperationPrinter::printRegion(Region ®ion,
bool printEntryBlockArgs,
3901 bool printBlockTerminators,
3902 bool printEmptyBlock) {
3907 os <<
"{" << newLine;
3908 if (!region.
empty()) {
3909 llvm::scope_exit restoreDefaultDialect(
3910 [&]() { defaultDialectStack.pop_back(); });
3911 if (
auto iface = dyn_cast<OpAsmOpInterface>(region.
getParentOp()))
3912 defaultDialectStack.push_back(iface.getDefaultDialect());
3914 defaultDialectStack.push_back(
"");
3916 auto *entryBlock = ®ion.
front();
3920 bool shouldAlwaysPrintBlockHeader =
3921 (printEmptyBlock && entryBlock->empty()) ||
3922 (printEntryBlockArgs && entryBlock->getNumArguments() != 0);
3923 print(entryBlock, shouldAlwaysPrintBlockHeader, printBlockTerminators);
3924 for (
auto &
b : llvm::drop_begin(region.
getBlocks(), 1))
3927 os.indent(currentIndent) <<
"}";
3930void OperationPrinter::printAffineMapOfSSAIds(AffineMapAttr mapAttr,
3933 os <<
"<<NULL AFFINE MAP>>";
3936 AffineMap map = mapAttr.getValue();
3938 auto printValueName = [&](
unsigned pos,
bool isSymbol) {
3939 unsigned index = isSymbol ? numDims + pos : pos;
3940 assert(index < operands.size());
3943 printValueID(operands[index]);
3948 interleaveComma(map.
getResults(), [&](AffineExpr expr) {
3949 printAffineExpr(expr, printValueName);
3953void OperationPrinter::printAffineExprOfSSAIds(AffineExpr expr,
3956 auto printValueName = [&](
unsigned pos,
bool isSymbol) {
3958 return printValueID(dimOperands[pos]);
3960 printValueID(symOperands[pos]);
3963 printAffineExpr(expr, printValueName);
3972 os <<
"<<NULL ATTRIBUTE>>";
3977 print(os, state, elideType);
3983 : AttrTypeElision::Never);
3987 print(llvm::errs());
3988 llvm::errs() <<
"\n";
3993 os <<
"<<NULL ATTRIBUTE>>";
4002 uint64_t posPrior = os.tell();
4004 dialect.printAttribute(*
this, printer);
4005 if (posPrior != os.tell())
4014 os <<
"<<NULL ATTRIBUTE>>";
4024 os <<
"<<NULL TYPE>>";
4036 print(llvm::errs());
4037 llvm::errs() <<
"\n";
4041 print(llvm::errs());
4042 llvm::errs() <<
"\n";
4046 print(llvm::errs());
4047 llvm::errs() <<
"\n";
4052 os <<
"<<NULL AFFINE EXPR>>";
4060 print(llvm::errs());
4061 llvm::errs() <<
"\n";
4066 os <<
"<<NULL AFFINE MAP>>";
4081 os <<
"<<NULL VALUE>>";
4086 return op->
print(os, flags);
4089 os <<
"<block argument> of type '" << arg.
getType()
4094 os <<
"<<NULL VALUE>>";
4099 return op->
print(os, state);
4103 os <<
"<block argument> of type '" << arg.
getType()
4108 print(llvm::errs());
4109 llvm::errs() <<
"\n";
4140 if (
auto result = llvm::dyn_cast<OpResult>(*
this)) {
4143 op = llvm::cast<BlockArgument>(*this).getOwner()->
getParentOp();
4145 os <<
"<<UNKNOWN SSA VALUE>>";
4161 OperationPrinter printer(os, state.
getImpl());
4164 printer.printTopLevelOperation(
this);
4166 printer.printFullOpWithIndentAndLoc(
this);
4172 llvm::errs() <<
"\n";
4177 llvm::errs() <<
"\n";
4183 os <<
"<<UNLINKED BLOCK>>\n";
4194 OperationPrinter(os, state.
getImpl()).print(
this);
4203 os <<
"<<UNLINKED BLOCK>>\n";
4210 OperationPrinter printer(os, state.
getImpl());
4211 printer.printBlockName(
this);
4226 if (dimensions.empty())
4229 if (dimensions.empty())
4239 <<
"Failed parsing dimension list.";
4250 <<
"Failed parsing dimension list.";
4252 if (shapeArr.empty()) {
4254 <<
"Failed parsing dimension list. Did you mean an empty list? It "
4255 "must be denoted by \"[]\".";
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)
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)
void printDenseIntOrFPElementsAttr(DenseIntOrFPElementsAttr attr, bool allowHex)
Print a dense elements attribute.
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 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.
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.
Dialect * getDialect() const
Return the dialect that this interface represents.
StringRef getNamespace() const
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.
OpAsmAliasResult AliasResult
virtual LogicalResult parseResource(AsmParsedResourceEntry &entry) const
Hook for parsing resource entries.
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 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()
ArrayRef< NamedAttribute > getAttrs()
Return all of the attributes on this operation.
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.
unsigned getNumOperands()
Attribute getPropertiesAsAttribute()
Return the properties converted to an attribute.
auto getDiscardableAttrs()
Return a range of all of discardable attributes on this operation.
OperationName getName()
The name of an operation is the key identifier for it.
void print(raw_ostream &os, const OpPrintingFlags &flags={})
operand_type_range getOperandTypes()
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.
OpaqueProperties getPropertiesStorage()
Returns the properties storage.
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
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...