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);
520 DenseElementType denseEltType);
544 function_ref<
void(
unsigned,
bool)> printValueName =
nullptr);
574 SymbolAlias(StringRef name, uint32_t suffixIndex,
bool isType,
576 : name(name), suffixIndex(suffixIndex), isType(isType),
577 isDeferrable(isDeferrable) {}
581 os << (isType ?
"!" :
"#") << name;
583 if (isdigit(name.back()))
590 bool isTypeAlias()
const {
return isType; }
593 bool canBeDeferred()
const {
return isDeferrable; }
599 uint32_t suffixIndex : 30;
603 bool isDeferrable : 1;
607 bool isPrinted =
false;
613class AliasInitializer {
616 DialectInterfaceCollection<OpAsmDialectInterface> &interfaces,
617 llvm::BumpPtrAllocator &aliasAllocator)
618 : interfaces(interfaces), aliasAllocator(aliasAllocator),
619 aliasOS(aliasBuffer) {}
621 void initialize(Operation *op,
const OpPrintingFlags &printerFlags,
622 llvm::MapVector<const void *, SymbolAlias> &attrTypeToAlias);
630 std::pair<size_t, size_t>
visit(Attribute attr,
bool canBeDeferred =
false,
631 bool elideType =
false) {
632 return visitImpl(attr, aliases, canBeDeferred, elideType);
639 std::pair<size_t, size_t>
visit(Type type,
bool canBeDeferred =
false) {
640 return visitImpl(type, aliases, canBeDeferred);
644 struct InProgressAliasInfo {
645 InProgressAliasInfo()
646 : aliasDepth(0), isType(
false), canBeDeferred(
false) {}
647 InProgressAliasInfo(StringRef alias)
648 : alias(alias), aliasDepth(1), isType(
false), canBeDeferred(
false) {}
652 if (aliasDepth !=
rhs.aliasDepth)
653 return aliasDepth <
rhs.aliasDepth;
654 if (isType !=
rhs.isType)
656 return alias <
rhs.alias;
661 std::optional<StringRef> alias;
664 unsigned aliasDepth : 30;
668 bool canBeDeferred : 1;
670 SmallVector<size_t> childIndices;
678 template <
typename T,
typename... PrintArgs>
679 std::pair<size_t, size_t>
681 llvm::MapVector<const void *, InProgressAliasInfo> &aliases,
682 bool canBeDeferred, PrintArgs &&...
printArgs);
685 void markAliasNonDeferrable(
size_t aliasIndex);
689 template <
typename T>
690 void generateAlias(T symbol, InProgressAliasInfo &alias,
bool canBeDeferred);
695 uniqueAliasNameIndex(StringRef alias, llvm::StringMap<unsigned> &nameCounts,
696 llvm::StringSet<llvm::BumpPtrAllocator &> &usedAliases);
700 static void initializeAliases(
701 llvm::MapVector<const void *, InProgressAliasInfo> &visitedSymbols,
702 llvm::MapVector<const void *, SymbolAlias> &symbolToAlias);
705 DialectInterfaceCollection<OpAsmDialectInterface> &interfaces;
708 llvm::BumpPtrAllocator &aliasAllocator;
711 llvm::MapVector<const void *, InProgressAliasInfo> aliases;
714 SmallString<32> aliasBuffer;
715 llvm::raw_svector_ostream aliasOS;
723class DummyAliasOperationPrinter :
private OpAsmPrinter {
725 explicit DummyAliasOperationPrinter(
const OpPrintingFlags &printerFlags,
726 AliasInitializer &initializer)
727 : printerFlags(printerFlags), initializer(initializer) {}
731 void printCustomOrGenericOp(Operation *op)
override {
733 if (printerFlags.shouldPrintDebugInfo())
734 initializer.visit(op->
getLoc(),
true);
737 if (!printerFlags.shouldPrintGenericOpForm()) {
748 void printGenericOp(Operation *op,
bool printOpName =
true)
override {
750 if (!printerFlags.shouldSkipRegions()) {
763 for (
const NamedAttribute &attr : op->
getAttrs())
764 printAttribute(attr.getValue());
770 void print(
Block *block,
bool printBlockArgs =
true,
771 bool printBlockTerminator =
true) {
774 if (printBlockArgs) {
779 if (printerFlags.shouldPrintDebugInfo())
781 initializer.visit(arg.getLoc(),
false);
789 auto range = llvm::make_range(
791 std::prev(block->
end(),
792 (!hasTerminator || printBlockTerminator) ? 0 : 1));
793 for (Operation &op : range)
794 printCustomOrGenericOp(&op);
798 void printRegion(Region ®ion,
bool printEntryBlockArgs,
799 bool printBlockTerminators,
800 bool printEmptyBlock =
false)
override {
803 if (printerFlags.shouldSkipRegions()) {
808 auto *entryBlock = ®ion.
front();
809 print(entryBlock, printEntryBlockArgs, printBlockTerminators);
810 for (
Block &
b : llvm::drop_begin(region, 1))
814 void printRegionArgument(BlockArgument arg, ArrayRef<NamedAttribute> argAttrs,
815 bool omitType)
override {
818 if (printerFlags.shouldPrintDebugInfo())
820 initializer.visit(arg.
getLoc(),
false);
824 void printType(Type type)
override { initializer.visit(type); }
827 void printAttribute(Attribute attr)
override { initializer.visit(attr); }
828 void printAttributeWithoutType(Attribute attr)
override {
829 printAttribute(attr);
831 void printNamedAttribute(NamedAttribute attr)
override {
835 LogicalResult printAlias(Attribute attr)
override {
836 initializer.visit(attr);
839 LogicalResult printAlias(Type type)
override {
840 initializer.visit(type);
845 void printOptionalLocationSpecifier(Location loc)
override {
851 void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
852 ArrayRef<StringRef> elidedAttrs = {})
override {
855 if (elidedAttrs.empty()) {
856 for (
const NamedAttribute &attr : attrs)
857 printAttribute(attr.getValue());
860 llvm::SmallDenseSet<StringRef> elidedAttrsSet(elidedAttrs.begin(),
862 for (
const NamedAttribute &attr : attrs)
863 if (!elidedAttrsSet.contains(attr.getName().strref()))
864 printAttribute(attr.getValue());
866 void printOptionalAttrDictWithKeyword(
867 ArrayRef<NamedAttribute> attrs,
868 ArrayRef<StringRef> elidedAttrs = {})
override {
869 printOptionalAttrDict(attrs, elidedAttrs);
874 raw_ostream &getStream()
const override {
return os; }
878 void printFloat(
const APFloat &)
override {}
879 void printAffineMapOfSSAIds(AffineMapAttr,
ValueRange)
override {}
882 void increaseIndent()
override {}
883 void decreaseIndent()
override {}
884 void printOperand(Value)
override {}
885 void printOperand(Value, raw_ostream &os)
override {
893 void printResourceHandle(
const AsmDialectResourceHandle &)
override {}
894 void printSymbolName(StringRef)
override {}
895 void printSuccessor(
Block *)
override {}
897 void shadowRegionArgs(Region &,
ValueRange)
override {}
900 const OpPrintingFlags &printerFlags;
903 AliasInitializer &initializer;
906 mutable llvm::raw_null_ostream os;
911 explicit DummyAliasDialectAsmPrinter(AliasInitializer &initializer,
913 SmallVectorImpl<size_t> &childIndices)
914 : initializer(initializer), canBeDeferred(canBeDeferred),
915 childIndices(childIndices) {}
920 template <
typename T,
typename... PrintArgs>
921 size_t printAndVisitNestedAliases(T value, PrintArgs &&...
printArgs) {
922 printAndVisitNestedAliasesImpl(value,
printArgs...);
923 return maxAliasDepth;
929 void printAndVisitNestedAliasesImpl(Attribute attr,
bool elideType) {
930 if (!isa<BuiltinDialect>(attr.
getDialect())) {
934 }
else if (llvm::isa<AffineMapAttr, DenseArrayAttr, FloatAttr, IntegerAttr,
935 IntegerSetAttr, UnitAttr>(attr)) {
937 }
else if (
auto distinctAttr = dyn_cast<DistinctAttr>(attr)) {
938 printAttribute(distinctAttr.getReferencedAttr());
939 }
else if (
auto dictAttr = dyn_cast<DictionaryAttr>(attr)) {
940 for (
const NamedAttribute &nestedAttr : dictAttr.getValue()) {
941 printAttribute(nestedAttr.getName());
942 printAttribute(nestedAttr.getValue());
944 }
else if (
auto arrayAttr = dyn_cast<ArrayAttr>(attr)) {
945 for (Attribute nestedAttr : arrayAttr.getValue())
946 printAttribute(nestedAttr);
947 }
else if (
auto typeAttr = dyn_cast<TypeAttr>(attr)) {
949 }
else if (
auto locAttr = dyn_cast<OpaqueLoc>(attr)) {
950 printAttribute(locAttr.getFallbackLocation());
951 }
else if (
auto locAttr = dyn_cast<NameLoc>(attr)) {
952 if (!isa<UnknownLoc>(locAttr.getChildLoc()))
953 printAttribute(locAttr.getChildLoc());
954 }
else if (
auto locAttr = dyn_cast<CallSiteLoc>(attr)) {
955 printAttribute(locAttr.getCallee());
956 printAttribute(locAttr.getCaller());
957 }
else if (
auto locAttr = dyn_cast<FusedLoc>(attr)) {
958 if (Attribute metadata = locAttr.getMetadata())
959 printAttribute(metadata);
960 for (Location nestedLoc : locAttr.getLocations())
961 printAttribute(nestedLoc);
966 if (
auto typedAttr = llvm::dyn_cast<TypedAttr>(attr)) {
967 Type attrType = typedAttr.getType();
968 if (!llvm::isa<NoneType>(attrType))
973 void printAndVisitNestedAliasesImpl(Type type) {
978 if (
auto memrefTy = llvm::dyn_cast<MemRefType>(type)) {
980 MemRefLayoutAttrInterface layout = memrefTy.getLayout();
981 if (!llvm::isa<AffineMapAttr>(layout) || !layout.isIdentity())
982 printAttribute(memrefTy.getLayout());
983 if (memrefTy.getMemorySpace())
984 printAttribute(memrefTy.getMemorySpace());
989 auto visitFn = [&](
auto element) {
991 (void)printAlias(element);
998 recordAliasResult(initializer.visit(type, canBeDeferred));
1002 void printAttribute(Attribute attr)
override {
1003 recordAliasResult(initializer.visit(attr, canBeDeferred));
1005 void printAttributeWithoutType(Attribute attr)
override {
1007 initializer.visit(attr, canBeDeferred,
true));
1009 void printNamedAttribute(NamedAttribute attr)
override {
1013 LogicalResult printAlias(Attribute attr)
override {
1014 printAttribute(attr);
1017 LogicalResult printAlias(Type type)
override {
1023 void recordAliasResult(std::pair<size_t, size_t> aliasDepthAndIndex) {
1024 childIndices.push_back(aliasDepthAndIndex.second);
1025 if (aliasDepthAndIndex.first > maxAliasDepth)
1026 maxAliasDepth = aliasDepthAndIndex.first;
1031 raw_ostream &getStream()
const override {
return os; }
1036 void increaseIndent()
override {}
1037 void decreaseIndent()
override {}
1038 void printFloat(
const APFloat &)
override {}
1041 void printSymbolName(StringRef)
override {}
1042 void printResourceHandle(
const AsmDialectResourceHandle &)
override {}
1044 LogicalResult pushCyclicPrinting(
const void *opaquePointer)
override {
1045 return success(cyclicPrintingStack.insert(opaquePointer));
1048 void popCyclicPrinting()
override { cyclicPrintingStack.pop_back(); }
1052 SetVector<const void *> cyclicPrintingStack;
1055 AliasInitializer &initializer;
1061 SmallVectorImpl<size_t> &childIndices;
1064 size_t maxAliasDepth = 0;
1067 mutable llvm::raw_null_ostream os;
1075 StringRef allowedPunctChars =
"$._-") {
1076 assert(!name.empty() &&
"Shouldn't have an empty name here");
1078 auto validChar = [&](
char ch) {
1079 return llvm::isAlnum(ch) || allowedPunctChars.contains(ch);
1082 auto copyNameToBuffer = [&] {
1083 for (
char ch : name) {
1085 buffer.push_back(ch);
1087 buffer.push_back(
'_');
1089 buffer.append(llvm::utohexstr((
unsigned char)ch));
1096 if (isdigit(name[0]) || (!validChar(name[0]) && name[0] !=
' ')) {
1097 buffer.push_back(
'_');
1103 for (
char ch : name) {
1104 if (!validChar(ch)) {
1114unsigned AliasInitializer::uniqueAliasNameIndex(
1115 StringRef alias, llvm::StringMap<unsigned> &nameCounts,
1116 llvm::StringSet<llvm::BumpPtrAllocator &> &usedAliases) {
1117 if (!usedAliases.count(alias)) {
1118 usedAliases.insert(alias);
1124 size_t probeSize = probeAlias.size();
1126 if (isdigit(alias.back())) {
1127 probeAlias.push_back(
'_');
1131 if (nameCounts[probeAlias] == 0)
1132 nameCounts[probeAlias] = 1;
1136 unsigned nameIndex = nameCounts[probeAlias]++;
1137 probeAlias += llvm::utostr(nameIndex);
1138 if (!usedAliases.count(probeAlias)) {
1139 usedAliases.insert(probeAlias);
1143 probeAlias.resize(probeSize);
1149void AliasInitializer::initializeAliases(
1150 llvm::MapVector<const void *, InProgressAliasInfo> &visitedSymbols,
1151 llvm::MapVector<const void *, SymbolAlias> &symbolToAlias) {
1153 unprocessedAliases = visitedSymbols.takeVector();
1154 llvm::stable_sort(unprocessedAliases, llvm::less_second());
1158 llvm::BumpPtrAllocator usedAliasAllocator;
1159 llvm::StringSet<llvm::BumpPtrAllocator &> usedAliases(usedAliasAllocator);
1161 llvm::StringMap<unsigned> nameCounts;
1162 for (
auto &[symbol, aliasInfo] : unprocessedAliases) {
1163 if (!aliasInfo.alias)
1165 StringRef alias = *aliasInfo.alias;
1166 unsigned nameIndex = uniqueAliasNameIndex(alias, nameCounts, usedAliases);
1167 symbolToAlias.insert(
1168 {symbol, SymbolAlias(alias, nameIndex, aliasInfo.isType,
1169 aliasInfo.canBeDeferred)});
1173void AliasInitializer::initialize(
1175 llvm::MapVector<const void *, SymbolAlias> &attrTypeToAlias) {
1179 DummyAliasOperationPrinter aliasPrinter(printerFlags, *
this);
1180 aliasPrinter.printCustomOrGenericOp(op);
1183 initializeAliases(aliases, attrTypeToAlias);
1186template <
typename T,
typename... PrintArgs>
1187std::pair<size_t, size_t> AliasInitializer::visitImpl(
1188 T value, llvm::MapVector<const void *, InProgressAliasInfo> &aliases,
1189 bool canBeDeferred, PrintArgs &&...
printArgs) {
1190 auto [it,
inserted] = aliases.try_emplace(value.getAsOpaquePointer());
1191 size_t aliasIndex = std::distance(aliases.begin(), it);
1195 markAliasNonDeferrable(aliasIndex);
1196 return {
static_cast<size_t>(it->second.aliasDepth), aliasIndex};
1200 generateAlias(value, it->second, canBeDeferred);
1201 it->second.isType = std::is_base_of_v<Type, T>;
1202 it->second.canBeDeferred = canBeDeferred;
1206 DummyAliasDialectAsmPrinter printer(*
this, canBeDeferred, childAliases);
1207 size_t maxAliasDepth =
1208 printer.printAndVisitNestedAliases(value,
printArgs...);
1211 it = std::next(aliases.begin(), aliasIndex);
1214 it->second.childIndices = std::move(childAliases);
1216 it->second.aliasDepth = maxAliasDepth + 1;
1219 return {(size_t)it->second.aliasDepth, aliasIndex};
1222void AliasInitializer::markAliasNonDeferrable(
size_t aliasIndex) {
1223 auto *it = std::next(aliases.begin(), aliasIndex);
1227 if (!it->second.canBeDeferred)
1230 it->second.canBeDeferred =
false;
1233 for (
size_t childIndex : it->second.childIndices)
1234 markAliasNonDeferrable(childIndex);
1237template <
typename T>
1238void AliasInitializer::generateAlias(T symbol, InProgressAliasInfo &alias,
1239 bool canBeDeferred) {
1242 OpAsmDialectInterface::AliasResult symbolInterfaceResult =
1243 OpAsmDialectInterface::AliasResult::NoAlias;
1244 using InterfaceT = std::conditional_t<std::is_base_of_v<Attribute, T>,
1245 OpAsmAttrInterface, OpAsmTypeInterface>;
1246 if (
auto symbolInterface = dyn_cast<InterfaceT>(symbol)) {
1247 symbolInterfaceResult = symbolInterface.getAlias(aliasOS);
1248 if (symbolInterfaceResult != OpAsmDialectInterface::AliasResult::NoAlias) {
1249 nameBuffer = std::move(aliasBuffer);
1250 assert(!nameBuffer.empty() &&
"expected valid alias name");
1254 if (symbolInterfaceResult != OpAsmDialectInterface::AliasResult::FinalAlias) {
1255 for (
const auto &interface : interfaces) {
1256 OpAsmDialectInterface::AliasResult
result =
1257 interface.getAlias(symbol, aliasOS);
1258 if (
result == OpAsmDialectInterface::AliasResult::NoAlias)
1260 nameBuffer = std::move(aliasBuffer);
1261 assert(!nameBuffer.empty() &&
"expected valid alias name");
1262 if (
result == OpAsmDialectInterface::AliasResult::FinalAlias)
1267 if (nameBuffer.empty())
1273 name = name.copy(aliasAllocator);
1274 alias = InProgressAliasInfo(name);
1287 initialize(Operation *op,
const OpPrintingFlags &printerFlags,
1288 DialectInterfaceCollection<OpAsmDialectInterface> &interfaces);
1292 LogicalResult getAlias(Attribute attr, raw_ostream &os)
const;
1296 LogicalResult getAlias(Type ty, raw_ostream &os)
const;
1300 void printNonDeferredAliases(AsmPrinter::Impl &p, NewLineCounter &newLine) {
1301 printAliases(p, newLine,
false);
1305 void printDeferredAliases(AsmPrinter::Impl &p, NewLineCounter &newLine) {
1306 printAliases(p, newLine,
true);
1312 void printAliases(AsmPrinter::Impl &p, NewLineCounter &newLine,
1316 llvm::MapVector<const void *, SymbolAlias> attrTypeToAlias;
1319 llvm::BumpPtrAllocator aliasAllocator;
1323void AliasState::initialize(
1326 AliasInitializer initializer(interfaces, aliasAllocator);
1327 initializer.initialize(op, printerFlags, attrTypeToAlias);
1332 if (it == attrTypeToAlias.end())
1334 it->second.print(os);
1340 if (it == attrTypeToAlias.end())
1342 if (!it->second.isPrinted)
1345 it->second.print(os);
1351 auto filterFn = [=](
const auto &aliasIt) {
1352 return aliasIt.second.canBeDeferred() == isDeferred;
1354 for (
auto &[opaqueSymbol, alias] :
1355 llvm::make_filter_range(attrTypeToAlias, filterFn)) {
1359 if (alias.isTypeAlias()) {
1362 alias.isPrinted =
true;
1392 enum :
unsigned { NameSentinel = ~0U };
1394 SSANameState(Operation *op,
const OpPrintingFlags &printerFlags);
1395 SSANameState() =
default;
1400 void printValueID(Value value,
bool printResultNo, raw_ostream &stream)
const;
1403 void printOperationID(Operation *op, raw_ostream &stream)
const;
1407 ArrayRef<int> getOpResultGroups(Operation *op);
1410 BlockInfo getBlockInfo(
Block *block);
1415 void shadowRegionArgs(Region ®ion,
ValueRange namesToUse);
1419 void numberValuesInRegion(Region ®ion);
1420 void numberValuesInBlock(
Block &block);
1421 void numberValuesInOp(Operation &op);
1427 void getResultIDAndNumber(OpResult
result, Value &lookupValue,
1428 std::optional<int> &lookupResultNo)
const;
1431 void setValueName(Value value, StringRef name);
1435 StringRef uniqueValueName(StringRef name);
1458 llvm::ScopedHashTable<StringRef, char> usedNames;
1459 llvm::BumpPtrAllocator usedNameAllocator;
1462 unsigned nextValueID = 0;
1464 unsigned nextArgumentID = 0;
1466 unsigned nextConflictID = 0;
1470 OpPrintingFlags printerFlags;
1475 : printerFlags(printerFlags) {
1476 llvm::SaveAndRestore valueIDSaver(nextValueID);
1477 llvm::SaveAndRestore argumentIDSaver(nextArgumentID);
1478 llvm::SaveAndRestore conflictIDSaver(nextConflictID);
1483 using UsedNamesScopeTy = llvm::ScopedHashTable<StringRef, char>::ScopeTy;
1484 using NamingContext =
1485 std::tuple<Region *, unsigned, unsigned, unsigned, UsedNamesScopeTy *>;
1488 llvm::BumpPtrAllocator allocator;
1491 auto *topLevelNamesScope =
1492 new (allocator.Allocate<UsedNamesScopeTy>()) UsedNamesScopeTy(usedNames);
1496 nameContext.push_back(std::make_tuple(®ion, nextValueID, nextArgumentID,
1497 nextConflictID, topLevelNamesScope));
1499 numberValuesInOp(*op);
1501 while (!nameContext.empty()) {
1503 UsedNamesScopeTy *parentScope;
1507 std::tie(region, std::ignore, std::ignore, std::ignore, parentScope) =
1508 nameContext.pop_back_val();
1510 std::tie(region, nextValueID, nextArgumentID, nextConflictID,
1511 parentScope) = nameContext.pop_back_val();
1515 while (usedNames.getCurScope() != parentScope) {
1516 usedNames.getCurScope()->~UsedNamesScopeTy();
1517 assert((usedNames.getCurScope() !=
nullptr || parentScope ==
nullptr) &&
1518 "top level parentScope must be a nullptr");
1522 auto *curNamesScope =
new (allocator.Allocate<UsedNamesScopeTy>())
1523 UsedNamesScopeTy(usedNames);
1525 numberValuesInRegion(*region);
1529 nameContext.push_back(std::make_tuple(®ion, nextValueID,
1530 nextArgumentID, nextConflictID,
1535 while (usedNames.getCurScope() !=
nullptr)
1536 usedNames.getCurScope()->~UsedNamesScopeTy();
1539void SSANameState::printValueID(
Value value,
bool printResultNo,
1542 stream <<
"<<NULL VALUE>>";
1546 std::optional<int> resultNo;
1547 auto lookupValue = value;
1551 if (OpResult
result = dyn_cast<OpResult>(value))
1552 getResultIDAndNumber(
result, lookupValue, resultNo);
1554 auto it = valueIDs.find(lookupValue);
1555 if (it == valueIDs.end()) {
1556 stream <<
"<<UNKNOWN SSA VALUE>>";
1561 if (it->second != NameSentinel) {
1562 stream << it->second;
1564 auto nameIt = valueNames.find(lookupValue);
1565 assert(nameIt != valueNames.end() &&
"Didn't have a name entry?");
1566 stream << nameIt->second;
1569 if (resultNo && printResultNo)
1570 stream <<
'#' << *resultNo;
1573void SSANameState::printOperationID(Operation *op, raw_ostream &stream)
const {
1574 auto it = operationIDs.find(op);
1575 if (it == operationIDs.end()) {
1576 stream <<
"<<UNKNOWN OPERATION>>";
1578 stream <<
'%' << it->second;
1582ArrayRef<int> SSANameState::getOpResultGroups(Operation *op) {
1583 auto it = opResultGroups.find(op);
1584 return it == opResultGroups.end() ? ArrayRef<int>() : it->second;
1587BlockInfo SSANameState::getBlockInfo(
Block *block) {
1588 auto it = blockNames.find(block);
1589 BlockInfo invalidBlock{-1,
"INVALIDBLOCK"};
1590 return it != blockNames.end() ? it->second : invalidBlock;
1593void SSANameState::shadowRegionArgs(Region ®ion,
ValueRange namesToUse) {
1594 assert(!region.
empty() &&
"cannot shadow arguments of an empty region");
1596 "incorrect number of names passed in");
1598 "only KnownIsolatedFromAbove ops can shadow names");
1600 SmallVector<char, 16> nameStr;
1601 for (
unsigned i = 0, e = namesToUse.size(); i != e; ++i) {
1602 auto nameToUse = namesToUse[i];
1603 if (nameToUse ==
nullptr)
1608 llvm::raw_svector_ostream nameStream(nameStr);
1609 printValueID(nameToUse,
true, nameStream);
1612 assert(valueIDs[nameToReplace] == NameSentinel);
1615 auto name = StringRef(nameStream.str()).drop_front();
1618 valueNames[nameToReplace] = name.copy(usedNameAllocator);
1624StringRef maybeGetValueNameFromLoc(Value value, StringRef name) {
1626 return maybeNameLoc.getName();
1631void SSANameState::numberValuesInRegion(Region ®ion) {
1633 bool opAsmOpInterfaceUsed =
false;
1634 auto setBlockArgNameFn = [&](Value arg, StringRef name) {
1635 assert(!valueIDs.count(arg) &&
"arg numbered multiple times");
1636 assert(llvm::cast<BlockArgument>(arg).getOwner()->getParent() == ®ion &&
1637 "arg not defined in current region");
1638 opAsmOpInterfaceUsed =
true;
1640 name = maybeGetValueNameFromLoc(arg, name);
1641 setValueName(arg, name);
1646 if (
auto asmInterface = dyn_cast<OpAsmOpInterface>(op))
1647 asmInterface.getAsmBlockArgumentNames(region, setBlockArgNameFn);
1649 if (!opAsmOpInterfaceUsed) {
1651 if (
auto interface = dyn_cast<OpAsmTypeInterface>(arg.
getType())) {
1652 interface.getAsmName(
1653 [&](StringRef name) { setBlockArgNameFn(arg, name); });
1661 unsigned nextBlockID = 0;
1662 for (
auto &block : region) {
1665 auto blockInfoIt = blockNames.insert({&block, {-1,
""}});
1666 if (blockInfoIt.second) {
1670 llvm::raw_string_ostream(name) <<
"^bb" << nextBlockID;
1671 blockInfoIt.first->second.name = StringRef(name).copy(usedNameAllocator);
1673 blockInfoIt.first->second.ordering = nextBlockID++;
1675 numberValuesInBlock(block);
1679void SSANameState::numberValuesInBlock(
Block &block) {
1683 SmallString<32> specialNameBuffer(isEntryBlock ?
"arg" :
"");
1684 llvm::raw_svector_ostream specialName(specialNameBuffer);
1686 if (valueIDs.count(arg))
1689 specialNameBuffer.resize(strlen(
"arg"));
1690 specialName << nextArgumentID++;
1692 StringRef specialNameStr = specialName.str();
1694 specialNameStr = maybeGetValueNameFromLoc(arg, specialNameStr);
1695 setValueName(arg, specialNameStr);
1699 for (
auto &op : block)
1700 numberValuesInOp(op);
1703void SSANameState::numberValuesInOp(Operation &op) {
1705 SmallVector<int, 2> resultGroups(1, 0);
1707 bool opAsmOpInterfaceUsed =
false;
1708 auto setResultNameFn = [&](Value
result, StringRef name) {
1709 assert(!valueIDs.count(
result) &&
"result numbered multiple times");
1710 assert(
result.getDefiningOp() == &op &&
"result not defined by 'op'");
1711 opAsmOpInterfaceUsed =
true;
1713 name = maybeGetValueNameFromLoc(
result, name);
1714 setValueName(
result, name);
1717 if (
int resultNo = llvm::cast<OpResult>(
result).getResultNumber())
1718 resultGroups.push_back(resultNo);
1721 auto setBlockNameFn = [&](
Block *block, StringRef name) {
1723 "getAsmBlockArgumentNames callback invoked on a block not directly "
1724 "nested under the current operation");
1725 assert(!blockNames.count(block) &&
"block numbered multiple times");
1726 SmallString<16> tmpBuffer{
"^"};
1728 if (name.data() != tmpBuffer.data()) {
1729 tmpBuffer.append(name);
1730 name = tmpBuffer.str();
1732 name = name.copy(usedNameAllocator);
1733 blockNames[block] = {-1, name};
1737 if (OpAsmOpInterface asmInterface = dyn_cast<OpAsmOpInterface>(&op)) {
1738 asmInterface.getAsmBlockNames(setBlockNameFn);
1739 asmInterface.getAsmResultNames(setResultNameFn);
1741 if (!opAsmOpInterfaceUsed) {
1744 bool allHaveOpAsmTypeInterface =
1746 return isa<OpAsmTypeInterface>(type);
1748 if (allHaveOpAsmTypeInterface) {
1750 auto interface = cast<OpAsmTypeInterface>(
result.
getType());
1751 interface.getAsmName(
1752 [&](StringRef name) { setResultNameFn(
result, name); });
1759 if (numResults == 0) {
1762 if (operationIDs.try_emplace(&op, nextValueID).second)
1771 setValueName(resultBegin, nameLoc.getName());
1776 if (valueIDs.try_emplace(resultBegin, nextValueID).second)
1780 if (resultGroups.size() != 1) {
1781 llvm::array_pod_sort(resultGroups.begin(), resultGroups.end());
1782 opResultGroups.try_emplace(&op, std::move(resultGroups));
1786void SSANameState::getResultIDAndNumber(
1787 OpResult
result, Value &lookupValue,
1788 std::optional<int> &lookupResultNo)
const {
1789 Operation *owner =
result.getOwner();
1792 int resultNo =
result.getResultNumber();
1796 auto resultGroupIt = opResultGroups.find(owner);
1797 if (resultGroupIt == opResultGroups.end()) {
1799 lookupResultNo = resultNo;
1805 ArrayRef<int> resultGroups = resultGroupIt->second;
1806 const auto *it = llvm::upper_bound(resultGroups, resultNo);
1807 int groupResultNo = 0, groupSize = 0;
1810 if (it == resultGroups.end()) {
1811 groupResultNo = resultGroups.back();
1812 groupSize =
static_cast<int>(owner->
getNumResults()) - resultGroups.back();
1815 groupResultNo = *std::prev(it);
1816 groupSize = *it - groupResultNo;
1821 lookupResultNo = resultNo - groupResultNo;
1822 lookupValue = owner->
getResult(groupResultNo);
1825void SSANameState::setValueName(Value value, StringRef name) {
1828 valueIDs[value] = nextValueID++;
1832 valueIDs[value] = NameSentinel;
1833 valueNames[value] = uniqueValueName(name);
1836StringRef SSANameState::uniqueValueName(StringRef name) {
1837 SmallString<16> tmpBuffer;
1841 if (!usedNames.count(name)) {
1842 name = name.copy(usedNameAllocator);
1847 SmallString<64> probeName(name);
1848 probeName.push_back(
'_');
1850 probeName += llvm::utostr(nextConflictID++);
1851 if (!usedNames.count(probeName)) {
1852 name = probeName.str().copy(usedNameAllocator);
1855 probeName.resize(name.size() + 1);
1859 usedNames.insert(name,
char());
1869class DistinctState {
1872 uint64_t getId(DistinctAttr distinctAttr);
1875 uint64_t distinctCounter = 0;
1880uint64_t DistinctState::getId(DistinctAttr distinctAttr) {
1882 distinctAttrMap.try_emplace(distinctAttr, distinctCounter);
1885 return it->getSecond();
1906 llvm_unreachable(
"unknown AsmResourceEntryKind");
1910 std::unique_ptr<ResourceCollection> &collection = keyToResources[key.str()];
1912 collection = std::make_unique<ResourceCollection>(key);
1916std::vector<std::unique_ptr<AsmResourcePrinter>>
1918 std::vector<std::unique_ptr<AsmResourcePrinter>> printers;
1919 for (
auto &it : keyToResources) {
1920 ResourceCollection *collection = it.second.get();
1922 return collection->buildResources(op, builder);
1924 printers.emplace_back(
1930LogicalResult FallbackAsmResourceMap::ResourceCollection::parseResource(
1934 FailureOr<AsmResourceBlob> blob = entry.
parseAsBlob();
1937 resources.emplace_back(entry.
getKey(), std::move(*blob));
1944 resources.emplace_back(entry.
getKey(), *value);
1947 case AsmResourceEntryKind::String: {
1951 resources.emplace_back(entry.
getKey(), std::move(*str));
1958void FallbackAsmResourceMap::ResourceCollection::buildResources(
1959 Operation *op, AsmResourceBuilder &builder)
const {
1960 for (
const auto &entry : resources) {
1961 if (
const auto *value = std::get_if<AsmResourceBlob>(&entry.value))
1963 else if (
const auto *value = std::get_if<bool>(&entry.value))
1965 else if (
const auto *value = std::get_if<std::string>(&entry.value))
1968 llvm_unreachable(
"unknown AsmResourceEntryKind");
1982 : interfaces(op->
getContext()), nameState(op, printerFlags),
1983 printerFlags(printerFlags), locationMap(locationMap) {}
1986 : interfaces(ctx), printerFlags(printerFlags), locationMap(locationMap) {}
1990 aliasState.initialize(op, printerFlags, interfaces);
2010 return llvm::make_pointee_range(externalResourcePrinters);
2020 (*locationMap)[op] = std::make_pair(line, col);
2026 return dialectResources;
2030 return success(cyclicPrintingStack.insert(opaquePointer));
2046 AliasState aliasState;
2049 SSANameState nameState;
2052 DistinctState distinctState;
2068template <
typename Range>
2072 [&stream](
const auto &dimSize) {
2073 if (ShapedType::isDynamic(dimSize))
2091 return printerFlags;
2095 auto parentThreadId = llvm::get_threadid();
2097 if (parentThreadId == llvm::get_threadid()) {
2099 diag.print(llvm::dbgs());
2100 llvm::dbgs() <<
"\n";
2108 <<
"' failed to verify and will be printed in generic form";
2112 return printerFlags;
2131 return impl->getPrinterFlags();
2135 std::unique_ptr<AsmResourcePrinter> printer) {
2136 impl->externalResourcePrinters.emplace_back(std::move(printer));
2141 return impl->getDialectResources();
2163 if (!isTopLevel && succeeded(
state.getAliasState().getAlias(loc,
os)))
2167 .Case([&](OpaqueLoc loc) {
2170 .Case([&](UnknownLoc loc) {
2178 os << loc.getFilename().getValue();
2181 if (loc.getEndColumn() == loc.getStartColumn() &&
2182 loc.getStartLine() == loc.getEndLine()) {
2183 os <<
':' << loc.getStartLine() <<
':' << loc.getStartColumn();
2186 if (loc.getStartLine() == loc.getEndLine()) {
2187 os <<
':' << loc.getStartLine() <<
':' << loc.getStartColumn()
2188 <<
" to :" << loc.getEndColumn();
2191 os <<
':' << loc.getStartLine() <<
':' << loc.getStartColumn() <<
" to "
2192 << loc.getEndLine() <<
':' << loc.getEndColumn();
2194 .Case([&](NameLoc loc) {
2198 auto childLoc = loc.getChildLoc();
2199 if (!llvm::isa<UnknownLoc>(childLoc)) {
2205 .Case([&](CallSiteLoc loc) {
2212 if (llvm::isa<NameLoc>(callee)) {
2213 if (llvm::isa<FileLineColLoc>(caller)) {
2231 if (
Attribute metadata = loc.getMetadata()) {
2238 printLocationInternal(loc, pretty);
2252 bool *printedHex =
nullptr) {
2257 bool isInf = apValue.isInfinity();
2258 bool isNaN = apValue.isNaN();
2259 if (!isInf && !isNaN) {
2261 apValue.toString(strValue, 6, 0,
2267 assert(((strValue[0] >=
'0' && strValue[0] <=
'9') ||
2268 ((strValue[0] ==
'-' || strValue[0] ==
'+') &&
2269 (strValue[1] >=
'0' && strValue[1] <=
'9'))) &&
2270 "[-+]?[0-9] regex does not match!");
2274 if (APFloat(apValue.getSemantics(), strValue).bitwiseIsEqual(apValue)) {
2282 apValue.toString(strValue);
2285 if (strValue.str().contains(
'.')) {
2296 APInt apInt = apValue.bitcastToAPInt();
2297 apInt.toString(str, 16,
false,
2317 if (symName.empty() || !isalpha(symName.front()))
2322 symName = symName.drop_while(
2323 [](
char c) {
return llvm::isAlnum(c) || c ==
'.' || c ==
'_'; });
2324 if (symName.empty())
2329 return symName.front() ==
'<' && symName.back() ==
'>';
2334 StringRef dialectName, StringRef symString) {
2335 os << symPrefix << dialectName;
2340 os <<
'.' << symString;
2344 os <<
'<' << symString <<
'>';
2353 if (name.empty() || (!isalpha(name[0]) && name[0] !=
'_'))
2355 return llvm::all_of(name.drop_front(), [](
unsigned char c) {
2356 return isalnum(c) || c ==
'_' || c ==
'$' || c ==
'.';
2371 printEscapedString(keyword, os);
2379 if (symbolRef.empty()) {
2380 os <<
"@<<INVALID EMPTY SYMBOL>>";
2393 os << R
"(dense_resource<__elided__>)";
2398 auto *
interface = cast<OpAsmDialectInterface>(resource.getDialect());
2404 return state.getAliasState().getAlias(attr,
os);
2408 return state.getAliasState().getAlias(type,
os);
2414 os <<
"<<NULL ATTRIBUTE>>";
2425 if (!isa<BuiltinDialect>(attr.
getDialect())) {
2427 }
else if (
auto opaqueAttr = llvm::dyn_cast<OpaqueAttr>(attr)) {
2429 opaqueAttr.getAttrData());
2430 }
else if (llvm::isa<UnitAttr>(attr)) {
2433 }
else if (
auto distinctAttr = llvm::dyn_cast<DistinctAttr>(attr)) {
2434 os <<
"distinct[" <<
state.getDistinctState().getId(distinctAttr) <<
"]<";
2440 }
else if (
auto dictAttr = llvm::dyn_cast<DictionaryAttr>(attr)) {
2446 }
else if (
auto intAttr = llvm::dyn_cast<IntegerAttr>(attr)) {
2447 Type intType = intAttr.getType();
2449 os << (intAttr.getValue().getBoolValue() ?
"true" :
"false");
2460 intAttr.getValue().print(
os, !isUnsigned);
2466 }
else if (
auto floatAttr = llvm::dyn_cast<FloatAttr>(attr)) {
2467 bool printedHex =
false;
2475 }
else if (
auto strAttr = llvm::dyn_cast<StringAttr>(attr)) {
2478 }
else if (
auto arrayAttr = llvm::dyn_cast<ArrayAttr>(attr)) {
2481 printAttribute(attr, AttrTypeElision::May);
2485 }
else if (
auto affineMapAttr = llvm::dyn_cast<AffineMapAttr>(attr)) {
2486 os <<
"affine_map<";
2487 affineMapAttr.getValue().print(
os);
2493 }
else if (
auto integerSetAttr = llvm::dyn_cast<IntegerSetAttr>(attr)) {
2494 os <<
"affine_set<";
2495 integerSetAttr.getValue().print(
os);
2501 }
else if (
auto typeAttr = llvm::dyn_cast<TypeAttr>(attr)) {
2504 }
else if (
auto refAttr = llvm::dyn_cast<SymbolRefAttr>(attr)) {
2511 }
else if (
auto intOrFpEltAttr =
2512 llvm::dyn_cast<DenseIntOrFPElementsAttr>(attr)) {
2513 if (
printerFlags.shouldElideElementsAttr(intOrFpEltAttr)) {
2520 Type eltType = intOrFpEltAttr.getElementType();
2521 if (isa<FloatType, IntegerType, IndexType, ComplexType>(eltType)) {
2525 cast<DenseElementType>(eltType));
2531 }
else if (
auto strEltAttr = llvm::dyn_cast<DenseStringElementsAttr>(attr)) {
2532 if (
printerFlags.shouldElideElementsAttr(strEltAttr)) {
2540 }
else if (
auto sparseEltAttr = llvm::dyn_cast<SparseElementsAttr>(attr)) {
2541 if (
printerFlags.shouldElideElementsAttr(sparseEltAttr.getIndices()) ||
2542 printerFlags.shouldElideElementsAttr(sparseEltAttr.getValues())) {
2547 if (
indices.getNumElements() != 0) {
2554 }
else if (
auto stridedLayoutAttr = llvm::dyn_cast<StridedLayoutAttr>(attr)) {
2555 stridedLayoutAttr.print(
os);
2556 }
else if (
auto denseArrayAttr = llvm::dyn_cast<DenseArrayAttr>(attr)) {
2558 printType(denseArrayAttr.getElementType());
2559 if (!denseArrayAttr.empty()) {
2565 }
else if (
auto resourceAttr =
2566 llvm::dyn_cast<DenseResourceElementsAttr>(attr)) {
2567 os <<
"dense_resource<";
2570 }
else if (
auto locAttr = llvm::dyn_cast<LocationAttr>(attr)) {
2573 llvm::report_fatal_error(
"Unknown builtin attribute");
2577 if (
auto typedAttr = llvm::dyn_cast<TypedAttr>(attr)) {
2578 Type attrType = typedAttr.getType();
2579 if (!llvm::isa<NoneType>(attrType)) {
2591 os << (value.getBoolValue() ?
"true" :
"false");
2601 return printEltFn(0);
2604 auto numElements = type.getNumElements();
2605 if (numElements == 0)
2613 int64_t rank = type.getRank();
2616 unsigned openBrackets = 0;
2618 auto shape = type.getShape();
2619 auto bumpCounter = [&] {
2621 ++counter[rank - 1];
2623 for (
unsigned i = rank - 1; i > 0; --i)
2624 if (counter[i] >=
shape[i]) {
2633 for (
unsigned idx = 0, e = numElements; idx != e; ++idx) {
2636 while (openBrackets++ < rank)
2638 openBrackets = rank;
2642 while (openBrackets-- > 0)
2648 if (
auto stringAttr = llvm::dyn_cast<DenseStringElementsAttr>(attr))
2657 auto type = attr.getType();
2658 auto elementType = type.getElementType();
2661 if (allowHex &&
printerFlags.shouldPrintElementsAttrWithHex(attr)) {
2663 if (llvm::endianness::native == llvm::endianness::big) {
2668 DenseIntOrFPElementsAttr::convertEndianOfArrayRefForBEmachine(
2669 rawData, convRawData, type);
2678 if (ComplexType complexTy = llvm::dyn_cast<ComplexType>(elementType)) {
2679 Type complexElementType = complexTy.getElementType();
2683 if (llvm::isa<IntegerType>(complexElementType)) {
2684 auto valueIt = attr.value_begin<std::complex<APInt>>();
2686 auto complexValue = *(valueIt + index);
2688 printDenseIntElement(complexValue.real(), os, complexElementType);
2690 printDenseIntElement(complexValue.imag(), os, complexElementType);
2694 auto valueIt = attr.value_begin<std::complex<APFloat>>();
2696 auto complexValue = *(valueIt + index);
2698 printFloatValue(complexValue.real(), os);
2700 printFloatValue(complexValue.imag(), os);
2704 }
else if (elementType.isIntOrIndex()) {
2705 auto valueIt = attr.value_begin<APInt>();
2707 printDenseIntElement(*(valueIt + index), os, elementType);
2710 assert(llvm::isa<FloatType>(elementType) &&
"unexpected element type");
2711 auto valueIt = attr.value_begin<APFloat>();
2713 printFloatValue(*(valueIt + index), os);
2719 DenseStringElementsAttr attr) {
2733 size_t bitSize = denseEltType.getDenseElementBitSize();
2734 size_t byteSize = llvm::divideCeil(bitSize,
static_cast<size_t>(CHAR_BIT));
2739 size_t offset = attr.isSplat() ? 0 : index * byteSize;
2740 ArrayRef<char> elemData = rawData.slice(offset, byteSize);
2741 Attribute elemAttr = denseEltType.convertToAttribute(elemData);
2742 printAttributeImpl(elemAttr);
2747 Type type = attr.getElementType();
2749 unsigned byteSize = bitwidth / 8;
2752 auto printElementAt = [&](
unsigned i) {
2753 APInt value(bitwidth, 0);
2755 llvm::LoadIntFromMemory(
2756 value,
reinterpret_cast<const uint8_t *
>(data.begin() + byteSize * i),
2763 APFloat fltVal(llvm::cast<FloatType>(type).getFloatSemantics(), value);
2767 llvm::interleaveComma(llvm::seq<unsigned>(0, attr.size()),
getStream(),
2773 os <<
"<<NULL TYPE>>";
2785 .Case([&](OpaqueType opaqueTy) {
2787 opaqueTy.getTypeData());
2789 .Case<IndexType>([&](
Type) {
os <<
"index"; })
2790 .Case<Float4E2M1FNType>([&](
Type) {
os <<
"f4E2M1FN"; })
2791 .Case<Float6E2M3FNType>([&](
Type) {
os <<
"f6E2M3FN"; })
2792 .Case<Float6E3M2FNType>([&](
Type) {
os <<
"f6E3M2FN"; })
2793 .Case<Float8E5M2Type>([&](
Type) {
os <<
"f8E5M2"; })
2794 .Case<Float8E4M3Type>([&](
Type) {
os <<
"f8E4M3"; })
2795 .Case<Float8E4M3FNType>([&](
Type) {
os <<
"f8E4M3FN"; })
2796 .Case<Float8E5M2FNUZType>([&](
Type) {
os <<
"f8E5M2FNUZ"; })
2797 .Case<Float8E4M3FNUZType>([&](
Type) {
os <<
"f8E4M3FNUZ"; })
2798 .Case<Float8E4M3B11FNUZType>([&](
Type) {
os <<
"f8E4M3B11FNUZ"; })
2799 .Case<Float8E3M4Type>([&](
Type) {
os <<
"f8E3M4"; })
2800 .Case<Float8E8M0FNUType>([&](
Type) {
os <<
"f8E8M0FNU"; })
2801 .Case<BFloat16Type>([&](
Type) {
os <<
"bf16"; })
2802 .Case<Float16Type>([&](
Type) {
os <<
"f16"; })
2803 .Case<FloatTF32Type>([&](
Type) {
os <<
"tf32"; })
2804 .Case<Float32Type>([&](
Type) {
os <<
"f32"; })
2805 .Case<Float64Type>([&](
Type) {
os <<
"f64"; })
2806 .Case<Float80Type>([&](
Type) {
os <<
"f80"; })
2807 .Case<Float128Type>([&](
Type) {
os <<
"f128"; })
2808 .Case([&](IntegerType integerTy) {
2809 if (integerTy.isSigned())
2811 else if (integerTy.isUnsigned())
2813 os <<
'i' << integerTy.getWidth();
2815 .Case([&](FunctionType funcTy) {
2820 if (results.size() == 1 && !llvm::isa<FunctionType>(results[0])) {
2828 .Case([&](VectorType vectorTy) {
2829 auto scalableDims = vectorTy.getScalableDims();
2831 auto vShape = vectorTy.getShape();
2832 unsigned lastDim = vShape.size();
2833 unsigned dimIdx = 0;
2834 for (dimIdx = 0; dimIdx < lastDim; dimIdx++) {
2835 if (!scalableDims.empty() && scalableDims[dimIdx])
2837 os << vShape[dimIdx];
2838 if (!scalableDims.empty() && scalableDims[dimIdx])
2845 .Case([&](RankedTensorType tensorTy) {
2848 if (!tensorTy.getShape().empty())
2852 if (tensorTy.getEncoding()) {
2858 .Case([&](UnrankedTensorType tensorTy) {
2863 .Case([&](MemRefType memrefTy) {
2866 if (!memrefTy.getShape().empty())
2869 MemRefLayoutAttrInterface layout = memrefTy.getLayout();
2870 if (!llvm::isa<AffineMapAttr>(layout) || !layout.isIdentity()) {
2875 if (memrefTy.getMemorySpace()) {
2885 if (memrefTy.getMemorySpace()) {
2891 .Case([&](ComplexType complexTy) {
2896 .Case([&](TupleType tupleTy) {
2899 [&](
Type type) { printType(type); });
2902 .Case<NoneType>([&](
Type) {
os <<
"none"; })
2903 .Case([&](GraphType graphTy) {
2908 if (results.size() == 1 && !isa<FunctionType, GraphType>(results[0])) {
2927 auto printFilteredAttributesFn = [&](
auto filteredAttrs) {
2930 os <<
" attributes";
2940 if (elidedAttrs.empty())
2941 return printFilteredAttributesFn(attrs);
2944 llvm::SmallDenseSet<StringRef> elidedAttrsSet(elidedAttrs.begin(),
2946 auto filteredAttrs = llvm::make_filter_range(attrs, [&](
NamedAttribute attr) {
2947 return !elidedAttrsSet.contains(attr.
getName().strref());
2949 if (!filteredAttrs.empty())
2950 printFilteredAttributesFn(filteredAttrs);
2957 if (llvm::isa<UnitAttr>(attr.
getValue()))
2968 std::string attrName;
2970 llvm::raw_string_ostream attrNameStr(attrName);
2980 dialect.printAttribute(attr, printer);
2989 std::string typeName;
2991 llvm::raw_string_ostream typeNameStr(typeName);
3001 dialect.printType(type, printer);
3008 llvm::printEscapedString(str,
os);
3013 os <<
"\"0x" << llvm::toHex(str) <<
"\"";
3020 return state.pushCyclicPrinting(opaquePointer);
3036 assert(
impl &&
"expected AsmPrinter::getStream to be overriden");
3037 return impl->getStream();
3041 assert(
impl &&
"expected AsmPrinter::printNewLine to be overriden");
3042 impl->printNewline();
3046 assert(
impl &&
"expected AsmPrinter::increaseIndent to be overriden");
3047 impl->increaseIndent();
3051 assert(
impl &&
"expected AsmPrinter::decreaseIndent to be overriden");
3052 impl->decreaseIndent();
3057 assert(
impl &&
"expected AsmPrinter::printFloat to be overriden");
3062 assert(
impl &&
"expected AsmPrinter::printType to be overriden");
3063 impl->printType(type);
3067 assert(
impl &&
"expected AsmPrinter::printAttribute to be overriden");
3068 impl->printAttribute(attr);
3072 assert(
impl &&
"expected AsmPrinter::printAlias to be overriden");
3073 return impl->printAlias(attr);
3077 assert(
impl &&
"expected AsmPrinter::printAlias to be overriden");
3078 return impl->printAlias(type);
3083 "expected AsmPrinter::printAttributeWithoutType to be overriden");
3088 assert(
impl &&
"expected AsmPrinter::printNamedAttribute to be overriden");
3089 impl->printNamedAttribute(attr);
3093 assert(
impl &&
"expected AsmPrinter::printKeywordOrString to be overriden");
3098 assert(
impl &&
"expected AsmPrinter::printString to be overriden");
3100 printEscapedString(keyword,
getStream());
3105 assert(
impl &&
"expected AsmPrinter::printSymbolName to be overriden");
3110 assert(
impl &&
"expected AsmPrinter::printResourceHandle to be overriden");
3111 impl->printResourceHandle(resource);
3119 return impl->pushCyclicPrinting(opaquePointer);
3136 const char *binopSpelling =
nullptr;
3139 unsigned pos = cast<AffineSymbolExpr>(expr).getPosition();
3141 printValueName(pos,
true);
3147 unsigned pos = cast<AffineDimExpr>(expr).getPosition();
3149 printValueName(pos,
false);
3155 os << cast<AffineConstantExpr>(expr).getValue();
3158 binopSpelling =
" + ";
3161 binopSpelling =
" * ";
3164 binopSpelling =
" floordiv ";
3167 binopSpelling =
" ceildiv ";
3170 binopSpelling =
" mod ";
3174 auto binOp = cast<AffineBinaryOpExpr>(expr);
3184 auto rhsConst = dyn_cast<AffineConstantExpr>(rhsExpr);
3186 rhsConst.getValue() == -1) {
3196 os << binopSpelling;
3210 if (
auto rhs = dyn_cast<AffineBinaryOpExpr>(rhsExpr)) {
3213 if (
auto rrhs = dyn_cast<AffineConstantExpr>(rrhsExpr)) {
3214 if (rrhs.getValue() == -1) {
3231 if (rrhs.getValue() < -1) {
3237 os <<
" * " << -rrhs.getValue();
3247 if (
auto rhsConst = dyn_cast<AffineConstantExpr>(rhsExpr)) {
3248 if (rhsConst.getValue() < 0) {
3250 os <<
" - " << -rhsConst.getValue();
3268 isEq ?
os <<
" == 0" :
os <<
" >= 0";
3274 for (
int i = 0; i < (int)map.
getNumDims() - 1; ++i)
3275 os <<
'd' << i <<
", ";
3284 os <<
's' << i <<
", ";
3293 [&](
AffineExpr expr) { printAffineExpr(expr); });
3300 for (
unsigned i = 1; i < set.
getNumDims(); ++i)
3301 os <<
'd' << i - 1 <<
", ";
3310 os <<
's' << i <<
", ";
3319 for (
int i = 1; i < numConstraints; ++i) {
3323 if (numConstraints >= 1)
3325 set.
isEq(numConstraints - 1));
3344 void printTopLevelOperation(
Operation *op);
3348 void printFullOpWithIndentAndLoc(
Operation *op);
3354 void printCustomOrGenericOp(
Operation *op)
override;
3356 void printGenericOp(
Operation *op,
bool printOpName)
override;
3359 void printBlockName(
Block *block);
3364 void print(
Block *block,
bool printBlockArgs =
true,
3365 bool printBlockTerminator =
true);
3368 void printValueID(
Value value,
bool printResultNo =
true,
3381 void printOptionalLocationSpecifier(
Location loc)
override {
3382 printTrailingLocation(loc);
3392 bool omitType =
false)
override;
3395 void printOperand(Value value)
override { printValueID(value); }
3396 void printOperand(Value value, raw_ostream &os)
override {
3397 printValueID(value,
true, &os);
3401 void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
3402 ArrayRef<StringRef> elidedAttrs = {})
override {
3403 Impl::printOptionalAttrDict(attrs, elidedAttrs);
3405 void printOptionalAttrDictWithKeyword(
3406 ArrayRef<NamedAttribute> attrs,
3407 ArrayRef<StringRef> elidedAttrs = {})
override {
3408 Impl::printOptionalAttrDict(attrs, elidedAttrs,
3413 void printSuccessor(
Block *successor)
override;
3417 void printSuccessorAndUseList(
Block *successor,
3421 void printRegion(Region ®ion,
bool printEntryBlockArgs,
3422 bool printBlockTerminators,
bool printEmptyBlock)
override;
3428 void shadowRegionArgs(Region ®ion,
ValueRange namesToUse)
override {
3434 void printAffineMapOfSSAIds(AffineMapAttr mapAttr,
3439 void printAffineExprOfSSAIds(AffineExpr expr,
ValueRange dimOperands,
3443 void printUsersComment(Operation *op);
3446 void printUsersComment(BlockArgument arg);
3449 void printValueUsers(Value value);
3453 void printUserIDs(Operation *user,
bool prefixComma =
false);
3458 class ResourceBuilder :
public AsmResourceBuilder {
3461 using PrintFn =
function_ref<void(StringRef, ValueFn)>;
3463 ResourceBuilder(PrintFn printFn) : printFn(printFn) {}
3464 ~ResourceBuilder()
override =
default;
3466 void buildBool(StringRef key,
bool data)
final {
3467 printFn(key, [&](raw_ostream &os) { os << (data ?
"true" :
"false"); });
3470 void buildString(StringRef key, StringRef data)
final {
3471 printFn(key, [&](raw_ostream &os) {
3473 llvm::printEscapedString(data, os);
3478 void buildBlob(StringRef key, ArrayRef<char> data,
3479 uint32_t dataAlignment)
final {
3480 printFn(key, [&](raw_ostream &os) {
3482 llvm::support::ulittle32_t dataAlignmentLE(dataAlignment);
3484 << llvm::toHex(StringRef(
reinterpret_cast<char *
>(&dataAlignmentLE),
3485 sizeof(dataAlignment)))
3486 << llvm::toHex(StringRef(data.data(), data.size())) <<
"\"";
3495 void printFileMetadataDictionary(Operation *op);
3501 void printResourceFileMetadata(
function_ref<
void()> checkAddMetadataDict,
3509 SmallVector<StringRef> defaultDialectStack{
"builtin"};
3513void OperationPrinter::printTopLevelOperation(Operation *op) {
3515 state.
getAliasState().printNonDeferredAliases(*
this, newLine);
3518 printFullOpWithIndentAndLoc(op);
3525 printFileMetadataDictionary(op);
3528void OperationPrinter::printFileMetadataDictionary(Operation *op) {
3529 bool sawMetadataEntry =
false;
3530 auto checkAddMetadataDict = [&] {
3531 if (!std::exchange(sawMetadataEntry,
true))
3532 os << newLine <<
"{-#" << newLine;
3536 printResourceFileMetadata(checkAddMetadataDict, op);
3539 if (sawMetadataEntry)
3540 os << newLine <<
"#-}" << newLine;
3543void OperationPrinter::printResourceFileMetadata(
3544 function_ref<
void()> checkAddMetadataDict, Operation *op) {
3546 bool hadResource =
false;
3547 bool needResourceComma =
false;
3548 bool needEntryComma =
false;
3549 auto processProvider = [&](StringRef dictName, StringRef name,
auto &provider,
3550 auto &&...providerArgs) {
3551 bool hadEntry =
false;
3552 auto printFn = [&](StringRef key, ResourceBuilder::ValueFn valueFn) {
3553 checkAddMetadataDict();
3555 std::string resourceStr;
3556 auto printResourceStr = [&](raw_ostream &os) { os << resourceStr; };
3557 std::optional<uint64_t> charLimit =
3559 if (charLimit.has_value()) {
3561 if (charLimit.value() == 0)
3564 llvm::raw_string_ostream ss(resourceStr);
3568 if (resourceStr.size() > charLimit.value())
3572 valueFn = printResourceStr;
3576 if (!std::exchange(hadResource,
true)) {
3577 if (needResourceComma)
3578 os <<
"," << newLine;
3579 os <<
" " << dictName <<
"_resources: {" << newLine;
3582 if (!std::exchange(hadEntry,
true)) {
3584 os <<
"," << newLine;
3585 os <<
" " << name <<
": {" << newLine;
3587 os <<
"," << newLine;
3595 ResourceBuilder entryBuilder(printFn);
3596 provider.buildResources(op, providerArgs..., entryBuilder);
3598 needEntryComma |= hadEntry;
3600 os << newLine <<
" }";
3607 StringRef name = interface.getDialect()->getNamespace();
3608 auto it = dialectResources.find(interface.getDialect());
3609 if (it != dialectResources.end())
3610 processProvider(
"dialect", name, interface, it->second);
3612 processProvider(
"dialect", name, interface,
3616 os << newLine <<
" }";
3620 needEntryComma =
false;
3621 needResourceComma = hadResource;
3622 hadResource =
false;
3624 processProvider(
"external", printer.getName(), printer);
3626 os << newLine <<
" }";
3634void OperationPrinter::printRegionArgument(BlockArgument arg,
3635 ArrayRef<NamedAttribute> argAttrs,
3642 printOptionalAttrDict(argAttrs);
3644 printTrailingLocation(arg.
getLoc(),
false);
3647void OperationPrinter::printFullOpWithIndentAndLoc(Operation *op) {
3651 os.indent(currentIndent);
3653 printTrailingLocation(op->
getLoc());
3655 printUsersComment(op);
3658void OperationPrinter::printFullOp(Operation *op) {
3660 auto printResultGroup = [&](
size_t resultNo,
size_t resultCount) {
3661 printValueID(op->
getResult(resultNo),
false);
3662 if (resultCount > 1)
3663 os <<
':' << resultCount;
3667 ArrayRef<int> resultGroups = state.
getSSANameState().getOpResultGroups(op);
3668 if (!resultGroups.empty()) {
3671 interleaveComma(llvm::seq<int>(0, resultGroups.size() - 1), [&](
int i) {
3672 printResultGroup(resultGroups[i],
3673 resultGroups[i + 1] - resultGroups[i]);
3676 printResultGroup(resultGroups.back(), numResults - resultGroups.back());
3679 printResultGroup(0, numResults);
3685 printCustomOrGenericOp(op);
3688void OperationPrinter::printUsersComment(Operation *op) {
3692 printOperationID(op);
3693 }
else if (numResults && op->
use_empty()) {
3695 }
else if (numResults && !op->
use_empty()) {
3698 unsigned usedInNResults = 0;
3699 unsigned usedInNOperations = 0;
3700 SmallPtrSet<Operation *, 1> userSet;
3701 for (Operation *user : op->
getUsers()) {
3702 if (userSet.insert(user).second) {
3703 ++usedInNOperations;
3704 usedInNResults += user->getNumResults();
3709 bool exactlyOneUniqueUse =
3710 usedInNResults <= 1 && usedInNOperations <= 1 && numResults == 1;
3711 os <<
" // " << (exactlyOneUniqueUse ?
"user" :
"users") <<
": ";
3712 bool shouldPrintBrackets = numResults > 1;
3713 auto printOpResult = [&](OpResult opResult) {
3714 if (shouldPrintBrackets)
3716 printValueUsers(opResult);
3717 if (shouldPrintBrackets)
3721 interleaveComma(op->
getResults(), printOpResult);
3725void OperationPrinter::printUsersComment(BlockArgument arg) {
3731 os <<
" is used by ";
3732 printValueUsers(arg);
3737void OperationPrinter::printValueUsers(Value value) {
3743 SmallPtrSet<Operation *, 1> userSet;
3745 if (userSet.insert(user).second)
3746 printUserIDs(user, index);
3750void OperationPrinter::printUserIDs(Operation *user,
bool prefixComma) {
3755 printOperationID(user);
3758 [
this](Value
result) { printValueID(result); });
3762void OperationPrinter::printCustomOrGenericOp(Operation *op) {
3768 opInfo->printAssembly(op, *
this, defaultDialectStack.back());
3773 if (
auto opPrinter = dialect->getOperationPrinter(op)) {
3778 if (name.count(
'.') == 1)
3779 name.consume_front((defaultDialectStack.back() +
".").str());
3783 opPrinter(op, *
this);
3790 printGenericOp(op,
true);
3793void OperationPrinter::printGenericOp(Operation *op,
bool printOpName) {
3797 interleaveComma(op->
getOperands(), [&](Value value) { printValueID(value); });
3804 [&](
Block *successor) { printBlockName(successor); });
3818 interleaveComma(op->
getRegions(), [&](Region ®ion) {
3819 printRegion(region, true,
3834void OperationPrinter::printBlockName(
Block *block) {
3838void OperationPrinter::print(
Block *block,
bool printBlockArgs,
3839 bool printBlockTerminator) {
3841 if (printBlockArgs) {
3842 os.indent(currentIndent);
3843 printBlockName(block);
3848 interleaveComma(block->
getArguments(), [&](BlockArgument arg) {
3851 printType(arg.getType());
3853 printTrailingLocation(arg.getLoc(), false);
3861 os <<
" // block is not in a region!";
3864 os <<
" // no predecessors";
3867 printBlockName(pred);
3871 SmallVector<BlockInfo, 4> predIDs;
3874 llvm::sort(predIDs, [](BlockInfo
lhs, BlockInfo
rhs) {
3875 return lhs.ordering <
rhs.ordering;
3878 os <<
" // " << predIDs.size() <<
" preds: ";
3880 interleaveComma(predIDs, [&](BlockInfo pred) { os << pred.name; });
3885 currentIndent += indentWidth;
3889 os.indent(currentIndent);
3890 printUsersComment(arg);
3894 bool hasTerminator =
3896 auto range = llvm::make_range(
3898 std::prev(block->
end(),
3899 (!hasTerminator || printBlockTerminator) ? 0 : 1));
3900 for (
auto &op : range) {
3901 printFullOpWithIndentAndLoc(&op);
3904 currentIndent -= indentWidth;
3907void OperationPrinter::printValueID(Value value,
bool printResultNo,
3908 raw_ostream *streamOverride)
const {
3910 streamOverride ? *streamOverride : os);
3913void OperationPrinter::printOperationID(Operation *op,
3914 raw_ostream *streamOverride)
const {
3915 state.
getSSANameState().printOperationID(op, streamOverride ? *streamOverride
3919void OperationPrinter::printSuccessor(
Block *successor) {
3920 printBlockName(successor);
3923void OperationPrinter::printSuccessorAndUseList(
Block *successor,
3925 printBlockName(successor);
3926 if (succOperands.empty())
3930 interleaveComma(succOperands,
3931 [
this](Value operand) { printValueID(operand); });
3933 interleaveComma(succOperands,
3938void OperationPrinter::printRegion(Region ®ion,
bool printEntryBlockArgs,
3939 bool printBlockTerminators,
3940 bool printEmptyBlock) {
3945 os <<
"{" << newLine;
3946 if (!region.
empty()) {
3947 llvm::scope_exit restoreDefaultDialect(
3948 [&]() { defaultDialectStack.pop_back(); });
3949 if (
auto iface = dyn_cast<OpAsmOpInterface>(region.
getParentOp()))
3950 defaultDialectStack.push_back(iface.getDefaultDialect());
3952 defaultDialectStack.push_back(
"");
3954 auto *entryBlock = ®ion.
front();
3958 bool shouldAlwaysPrintBlockHeader =
3959 (printEmptyBlock && entryBlock->empty()) ||
3960 (printEntryBlockArgs && entryBlock->getNumArguments() != 0);
3961 print(entryBlock, shouldAlwaysPrintBlockHeader, printBlockTerminators);
3962 for (
auto &
b : llvm::drop_begin(region.
getBlocks(), 1))
3965 os.indent(currentIndent) <<
"}";
3968void OperationPrinter::printAffineMapOfSSAIds(AffineMapAttr mapAttr,
3971 os <<
"<<NULL AFFINE MAP>>";
3974 AffineMap map = mapAttr.getValue();
3976 auto printValueName = [&](
unsigned pos,
bool isSymbol) {
3977 unsigned index = isSymbol ? numDims + pos : pos;
3978 assert(index < operands.size());
3981 printValueID(operands[index]);
3986 interleaveComma(map.
getResults(), [&](AffineExpr expr) {
3987 printAffineExpr(expr, printValueName);
3991void OperationPrinter::printAffineExprOfSSAIds(AffineExpr expr,
3994 auto printValueName = [&](
unsigned pos,
bool isSymbol) {
3996 return printValueID(dimOperands[pos]);
3998 printValueID(symOperands[pos]);
4001 printAffineExpr(expr, printValueName);
4010 os <<
"<<NULL ATTRIBUTE>>";
4015 print(os, state, elideType);
4021 : AttrTypeElision::Never);
4025 print(llvm::errs());
4026 llvm::errs() <<
"\n";
4031 os <<
"<<NULL ATTRIBUTE>>";
4040 uint64_t posPrior = os.tell();
4042 dialect.printAttribute(*
this, printer);
4043 if (posPrior != os.tell())
4052 os <<
"<<NULL ATTRIBUTE>>";
4062 os <<
"<<NULL TYPE>>";
4074 print(llvm::errs());
4075 llvm::errs() <<
"\n";
4079 print(llvm::errs());
4080 llvm::errs() <<
"\n";
4084 print(llvm::errs());
4085 llvm::errs() <<
"\n";
4090 os <<
"<<NULL AFFINE EXPR>>";
4098 print(llvm::errs());
4099 llvm::errs() <<
"\n";
4104 os <<
"<<NULL AFFINE MAP>>";
4119 os <<
"<<NULL VALUE>>";
4124 return op->
print(os, flags);
4127 os <<
"<block argument> of type '" << arg.
getType()
4132 os <<
"<<NULL VALUE>>";
4137 return op->
print(os, state);
4141 os <<
"<block argument> of type '" << arg.
getType()
4146 print(llvm::errs());
4147 llvm::errs() <<
"\n";
4178 if (
auto result = llvm::dyn_cast<OpResult>(*
this)) {
4181 op = llvm::cast<BlockArgument>(*this).getOwner()->
getParentOp();
4183 os <<
"<<UNKNOWN SSA VALUE>>";
4199 OperationPrinter printer(os, state.
getImpl());
4202 printer.printTopLevelOperation(
this);
4204 printer.printFullOpWithIndentAndLoc(
this);
4210 llvm::errs() <<
"\n";
4215 llvm::errs() <<
"\n";
4221 os <<
"<<UNLINKED BLOCK>>\n";
4232 OperationPrinter(os, state.
getImpl()).print(
this);
4241 os <<
"<<UNLINKED BLOCK>>\n";
4248 OperationPrinter printer(os, state.
getImpl());
4249 printer.printBlockName(
this);
4264 if (dimensions.empty())
4267 if (dimensions.empty())
4277 <<
"Failed parsing dimension list.";
4288 <<
"Failed parsing dimension list.";
4290 if (shapeArr.empty()) {
4292 <<
"Failed parsing dimension list. Did you mean an empty list? It "
4293 "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)
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)
void printDenseIntOrFPElementsAttr(DenseIntOrFPElementsAttr attr, bool allowHex)
Print a dense elements attribute in the literal-first syntax.
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.
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 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...