31#include "llvm/ADT/APFloat.h"
32#include "llvm/ADT/ArrayRef.h"
33#include "llvm/ADT/DenseMap.h"
34#include "llvm/ADT/MapVector.h"
35#include "llvm/ADT/STLExtras.h"
36#include "llvm/ADT/ScopeExit.h"
37#include "llvm/ADT/ScopedHashTable.h"
38#include "llvm/ADT/SetVector.h"
39#include "llvm/ADT/StringExtras.h"
40#include "llvm/ADT/StringSet.h"
41#include "llvm/ADT/TypeSwitch.h"
42#include "llvm/Support/CommandLine.h"
43#include "llvm/Support/DebugLog.h"
44#include "llvm/Support/Endian.h"
45#include "llvm/Support/ManagedStatic.h"
46#include "llvm/Support/Regex.h"
47#include "llvm/Support/SaveAndRestore.h"
48#include "llvm/Support/Threading.h"
49#include "llvm/Support/raw_ostream.h"
58#define DEBUG_TYPE "mlir-asm-printer"
99 *this << (operand ? operand.getType() : Type());
115 *this << (result ? result.getType() : Type());
127#include "mlir/IR/OpAsmAttrInterface.cpp.inc"
128#include "mlir/IR/OpAsmOpInterface.cpp.inc"
129#include "mlir/IR/OpAsmTypeInterface.cpp.inc"
133 return entry.
emitError() <<
"unknown 'resource' key '" << entry.
getKey()
134 <<
"' for dialect '" << getDialect()->getNamespace()
146struct AsmPrinterOptions {
147 llvm::cl::opt<int64_t> printElementsAttrWithHexIfLarger{
148 "mlir-print-elementsattrs-with-hex-if-larger",
150 "Print DenseElementsAttrs with a hex string that have "
151 "more elements than the given upper limit (use -1 to disable)")};
153 llvm::cl::opt<unsigned> elideElementsAttrIfLarger{
154 "mlir-elide-elementsattrs-if-larger",
155 llvm::cl::desc(
"Elide ElementsAttrs with \"...\" that have "
156 "more elements than the given upper limit")};
158 llvm::cl::opt<unsigned> elideResourceStringsIfLarger{
159 "mlir-elide-resource-strings-if-larger",
161 "Elide printing value of resources if string is too long in chars.")};
163 llvm::cl::opt<bool> printDebugInfoOpt{
164 "mlir-print-debuginfo", llvm::cl::init(
false),
165 llvm::cl::desc(
"Print debug info in MLIR output")};
167 llvm::cl::opt<bool> printPrettyDebugInfoOpt{
168 "mlir-pretty-debuginfo", llvm::cl::init(
false),
169 llvm::cl::desc(
"Print pretty debug info in MLIR output")};
173 llvm::cl::opt<bool> printGenericOpFormOpt{
174 "mlir-print-op-generic", llvm::cl::init(
false),
175 llvm::cl::desc(
"Print the generic op form"), llvm::cl::Hidden};
177 llvm::cl::opt<bool> assumeVerifiedOpt{
178 "mlir-print-assume-verified", llvm::cl::init(
false),
179 llvm::cl::desc(
"Skip op verification when using custom printers"),
182 llvm::cl::opt<bool> printLocalScopeOpt{
183 "mlir-print-local-scope", llvm::cl::init(
false),
184 llvm::cl::desc(
"Print with local scope and inline information (eliding "
185 "aliases for attributes, types, and locations)")};
187 llvm::cl::opt<bool> skipRegionsOpt{
188 "mlir-print-skip-regions", llvm::cl::init(
false),
189 llvm::cl::desc(
"Skip regions when printing ops.")};
191 llvm::cl::opt<bool> printValueUsers{
192 "mlir-print-value-users", llvm::cl::init(
false),
194 "Print users of operation results and block arguments as a comment")};
196 llvm::cl::opt<bool> printUniqueSSAIDs{
197 "mlir-print-unique-ssa-ids", llvm::cl::init(
false),
198 llvm::cl::desc(
"Print unique SSA ID numbers for values, block arguments "
199 "and naming conflicts across all regions")};
201 llvm::cl::opt<bool> useNameLocAsPrefix{
202 "mlir-use-nameloc-as-prefix", llvm::cl::init(
false),
203 llvm::cl::desc(
"Print SSA IDs using NameLocs as prefixes")};
218 : printDebugInfoFlag(
false), printDebugInfoPrettyFormFlag(
false),
219 printGenericOpFormFlag(
false), skipRegionsFlag(
false),
220 assumeVerifiedFlag(
false), printLocalScope(
false),
221 printValueUsersFlag(
false), printUniqueSSAIDsFlag(
false),
222 useNameLocAsPrefix(
false) {
226 if (
clOptions->elideElementsAttrIfLarger.getNumOccurrences())
227 elementsAttrElementLimit =
clOptions->elideElementsAttrIfLarger;
228 if (
clOptions->printElementsAttrWithHexIfLarger.getNumOccurrences())
229 elementsAttrHexElementLimit =
230 clOptions->printElementsAttrWithHexIfLarger.getValue();
231 if (
clOptions->elideResourceStringsIfLarger.getNumOccurrences())
232 resourceStringCharLimit =
clOptions->elideResourceStringsIfLarger;
233 printDebugInfoFlag =
clOptions->printDebugInfoOpt;
234 printDebugInfoPrettyFormFlag =
clOptions->printPrettyDebugInfoOpt;
235 printGenericOpFormFlag =
clOptions->printGenericOpFormOpt;
236 assumeVerifiedFlag =
clOptions->assumeVerifiedOpt;
237 printLocalScope =
clOptions->printLocalScopeOpt;
238 skipRegionsFlag =
clOptions->skipRegionsOpt;
239 printValueUsersFlag =
clOptions->printValueUsers;
240 printUniqueSSAIDsFlag =
clOptions->printUniqueSSAIDs;
241 useNameLocAsPrefix =
clOptions->useNameLocAsPrefix;
250 elementsAttrElementLimit = largeElementLimit;
256 elementsAttrHexElementLimit = largeElementLimit;
262 resourceStringCharLimit = largeResourceLimit;
270 printDebugInfoFlag = enable;
271 printDebugInfoPrettyFormFlag = prettyForm;
277 printGenericOpFormFlag = enable;
283 skipRegionsFlag = skip;
289 assumeVerifiedFlag = enable;
297 printLocalScope = enable;
303 printValueUsersFlag = enable;
310 printUniqueSSAIDsFlag = enable;
316 return elementsAttrElementLimit &&
317 *elementsAttrElementLimit <
int64_t(attr.getNumElements()) &&
318 !llvm::isa<SplatElementsAttr>(attr);
324 return (elementsAttrHexElementLimit != -1) &&
325 (elementsAttrHexElementLimit <
int64_t(attr.getNumElements())) &&
326 !llvm::isa<SplatElementsAttr>(attr);
330 useNameLocAsPrefix = enable;
336 return elementsAttrElementLimit;
341 return elementsAttrHexElementLimit;
346 return resourceStringCharLimit;
351 return printDebugInfoFlag;
356 return printDebugInfoPrettyFormFlag;
361 return printGenericOpFormFlag;
369 return assumeVerifiedFlag;
377 return printValueUsersFlag;
387 return useNameLocAsPrefix;
398struct NewLineCounter {
399 unsigned curLine = 1;
436 template <
typename Container,
typename UnaryFunctor>
438 llvm::interleaveComma(c,
os, eachFn);
485 function_ref<
void(
unsigned,
bool)> printValueName =
nullptr);
498 bool withKeyword =
false);
501 bool isTopLevel =
false);
519 DenseElementType denseEltType);
543 function_ref<
void(
unsigned,
bool)> printValueName =
nullptr);
573 SymbolAlias(StringRef name, uint32_t suffixIndex,
bool isType,
575 : name(name), suffixIndex(suffixIndex), isType(isType),
576 isDeferrable(isDeferrable) {}
580 os << (isType ?
"!" :
"#") << name;
582 if (isdigit(name.back()))
589 bool isTypeAlias()
const {
return isType; }
592 bool canBeDeferred()
const {
return isDeferrable; }
598 uint32_t suffixIndex : 30;
602 bool isDeferrable : 1;
606 bool isPrinted =
false;
612class AliasInitializer {
615 DialectInterfaceCollection<OpAsmDialectInterface> &interfaces,
616 llvm::BumpPtrAllocator &aliasAllocator)
617 : interfaces(interfaces), aliasAllocator(aliasAllocator),
618 aliasOS(aliasBuffer) {}
620 void initialize(Operation *op,
const OpPrintingFlags &printerFlags,
621 llvm::MapVector<const void *, SymbolAlias> &attrTypeToAlias);
629 std::pair<size_t, size_t>
visit(Attribute attr,
bool canBeDeferred =
false,
630 bool elideType =
false) {
631 return visitImpl(attr, aliases, canBeDeferred, elideType);
638 std::pair<size_t, size_t>
visit(Type type,
bool canBeDeferred =
false) {
639 return visitImpl(type, aliases, canBeDeferred);
643 struct InProgressAliasInfo {
644 InProgressAliasInfo()
645 : aliasDepth(0), isType(
false), canBeDeferred(
false) {}
646 InProgressAliasInfo(StringRef alias)
647 : alias(alias), aliasDepth(1), isType(
false), canBeDeferred(
false) {}
651 if (aliasDepth !=
rhs.aliasDepth)
652 return aliasDepth <
rhs.aliasDepth;
653 if (isType !=
rhs.isType)
655 return alias <
rhs.alias;
660 std::optional<StringRef> alias;
663 unsigned aliasDepth : 30;
667 bool canBeDeferred : 1;
669 SmallVector<size_t> childIndices;
677 template <
typename T,
typename... PrintArgs>
678 std::pair<size_t, size_t>
680 llvm::MapVector<const void *, InProgressAliasInfo> &aliases,
681 bool canBeDeferred, PrintArgs &&...
printArgs);
684 void markAliasNonDeferrable(
size_t aliasIndex);
688 template <
typename T>
689 void generateAlias(T symbol, InProgressAliasInfo &alias,
bool canBeDeferred);
694 uniqueAliasNameIndex(StringRef alias, llvm::StringMap<unsigned> &nameCounts,
695 llvm::StringSet<llvm::BumpPtrAllocator &> &usedAliases);
699 static void initializeAliases(
700 llvm::MapVector<const void *, InProgressAliasInfo> &visitedSymbols,
701 llvm::MapVector<const void *, SymbolAlias> &symbolToAlias);
704 DialectInterfaceCollection<OpAsmDialectInterface> &interfaces;
707 llvm::BumpPtrAllocator &aliasAllocator;
710 llvm::MapVector<const void *, InProgressAliasInfo> aliases;
713 SmallString<32> aliasBuffer;
714 llvm::raw_svector_ostream aliasOS;
722class DummyAliasOperationPrinter :
private OpAsmPrinter {
724 explicit DummyAliasOperationPrinter(
const OpPrintingFlags &printerFlags,
725 AliasInitializer &initializer)
726 : printerFlags(printerFlags), initializer(initializer) {}
730 void printCustomOrGenericOp(Operation *op)
override {
732 if (printerFlags.shouldPrintDebugInfo())
733 initializer.visit(op->
getLoc(),
true);
736 if (!printerFlags.shouldPrintGenericOpForm()) {
747 void printGenericOp(Operation *op,
bool printOpName =
true)
override {
749 if (!printerFlags.shouldSkipRegions()) {
759 if (operand && operand.getType())
765 for (
const NamedAttribute &attr : op->
getAttrs())
766 printAttribute(attr.getValue());
772 void print(
Block *block,
bool printBlockArgs =
true,
773 bool printBlockTerminator =
true) {
776 if (printBlockArgs) {
781 if (printerFlags.shouldPrintDebugInfo())
783 initializer.visit(arg.getLoc(),
false);
791 auto range = llvm::make_range(
793 std::prev(block->
end(),
794 (!hasTerminator || printBlockTerminator) ? 0 : 1));
795 for (Operation &op : range)
796 printCustomOrGenericOp(&op);
800 void printRegion(Region ®ion,
bool printEntryBlockArgs,
801 bool printBlockTerminators,
802 bool printEmptyBlock =
false)
override {
805 if (printerFlags.shouldSkipRegions()) {
810 auto *entryBlock = ®ion.
front();
811 print(entryBlock, printEntryBlockArgs, printBlockTerminators);
812 for (
Block &
b : llvm::drop_begin(region, 1))
816 void printRegionArgument(BlockArgument arg, ArrayRef<NamedAttribute> argAttrs,
817 bool omitType)
override {
820 if (printerFlags.shouldPrintDebugInfo())
822 initializer.visit(arg.
getLoc(),
false);
828 initializer.visit(type);
832 void printAttribute(Attribute attr)
override { initializer.visit(attr); }
833 void printAttributeWithoutType(Attribute attr)
override {
834 printAttribute(attr);
836 void printNamedAttribute(NamedAttribute attr)
override {
840 LogicalResult printAlias(Attribute attr)
override {
841 initializer.visit(attr);
844 LogicalResult printAlias(Type type)
override {
845 initializer.visit(type);
850 void printOptionalLocationSpecifier(Location loc)
override {
856 void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
857 ArrayRef<StringRef> elidedAttrs = {})
override {
860 if (elidedAttrs.empty()) {
861 for (
const NamedAttribute &attr : attrs)
862 printAttribute(attr.getValue());
865 llvm::SmallDenseSet<StringRef> elidedAttrsSet(elidedAttrs.begin(),
867 for (
const NamedAttribute &attr : attrs)
868 if (!elidedAttrsSet.contains(attr.getName().strref()))
869 printAttribute(attr.getValue());
871 void printOptionalAttrDictWithKeyword(
872 ArrayRef<NamedAttribute> attrs,
873 ArrayRef<StringRef> elidedAttrs = {})
override {
874 printOptionalAttrDict(attrs, elidedAttrs);
879 raw_ostream &getStream()
const override {
return os; }
883 void printFloat(
const APFloat &)
override {}
884 void printAffineMapOfSSAIds(AffineMapAttr,
ValueRange)
override {}
887 void increaseIndent()
override {}
888 void decreaseIndent()
override {}
889 void printOperand(Value)
override {}
890 void printOperand(Value, raw_ostream &os)
override {
898 void printResourceHandle(
const AsmDialectResourceHandle &)
override {}
899 void printSymbolName(StringRef)
override {}
900 void printSuccessor(
Block *)
override {}
902 void shadowRegionArgs(Region &,
ValueRange)
override {}
905 const OpPrintingFlags &printerFlags;
908 AliasInitializer &initializer;
911 mutable llvm::raw_null_ostream os;
916 explicit DummyAliasDialectAsmPrinter(AliasInitializer &initializer,
918 SmallVectorImpl<size_t> &childIndices)
919 : initializer(initializer), canBeDeferred(canBeDeferred),
920 childIndices(childIndices) {}
925 template <
typename T,
typename... PrintArgs>
926 size_t printAndVisitNestedAliases(T value, PrintArgs &&...
printArgs) {
927 printAndVisitNestedAliasesImpl(value,
printArgs...);
928 return maxAliasDepth;
934 void printAndVisitNestedAliasesImpl(Attribute attr,
bool elideType) {
935 if (!isa<BuiltinDialect>(attr.
getDialect())) {
939 }
else if (llvm::isa<AffineMapAttr, DenseArrayAttr, FloatAttr, IntegerAttr,
940 IntegerSetAttr, UnitAttr>(attr)) {
942 }
else if (
auto distinctAttr = dyn_cast<DistinctAttr>(attr)) {
943 printAttribute(distinctAttr.getReferencedAttr());
944 }
else if (
auto dictAttr = dyn_cast<DictionaryAttr>(attr)) {
945 for (
const NamedAttribute &nestedAttr : dictAttr.getValue()) {
946 printAttribute(nestedAttr.getName());
947 printAttribute(nestedAttr.getValue());
949 }
else if (
auto arrayAttr = dyn_cast<ArrayAttr>(attr)) {
950 for (Attribute nestedAttr : arrayAttr.getValue())
951 printAttribute(nestedAttr);
952 }
else if (
auto typeAttr = dyn_cast<TypeAttr>(attr)) {
954 }
else if (
auto locAttr = dyn_cast<OpaqueLoc>(attr)) {
955 printAttribute(locAttr.getFallbackLocation());
956 }
else if (
auto locAttr = dyn_cast<NameLoc>(attr)) {
957 if (!isa<UnknownLoc>(locAttr.getChildLoc()))
958 printAttribute(locAttr.getChildLoc());
959 }
else if (
auto locAttr = dyn_cast<CallSiteLoc>(attr)) {
960 printAttribute(locAttr.getCallee());
961 printAttribute(locAttr.getCaller());
962 }
else if (
auto locAttr = dyn_cast<FusedLoc>(attr)) {
963 if (Attribute metadata = locAttr.getMetadata())
964 printAttribute(metadata);
965 for (Location nestedLoc : locAttr.getLocations())
966 printAttribute(nestedLoc);
971 if (
auto typedAttr = llvm::dyn_cast<TypedAttr>(attr)) {
972 Type attrType = typedAttr.getType();
973 if (!llvm::isa<NoneType>(attrType))
978 void printAndVisitNestedAliasesImpl(Type type) {
985 if (
auto memrefTy = llvm::dyn_cast<MemRefType>(type)) {
987 MemRefLayoutAttrInterface layout = memrefTy.getLayout();
988 if (!llvm::isa<AffineMapAttr>(layout) || !layout.isIdentity())
989 printAttribute(memrefTy.getLayout());
990 if (memrefTy.getMemorySpace())
991 printAttribute(memrefTy.getMemorySpace());
996 auto visitFn = [&](
auto element) {
998 (void)printAlias(element);
1005 recordAliasResult(initializer.visit(type, canBeDeferred));
1009 void printAttribute(Attribute attr)
override {
1010 recordAliasResult(initializer.visit(attr, canBeDeferred));
1012 void printAttributeWithoutType(Attribute attr)
override {
1014 initializer.visit(attr, canBeDeferred,
true));
1016 void printNamedAttribute(NamedAttribute attr)
override {
1020 LogicalResult printAlias(Attribute attr)
override {
1021 printAttribute(attr);
1024 LogicalResult printAlias(Type type)
override {
1030 void recordAliasResult(std::pair<size_t, size_t> aliasDepthAndIndex) {
1031 childIndices.push_back(aliasDepthAndIndex.second);
1032 if (aliasDepthAndIndex.first > maxAliasDepth)
1033 maxAliasDepth = aliasDepthAndIndex.first;
1038 raw_ostream &getStream()
const override {
return os; }
1043 void increaseIndent()
override {}
1044 void decreaseIndent()
override {}
1045 void printFloat(
const APFloat &)
override {}
1048 void printSymbolName(StringRef)
override {}
1049 void printResourceHandle(
const AsmDialectResourceHandle &)
override {}
1051 LogicalResult pushCyclicPrinting(
const void *opaquePointer)
override {
1052 return success(cyclicPrintingStack.insert(opaquePointer));
1055 void popCyclicPrinting()
override { cyclicPrintingStack.pop_back(); }
1059 SetVector<const void *> cyclicPrintingStack;
1062 AliasInitializer &initializer;
1068 SmallVectorImpl<size_t> &childIndices;
1071 size_t maxAliasDepth = 0;
1074 mutable llvm::raw_null_ostream os;
1082 StringRef allowedPunctChars =
"$._-") {
1083 assert(!name.empty() &&
"Shouldn't have an empty name here");
1085 auto validChar = [&](
char ch) {
1086 return llvm::isAlnum(ch) || allowedPunctChars.contains(ch);
1089 auto copyNameToBuffer = [&] {
1090 for (
char ch : name) {
1092 buffer.push_back(ch);
1094 buffer.push_back(
'_');
1096 buffer.append(llvm::utohexstr((
unsigned char)ch));
1103 if (isdigit(name[0]) || (!validChar(name[0]) && name[0] !=
' ')) {
1104 buffer.push_back(
'_');
1110 for (
char ch : name) {
1111 if (!validChar(ch)) {
1121unsigned AliasInitializer::uniqueAliasNameIndex(
1122 StringRef alias, llvm::StringMap<unsigned> &nameCounts,
1123 llvm::StringSet<llvm::BumpPtrAllocator &> &usedAliases) {
1124 if (!usedAliases.count(alias)) {
1125 usedAliases.insert(alias);
1131 size_t probeSize = probeAlias.size();
1133 if (isdigit(alias.back())) {
1134 probeAlias.push_back(
'_');
1138 if (nameCounts[probeAlias] == 0)
1139 nameCounts[probeAlias] = 1;
1143 unsigned nameIndex = nameCounts[probeAlias]++;
1144 probeAlias += llvm::utostr(nameIndex);
1145 if (!usedAliases.count(probeAlias)) {
1146 usedAliases.insert(probeAlias);
1150 probeAlias.resize(probeSize);
1156void AliasInitializer::initializeAliases(
1157 llvm::MapVector<const void *, InProgressAliasInfo> &visitedSymbols,
1158 llvm::MapVector<const void *, SymbolAlias> &symbolToAlias) {
1160 unprocessedAliases = visitedSymbols.takeVector();
1161 llvm::stable_sort(unprocessedAliases, llvm::less_second());
1165 llvm::BumpPtrAllocator usedAliasAllocator;
1166 llvm::StringSet<llvm::BumpPtrAllocator &> usedAliases(usedAliasAllocator);
1168 llvm::StringMap<unsigned> nameCounts;
1169 for (
auto &[symbol, aliasInfo] : unprocessedAliases) {
1170 if (!aliasInfo.alias)
1172 StringRef alias = *aliasInfo.alias;
1173 unsigned nameIndex = uniqueAliasNameIndex(alias, nameCounts, usedAliases);
1174 symbolToAlias.insert(
1175 {symbol, SymbolAlias(alias, nameIndex, aliasInfo.isType,
1176 aliasInfo.canBeDeferred)});
1180void AliasInitializer::initialize(
1182 llvm::MapVector<const void *, SymbolAlias> &attrTypeToAlias) {
1186 DummyAliasOperationPrinter aliasPrinter(printerFlags, *
this);
1187 aliasPrinter.printCustomOrGenericOp(op);
1190 initializeAliases(aliases, attrTypeToAlias);
1193template <
typename T,
typename... PrintArgs>
1194std::pair<size_t, size_t> AliasInitializer::visitImpl(
1195 T value, llvm::MapVector<const void *, InProgressAliasInfo> &aliases,
1196 bool canBeDeferred, PrintArgs &&...
printArgs) {
1197 auto [it,
inserted] = aliases.try_emplace(value.getAsOpaquePointer());
1198 size_t aliasIndex = std::distance(aliases.begin(), it);
1202 markAliasNonDeferrable(aliasIndex);
1203 return {
static_cast<size_t>(it->second.aliasDepth), aliasIndex};
1207 generateAlias(value, it->second, canBeDeferred);
1208 it->second.isType = std::is_base_of_v<Type, T>;
1209 it->second.canBeDeferred = canBeDeferred;
1213 DummyAliasDialectAsmPrinter printer(*
this, canBeDeferred, childAliases);
1214 size_t maxAliasDepth =
1215 printer.printAndVisitNestedAliases(value,
printArgs...);
1218 it = std::next(aliases.begin(), aliasIndex);
1221 it->second.childIndices = std::move(childAliases);
1223 it->second.aliasDepth = maxAliasDepth + 1;
1226 return {(size_t)it->second.aliasDepth, aliasIndex};
1229void AliasInitializer::markAliasNonDeferrable(
size_t aliasIndex) {
1230 auto *it = std::next(aliases.begin(), aliasIndex);
1234 if (!it->second.canBeDeferred)
1237 it->second.canBeDeferred =
false;
1240 for (
size_t childIndex : it->second.childIndices)
1241 markAliasNonDeferrable(childIndex);
1244template <
typename T>
1245void AliasInitializer::generateAlias(T symbol, InProgressAliasInfo &alias,
1246 bool canBeDeferred) {
1249 OpAsmDialectInterface::AliasResult symbolInterfaceResult =
1250 OpAsmDialectInterface::AliasResult::NoAlias;
1251 using InterfaceT = std::conditional_t<std::is_base_of_v<Attribute, T>,
1252 OpAsmAttrInterface, OpAsmTypeInterface>;
1253 if (
auto symbolInterface = dyn_cast<InterfaceT>(symbol)) {
1254 symbolInterfaceResult = symbolInterface.getAlias(aliasOS);
1255 if (symbolInterfaceResult != OpAsmDialectInterface::AliasResult::NoAlias) {
1256 nameBuffer = std::move(aliasBuffer);
1257 assert(!nameBuffer.empty() &&
"expected valid alias name");
1261 if (symbolInterfaceResult != OpAsmDialectInterface::AliasResult::FinalAlias) {
1262 for (
const auto &interface : interfaces) {
1263 OpAsmDialectInterface::AliasResult
result =
1264 interface.getAlias(symbol, aliasOS);
1265 if (
result == OpAsmDialectInterface::AliasResult::NoAlias)
1267 nameBuffer = std::move(aliasBuffer);
1268 assert(!nameBuffer.empty() &&
"expected valid alias name");
1269 if (
result == OpAsmDialectInterface::AliasResult::FinalAlias)
1274 if (nameBuffer.empty())
1280 name = name.copy(aliasAllocator);
1281 alias = InProgressAliasInfo(name);
1294 initialize(Operation *op,
const OpPrintingFlags &printerFlags,
1295 DialectInterfaceCollection<OpAsmDialectInterface> &interfaces);
1299 LogicalResult getAlias(Attribute attr, raw_ostream &os)
const;
1303 LogicalResult getAlias(Type ty, raw_ostream &os)
const;
1307 void printNonDeferredAliases(AsmPrinter::Impl &p, NewLineCounter &newLine) {
1308 printAliases(p, newLine,
false);
1312 void printDeferredAliases(AsmPrinter::Impl &p, NewLineCounter &newLine) {
1313 printAliases(p, newLine,
true);
1319 void printAliases(AsmPrinter::Impl &p, NewLineCounter &newLine,
1323 llvm::MapVector<const void *, SymbolAlias> attrTypeToAlias;
1326 llvm::BumpPtrAllocator aliasAllocator;
1330void AliasState::initialize(
1333 AliasInitializer initializer(interfaces, aliasAllocator);
1334 initializer.initialize(op, printerFlags, attrTypeToAlias);
1339 if (it == attrTypeToAlias.end())
1341 it->second.print(os);
1347 if (it == attrTypeToAlias.end())
1349 if (!it->second.isPrinted)
1352 it->second.print(os);
1358 auto filterFn = [=](
const auto &aliasIt) {
1359 return aliasIt.second.canBeDeferred() == isDeferred;
1361 for (
auto &[opaqueSymbol, alias] :
1362 llvm::make_filter_range(attrTypeToAlias, filterFn)) {
1366 if (alias.isTypeAlias()) {
1369 alias.isPrinted =
true;
1399 enum :
unsigned { NameSentinel = ~0U };
1401 SSANameState(Operation *op,
const OpPrintingFlags &printerFlags);
1402 SSANameState() =
default;
1407 void printValueID(Value value,
bool printResultNo, raw_ostream &stream)
const;
1410 void printOperationID(Operation *op, raw_ostream &stream)
const;
1414 ArrayRef<int> getOpResultGroups(Operation *op);
1417 BlockInfo getBlockInfo(
Block *block);
1422 void shadowRegionArgs(Region ®ion,
ValueRange namesToUse);
1426 void numberValuesInRegion(Region ®ion);
1427 void numberValuesInBlock(
Block &block);
1428 void numberValuesInOp(Operation &op);
1434 void getResultIDAndNumber(OpResult
result, Value &lookupValue,
1435 std::optional<int> &lookupResultNo)
const;
1438 void setValueName(Value value, StringRef name);
1442 StringRef uniqueValueName(StringRef name);
1465 llvm::ScopedHashTable<StringRef, char> usedNames;
1466 llvm::BumpPtrAllocator usedNameAllocator;
1469 unsigned nextValueID = 0;
1471 unsigned nextArgumentID = 0;
1473 unsigned nextConflictID = 0;
1477 OpPrintingFlags printerFlags;
1482 : printerFlags(printerFlags) {
1483 llvm::SaveAndRestore valueIDSaver(nextValueID);
1484 llvm::SaveAndRestore argumentIDSaver(nextArgumentID);
1485 llvm::SaveAndRestore conflictIDSaver(nextConflictID);
1490 using UsedNamesScopeTy = llvm::ScopedHashTable<StringRef, char>::ScopeTy;
1491 using NamingContext =
1492 std::tuple<Region *, unsigned, unsigned, unsigned, UsedNamesScopeTy *>;
1495 llvm::BumpPtrAllocator allocator;
1498 auto *topLevelNamesScope =
1499 new (allocator.Allocate<UsedNamesScopeTy>()) UsedNamesScopeTy(usedNames);
1503 nameContext.push_back(std::make_tuple(®ion, nextValueID, nextArgumentID,
1504 nextConflictID, topLevelNamesScope));
1506 numberValuesInOp(*op);
1508 while (!nameContext.empty()) {
1510 UsedNamesScopeTy *parentScope;
1514 std::tie(region, std::ignore, std::ignore, std::ignore, parentScope) =
1515 nameContext.pop_back_val();
1517 std::tie(region, nextValueID, nextArgumentID, nextConflictID,
1518 parentScope) = nameContext.pop_back_val();
1522 while (usedNames.getCurScope() != parentScope) {
1523 usedNames.getCurScope()->~UsedNamesScopeTy();
1524 assert((usedNames.getCurScope() !=
nullptr || parentScope ==
nullptr) &&
1525 "top level parentScope must be a nullptr");
1529 auto *curNamesScope =
new (allocator.Allocate<UsedNamesScopeTy>())
1530 UsedNamesScopeTy(usedNames);
1532 numberValuesInRegion(*region);
1536 nameContext.push_back(std::make_tuple(®ion, nextValueID,
1537 nextArgumentID, nextConflictID,
1542 while (usedNames.getCurScope() !=
nullptr)
1543 usedNames.getCurScope()->~UsedNamesScopeTy();
1546void SSANameState::printValueID(
Value value,
bool printResultNo,
1549 stream <<
"<<NULL VALUE>>";
1553 std::optional<int> resultNo;
1554 auto lookupValue = value;
1558 if (OpResult
result = dyn_cast<OpResult>(value))
1559 getResultIDAndNumber(
result, lookupValue, resultNo);
1561 auto it = valueIDs.find(lookupValue);
1562 if (it == valueIDs.end()) {
1563 stream <<
"<<UNKNOWN SSA VALUE>>";
1568 if (it->second != NameSentinel) {
1569 stream << it->second;
1571 auto nameIt = valueNames.find(lookupValue);
1572 assert(nameIt != valueNames.end() &&
"Didn't have a name entry?");
1573 stream << nameIt->second;
1576 if (resultNo && printResultNo)
1577 stream <<
'#' << *resultNo;
1580void SSANameState::printOperationID(Operation *op, raw_ostream &stream)
const {
1581 auto it = operationIDs.find(op);
1582 if (it == operationIDs.end()) {
1583 stream <<
"<<UNKNOWN OPERATION>>";
1585 stream <<
'%' << it->second;
1589ArrayRef<int> SSANameState::getOpResultGroups(Operation *op) {
1590 auto it = opResultGroups.find(op);
1591 return it == opResultGroups.end() ? ArrayRef<int>() : it->second;
1594BlockInfo SSANameState::getBlockInfo(
Block *block) {
1595 auto it = blockNames.find(block);
1596 BlockInfo invalidBlock{-1,
"INVALIDBLOCK"};
1597 return it != blockNames.end() ? it->second : invalidBlock;
1600void SSANameState::shadowRegionArgs(Region ®ion,
ValueRange namesToUse) {
1601 assert(!region.
empty() &&
"cannot shadow arguments of an empty region");
1603 "incorrect number of names passed in");
1605 "only KnownIsolatedFromAbove ops can shadow names");
1607 SmallVector<char, 16> nameStr;
1608 for (
unsigned i = 0, e = namesToUse.size(); i != e; ++i) {
1609 auto nameToUse = namesToUse[i];
1610 if (nameToUse ==
nullptr)
1615 llvm::raw_svector_ostream nameStream(nameStr);
1616 printValueID(nameToUse,
true, nameStream);
1619 assert(valueIDs[nameToReplace] == NameSentinel);
1622 auto name = StringRef(nameStream.str()).drop_front();
1625 valueNames[nameToReplace] = name.copy(usedNameAllocator);
1631StringRef maybeGetValueNameFromLoc(Value value, StringRef name) {
1633 return maybeNameLoc.getName();
1638void SSANameState::numberValuesInRegion(Region ®ion) {
1640 bool opAsmOpInterfaceUsed =
false;
1641 auto setBlockArgNameFn = [&](Value arg, StringRef name) {
1642 assert(!valueIDs.count(arg) &&
"arg numbered multiple times");
1643 assert(llvm::cast<BlockArgument>(arg).getOwner()->getParent() == ®ion &&
1644 "arg not defined in current region");
1645 opAsmOpInterfaceUsed =
true;
1647 name = maybeGetValueNameFromLoc(arg, name);
1648 setValueName(arg, name);
1653 if (
auto asmInterface = dyn_cast<OpAsmOpInterface>(op))
1654 asmInterface.getAsmBlockArgumentNames(region, setBlockArgNameFn);
1656 if (!opAsmOpInterfaceUsed) {
1658 if (
auto interface = dyn_cast<OpAsmTypeInterface>(arg.
getType())) {
1659 interface.getAsmName(
1660 [&](StringRef name) { setBlockArgNameFn(arg, name); });
1668 unsigned nextBlockID = 0;
1669 for (
auto &block : region) {
1672 auto blockInfoIt = blockNames.insert({&block, {-1,
""}});
1673 if (blockInfoIt.second) {
1677 llvm::raw_string_ostream(name) <<
"^bb" << nextBlockID;
1678 blockInfoIt.first->second.name = StringRef(name).copy(usedNameAllocator);
1680 blockInfoIt.first->second.ordering = nextBlockID++;
1682 numberValuesInBlock(block);
1686void SSANameState::numberValuesInBlock(
Block &block) {
1690 SmallString<32> specialNameBuffer(isEntryBlock ?
"arg" :
"");
1691 llvm::raw_svector_ostream specialName(specialNameBuffer);
1693 if (valueIDs.count(arg))
1696 specialNameBuffer.resize(strlen(
"arg"));
1697 specialName << nextArgumentID++;
1699 StringRef specialNameStr = specialName.str();
1701 specialNameStr = maybeGetValueNameFromLoc(arg, specialNameStr);
1702 setValueName(arg, specialNameStr);
1706 for (
auto &op : block)
1707 numberValuesInOp(op);
1710void SSANameState::numberValuesInOp(Operation &op) {
1712 SmallVector<int, 2> resultGroups(1, 0);
1714 bool opAsmOpInterfaceUsed =
false;
1715 auto setResultNameFn = [&](Value
result, StringRef name) {
1716 assert(!valueIDs.count(
result) &&
"result numbered multiple times");
1717 assert(
result.getDefiningOp() == &op &&
"result not defined by 'op'");
1718 opAsmOpInterfaceUsed =
true;
1720 name = maybeGetValueNameFromLoc(
result, name);
1721 setValueName(
result, name);
1724 if (
int resultNo = llvm::cast<OpResult>(
result).getResultNumber())
1725 resultGroups.push_back(resultNo);
1728 auto setBlockNameFn = [&](
Block *block, StringRef name) {
1730 "getAsmBlockArgumentNames callback invoked on a block not directly "
1731 "nested under the current operation");
1732 assert(!blockNames.count(block) &&
"block numbered multiple times");
1733 SmallString<16> tmpBuffer{
"^"};
1735 if (name.data() != tmpBuffer.data()) {
1736 tmpBuffer.append(name);
1737 name = tmpBuffer.str();
1739 name = name.copy(usedNameAllocator);
1740 blockNames[block] = {-1, name};
1744 if (OpAsmOpInterface asmInterface = dyn_cast<OpAsmOpInterface>(&op)) {
1745 asmInterface.getAsmBlockNames(setBlockNameFn);
1746 asmInterface.getAsmResultNames(setResultNameFn);
1748 if (!opAsmOpInterfaceUsed) {
1751 bool allHaveOpAsmTypeInterface =
1753 return isa<OpAsmTypeInterface>(type);
1755 if (allHaveOpAsmTypeInterface) {
1757 auto interface = cast<OpAsmTypeInterface>(
result.
getType());
1758 interface.getAsmName(
1759 [&](StringRef name) { setResultNameFn(
result, name); });
1766 if (numResults == 0) {
1769 if (operationIDs.try_emplace(&op, nextValueID).second)
1778 setValueName(resultBegin, nameLoc.getName());
1783 if (valueIDs.try_emplace(resultBegin, nextValueID).second)
1787 if (resultGroups.size() != 1) {
1788 llvm::array_pod_sort(resultGroups.begin(), resultGroups.end());
1789 opResultGroups.try_emplace(&op, std::move(resultGroups));
1793void SSANameState::getResultIDAndNumber(
1794 OpResult
result, Value &lookupValue,
1795 std::optional<int> &lookupResultNo)
const {
1796 Operation *owner =
result.getOwner();
1799 int resultNo =
result.getResultNumber();
1803 auto resultGroupIt = opResultGroups.find(owner);
1804 if (resultGroupIt == opResultGroups.end()) {
1806 lookupResultNo = resultNo;
1812 ArrayRef<int> resultGroups = resultGroupIt->second;
1813 const auto *it = llvm::upper_bound(resultGroups, resultNo);
1814 int groupResultNo = 0, groupSize = 0;
1817 if (it == resultGroups.end()) {
1818 groupResultNo = resultGroups.back();
1819 groupSize =
static_cast<int>(owner->
getNumResults()) - resultGroups.back();
1822 groupResultNo = *std::prev(it);
1823 groupSize = *it - groupResultNo;
1828 lookupResultNo = resultNo - groupResultNo;
1829 lookupValue = owner->
getResult(groupResultNo);
1832void SSANameState::setValueName(Value value, StringRef name) {
1835 valueIDs[value] = nextValueID++;
1839 valueIDs[value] = NameSentinel;
1840 valueNames[value] = uniqueValueName(name);
1843StringRef SSANameState::uniqueValueName(StringRef name) {
1844 SmallString<16> tmpBuffer;
1848 if (!usedNames.count(name)) {
1849 name = name.copy(usedNameAllocator);
1854 SmallString<64> probeName(name);
1855 probeName.push_back(
'_');
1857 probeName += llvm::utostr(nextConflictID++);
1858 if (!usedNames.count(probeName)) {
1859 name = probeName.str().copy(usedNameAllocator);
1862 probeName.resize(name.size() + 1);
1866 usedNames.insert(name,
char());
1876class DistinctState {
1879 uint64_t getId(DistinctAttr distinctAttr);
1882 uint64_t distinctCounter = 0;
1887uint64_t DistinctState::getId(DistinctAttr distinctAttr) {
1889 distinctAttrMap.try_emplace(distinctAttr, distinctCounter);
1892 return it->getSecond();
1913 llvm_unreachable(
"unknown AsmResourceEntryKind");
1917 std::unique_ptr<ResourceCollection> &collection = keyToResources[key.str()];
1919 collection = std::make_unique<ResourceCollection>(key);
1923std::vector<std::unique_ptr<AsmResourcePrinter>>
1925 std::vector<std::unique_ptr<AsmResourcePrinter>> printers;
1926 for (
auto &it : keyToResources) {
1927 ResourceCollection *collection = it.second.get();
1929 return collection->buildResources(op, builder);
1931 printers.emplace_back(
1937LogicalResult FallbackAsmResourceMap::ResourceCollection::parseResource(
1941 FailureOr<AsmResourceBlob> blob = entry.
parseAsBlob();
1944 resources.emplace_back(entry.
getKey(), std::move(*blob));
1951 resources.emplace_back(entry.
getKey(), *value);
1954 case AsmResourceEntryKind::String: {
1958 resources.emplace_back(entry.
getKey(), std::move(*str));
1965void FallbackAsmResourceMap::ResourceCollection::buildResources(
1966 Operation *op, AsmResourceBuilder &builder)
const {
1967 for (
const auto &entry : resources) {
1968 if (
const auto *value = std::get_if<AsmResourceBlob>(&entry.value))
1970 else if (
const auto *value = std::get_if<bool>(&entry.value))
1972 else if (
const auto *value = std::get_if<std::string>(&entry.value))
1975 llvm_unreachable(
"unknown AsmResourceEntryKind");
1989 : interfaces(op->
getContext()), nameState(op, printerFlags),
1990 printerFlags(printerFlags), locationMap(locationMap) {}
1993 : interfaces(ctx), printerFlags(printerFlags), locationMap(locationMap) {}
1997 aliasState.initialize(op, printerFlags, interfaces);
2017 return llvm::make_pointee_range(externalResourcePrinters);
2027 (*locationMap)[op] = std::make_pair(line, col);
2033 return dialectResources;
2037 return success(cyclicPrintingStack.insert(opaquePointer));
2053 AliasState aliasState;
2056 SSANameState nameState;
2059 DistinctState distinctState;
2075template <
typename Range>
2079 [&stream](
const auto &dimSize) {
2080 if (ShapedType::isDynamic(dimSize))
2098 return printerFlags;
2102 auto parentThreadId = llvm::get_threadid();
2104 if (parentThreadId == llvm::get_threadid()) {
2106 diag.print(llvm::dbgs());
2107 llvm::dbgs() <<
"\n";
2115 <<
"' failed to verify and will be printed in generic form";
2119 return printerFlags;
2138 return impl->getPrinterFlags();
2142 std::unique_ptr<AsmResourcePrinter> printer) {
2143 impl->externalResourcePrinters.emplace_back(std::move(printer));
2148 return impl->getDialectResources();
2170 if (!isTopLevel && succeeded(
state.getAliasState().getAlias(loc,
os)))
2174 .Case([&](OpaqueLoc loc) {
2177 .Case([&](UnknownLoc loc) {
2185 os << loc.getFilename().getValue();
2188 if (loc.getEndColumn() == loc.getStartColumn() &&
2189 loc.getStartLine() == loc.getEndLine()) {
2190 os <<
':' << loc.getStartLine() <<
':' << loc.getStartColumn();
2193 if (loc.getStartLine() == loc.getEndLine()) {
2194 os <<
':' << loc.getStartLine() <<
':' << loc.getStartColumn()
2195 <<
" to :" << loc.getEndColumn();
2198 os <<
':' << loc.getStartLine() <<
':' << loc.getStartColumn() <<
" to "
2199 << loc.getEndLine() <<
':' << loc.getEndColumn();
2201 .Case([&](NameLoc loc) {
2205 auto childLoc = loc.getChildLoc();
2206 if (!llvm::isa<UnknownLoc>(childLoc)) {
2212 .Case([&](CallSiteLoc loc) {
2219 if (llvm::isa<NameLoc>(callee)) {
2220 if (llvm::isa<FileLineColLoc>(caller)) {
2238 if (
Attribute metadata = loc.getMetadata()) {
2245 printLocationInternal(loc, pretty);
2259 bool *printedHex =
nullptr) {
2264 bool isInf = apValue.isInfinity();
2265 bool isNaN = apValue.isNaN();
2266 if (!isInf && !isNaN) {
2268 apValue.toString(strValue, 6, 0,
2274 assert(((strValue[0] >=
'0' && strValue[0] <=
'9') ||
2275 ((strValue[0] ==
'-' || strValue[0] ==
'+') &&
2276 (strValue[1] >=
'0' && strValue[1] <=
'9'))) &&
2277 "[-+]?[0-9] regex does not match!");
2281 if (APFloat(apValue.getSemantics(), strValue).bitwiseIsEqual(apValue)) {
2289 apValue.toString(strValue);
2292 if (strValue.str().contains(
'.')) {
2303 APInt apInt = apValue.bitcastToAPInt();
2304 apInt.toString(str, 16,
false,
2324 if (symName.empty() || !isalpha(symName.front()))
2329 symName = symName.drop_while(
2330 [](
char c) {
return llvm::isAlnum(c) || c ==
'.' || c ==
'_'; });
2331 if (symName.empty())
2336 return symName.front() ==
'<' && symName.back() ==
'>';
2341 StringRef dialectName, StringRef symString) {
2342 os << symPrefix << dialectName;
2347 os <<
'.' << symString;
2351 os <<
'<' << symString <<
'>';
2360 if (name.empty() || (!isalpha(name[0]) && name[0] !=
'_'))
2362 return llvm::all_of(name.drop_front(), [](
unsigned char c) {
2363 return isalnum(c) || c ==
'_' || c ==
'$' || c ==
'.';
2378 printEscapedString(keyword, os);
2386 if (symbolRef.empty()) {
2387 os <<
"@<<INVALID EMPTY SYMBOL>>";
2400 os << R
"(dense_resource<__elided__>)";
2405 auto *
interface = cast<OpAsmDialectInterface>(resource.getDialect());
2411 return state.getAliasState().getAlias(attr,
os);
2415 return state.getAliasState().getAlias(type,
os);
2421 os <<
"<<NULL ATTRIBUTE>>";
2432 if (!isa<BuiltinDialect>(attr.
getDialect())) {
2434 }
else if (
auto opaqueAttr = llvm::dyn_cast<OpaqueAttr>(attr)) {
2436 opaqueAttr.getAttrData());
2437 }
else if (llvm::isa<UnitAttr>(attr)) {
2440 }
else if (
auto distinctAttr = llvm::dyn_cast<DistinctAttr>(attr)) {
2441 os <<
"distinct[" <<
state.getDistinctState().getId(distinctAttr) <<
"]<";
2447 }
else if (
auto dictAttr = llvm::dyn_cast<DictionaryAttr>(attr)) {
2453 }
else if (
auto intAttr = llvm::dyn_cast<IntegerAttr>(attr)) {
2454 Type intType = intAttr.getType();
2456 os << (intAttr.getValue().getBoolValue() ?
"true" :
"false");
2467 intAttr.getValue().print(
os, !isUnsigned);
2473 }
else if (
auto floatAttr = llvm::dyn_cast<FloatAttr>(attr)) {
2474 bool printedHex =
false;
2482 }
else if (
auto strAttr = llvm::dyn_cast<StringAttr>(attr)) {
2485 }
else if (
auto arrayAttr = llvm::dyn_cast<ArrayAttr>(attr)) {
2488 printAttribute(attr, AttrTypeElision::May);
2492 }
else if (
auto affineMapAttr = llvm::dyn_cast<AffineMapAttr>(attr)) {
2493 os <<
"affine_map<";
2494 affineMapAttr.getValue().print(
os);
2500 }
else if (
auto integerSetAttr = llvm::dyn_cast<IntegerSetAttr>(attr)) {
2501 os <<
"affine_set<";
2502 integerSetAttr.getValue().print(
os);
2508 }
else if (
auto typeAttr = llvm::dyn_cast<TypeAttr>(attr)) {
2511 }
else if (
auto refAttr = llvm::dyn_cast<SymbolRefAttr>(attr)) {
2518 }
else if (
auto intOrFpEltAttr =
2519 llvm::dyn_cast<DenseTypedElementsAttr>(attr)) {
2520 if (
printerFlags.shouldElideElementsAttr(intOrFpEltAttr)) {
2527 Type eltType = intOrFpEltAttr.getElementType();
2528 if (isa<FloatType, IntegerType, IndexType, ComplexType>(eltType)) {
2532 cast<DenseElementType>(eltType));
2538 }
else if (
auto strEltAttr = llvm::dyn_cast<DenseStringElementsAttr>(attr)) {
2539 if (
printerFlags.shouldElideElementsAttr(strEltAttr)) {
2547 }
else if (
auto sparseEltAttr = llvm::dyn_cast<SparseElementsAttr>(attr)) {
2548 if (
printerFlags.shouldElideElementsAttr(sparseEltAttr.getIndices()) ||
2549 printerFlags.shouldElideElementsAttr(sparseEltAttr.getValues())) {
2554 if (
indices.getNumElements() != 0) {
2561 }
else if (
auto stridedLayoutAttr = llvm::dyn_cast<StridedLayoutAttr>(attr)) {
2562 stridedLayoutAttr.print(
os);
2563 }
else if (
auto denseArrayAttr = llvm::dyn_cast<DenseArrayAttr>(attr)) {
2565 printType(denseArrayAttr.getElementType());
2566 if (!denseArrayAttr.empty()) {
2572 }
else if (
auto resourceAttr =
2573 llvm::dyn_cast<DenseResourceElementsAttr>(attr)) {
2574 os <<
"dense_resource<";
2577 }
else if (
auto locAttr = llvm::dyn_cast<LocationAttr>(attr)) {
2580 llvm::report_fatal_error(
"Unknown builtin attribute");
2584 if (
auto typedAttr = llvm::dyn_cast<TypedAttr>(attr)) {
2585 Type attrType = typedAttr.getType();
2586 if (!llvm::isa<NoneType>(attrType)) {
2598 os << (value.getBoolValue() ?
"true" :
"false");
2608 return printEltFn(0);
2611 auto numElements = type.getNumElements();
2612 if (numElements == 0)
2620 int64_t rank = type.getRank();
2623 unsigned openBrackets = 0;
2625 auto shape = type.getShape();
2626 auto bumpCounter = [&] {
2628 ++counter[rank - 1];
2630 for (
unsigned i = rank - 1; i > 0; --i)
2631 if (counter[i] >=
shape[i]) {
2640 for (
unsigned idx = 0, e = numElements; idx != e; ++idx) {
2643 while (openBrackets++ < rank)
2645 openBrackets = rank;
2649 while (openBrackets-- > 0)
2655 if (
auto stringAttr = llvm::dyn_cast<DenseStringElementsAttr>(attr))
2664 auto type = attr.getType();
2665 auto elementType = type.getElementType();
2668 if (allowHex &&
printerFlags.shouldPrintElementsAttrWithHex(attr)) {
2670 if (llvm::endianness::native == llvm::endianness::big) {
2675 DenseTypedElementsAttr::convertEndianOfArrayRefForBEmachine(
2676 rawData, convRawData, type);
2685 if (ComplexType complexTy = llvm::dyn_cast<ComplexType>(elementType)) {
2686 Type complexElementType = complexTy.getElementType();
2690 if (llvm::isa<IntegerType>(complexElementType)) {
2691 auto valueIt = attr.value_begin<std::complex<APInt>>();
2693 auto complexValue = *(valueIt + index);
2695 printDenseIntElement(complexValue.real(), os, complexElementType);
2697 printDenseIntElement(complexValue.imag(), os, complexElementType);
2701 auto valueIt = attr.value_begin<std::complex<APFloat>>();
2703 auto complexValue = *(valueIt + index);
2705 printFloatValue(complexValue.real(), os);
2707 printFloatValue(complexValue.imag(), os);
2711 }
else if (elementType.isIntOrIndex()) {
2712 auto valueIt = attr.value_begin<APInt>();
2714 printDenseIntElement(*(valueIt + index), os, elementType);
2717 assert(llvm::isa<FloatType>(elementType) &&
"unexpected element type");
2718 auto valueIt = attr.value_begin<APFloat>();
2720 printFloatValue(*(valueIt + index), os);
2726 DenseStringElementsAttr attr) {
2740 size_t bitSize = denseEltType.getDenseElementBitSize();
2741 size_t byteSize = llvm::divideCeil(bitSize,
static_cast<size_t>(CHAR_BIT));
2746 size_t offset = attr.isSplat() ? 0 : index * byteSize;
2747 ArrayRef<char> elemData = rawData.slice(offset, byteSize);
2748 Attribute elemAttr = denseEltType.convertToAttribute(elemData);
2749 printAttributeImpl(elemAttr);
2754 Type type = attr.getElementType();
2756 unsigned byteSize = bitwidth / 8;
2759 auto printElementAt = [&](
unsigned i) {
2760 APInt value(bitwidth, 0);
2762 llvm::LoadIntFromMemory(
2763 value,
reinterpret_cast<const uint8_t *
>(data.begin() + byteSize * i),
2770 APFloat fltVal(llvm::cast<FloatType>(type).getFloatSemantics(), value);
2774 llvm::interleaveComma(llvm::seq<unsigned>(0, attr.size()),
getStream(),
2780 os <<
"<<NULL TYPE>>";
2792 .Case([&](OpaqueType opaqueTy) {
2794 opaqueTy.getTypeData());
2796 .Case<IndexType>([&](
Type) {
os <<
"index"; })
2797 .Case<Float4E2M1FNType>([&](
Type) {
os <<
"f4E2M1FN"; })
2798 .Case<Float6E2M3FNType>([&](
Type) {
os <<
"f6E2M3FN"; })
2799 .Case<Float6E3M2FNType>([&](
Type) {
os <<
"f6E3M2FN"; })
2800 .Case<Float8E5M2Type>([&](
Type) {
os <<
"f8E5M2"; })
2801 .Case<Float8E4M3Type>([&](
Type) {
os <<
"f8E4M3"; })
2802 .Case<Float8E4M3FNType>([&](
Type) {
os <<
"f8E4M3FN"; })
2803 .Case<Float8E5M2FNUZType>([&](
Type) {
os <<
"f8E5M2FNUZ"; })
2804 .Case<Float8E4M3FNUZType>([&](
Type) {
os <<
"f8E4M3FNUZ"; })
2805 .Case<Float8E4M3B11FNUZType>([&](
Type) {
os <<
"f8E4M3B11FNUZ"; })
2806 .Case<Float8E3M4Type>([&](
Type) {
os <<
"f8E3M4"; })
2807 .Case<Float8E8M0FNUType>([&](
Type) {
os <<
"f8E8M0FNU"; })
2808 .Case<BFloat16Type>([&](
Type) {
os <<
"bf16"; })
2809 .Case<Float16Type>([&](
Type) {
os <<
"f16"; })
2810 .Case<FloatTF32Type>([&](
Type) {
os <<
"tf32"; })
2811 .Case<Float32Type>([&](
Type) {
os <<
"f32"; })
2812 .Case<Float64Type>([&](
Type) {
os <<
"f64"; })
2813 .Case<Float80Type>([&](
Type) {
os <<
"f80"; })
2814 .Case<Float128Type>([&](
Type) {
os <<
"f128"; })
2815 .Case([&](IntegerType integerTy) {
2816 if (integerTy.isSigned())
2818 else if (integerTy.isUnsigned())
2820 os <<
'i' << integerTy.getWidth();
2822 .Case([&](FunctionType funcTy) {
2827 if (results.size() == 1 && !llvm::isa<FunctionType>(results[0])) {
2835 .Case([&](VectorType vectorTy) {
2836 auto scalableDims = vectorTy.getScalableDims();
2838 auto vShape = vectorTy.getShape();
2839 unsigned lastDim = vShape.size();
2840 unsigned dimIdx = 0;
2841 for (dimIdx = 0; dimIdx < lastDim; dimIdx++) {
2842 if (!scalableDims.empty() && scalableDims[dimIdx])
2844 os << vShape[dimIdx];
2845 if (!scalableDims.empty() && scalableDims[dimIdx])
2852 .Case([&](RankedTensorType tensorTy) {
2855 if (!tensorTy.getShape().empty())
2859 if (tensorTy.getEncoding()) {
2865 .Case([&](UnrankedTensorType tensorTy) {
2870 .Case([&](MemRefType memrefTy) {
2873 if (!memrefTy.getShape().empty())
2876 MemRefLayoutAttrInterface layout = memrefTy.getLayout();
2877 if (!llvm::isa<AffineMapAttr>(layout) || !layout.isIdentity()) {
2882 if (memrefTy.getMemorySpace()) {
2892 if (memrefTy.getMemorySpace()) {
2898 .Case([&](ComplexType complexTy) {
2903 .Case([&](TupleType tupleTy) {
2906 [&](
Type type) { printType(type); });
2909 .Case<NoneType>([&](
Type) {
os <<
"none"; })
2910 .Case([&](GraphType graphTy) {
2915 if (results.size() == 1 && !isa<FunctionType, GraphType>(results[0])) {
2934 auto printFilteredAttributesFn = [&](
auto filteredAttrs) {
2937 os <<
" attributes";
2947 if (elidedAttrs.empty())
2948 return printFilteredAttributesFn(attrs);
2951 llvm::SmallDenseSet<StringRef> elidedAttrsSet(elidedAttrs.begin(),
2953 auto filteredAttrs = llvm::make_filter_range(attrs, [&](
NamedAttribute attr) {
2954 return !elidedAttrsSet.contains(attr.
getName().strref());
2956 if (!filteredAttrs.empty())
2957 printFilteredAttributesFn(filteredAttrs);
2964 if (llvm::isa<UnitAttr>(attr.
getValue()))
2975 std::string attrName;
2977 llvm::raw_string_ostream attrNameStr(attrName);
2987 dialect.printAttribute(attr, printer);
2996 std::string typeName;
2998 llvm::raw_string_ostream typeNameStr(typeName);
3008 dialect.printType(type, printer);
3015 llvm::printEscapedString(str,
os);
3020 os <<
"\"0x" << llvm::toHex(str) <<
"\"";
3027 return state.pushCyclicPrinting(opaquePointer);
3043 assert(
impl &&
"expected AsmPrinter::getStream to be overriden");
3044 return impl->getStream();
3048 assert(
impl &&
"expected AsmPrinter::printNewLine to be overriden");
3049 impl->printNewline();
3053 assert(
impl &&
"expected AsmPrinter::increaseIndent to be overriden");
3054 impl->increaseIndent();
3058 assert(
impl &&
"expected AsmPrinter::decreaseIndent to be overriden");
3059 impl->decreaseIndent();
3064 assert(
impl &&
"expected AsmPrinter::printFloat to be overriden");
3069 assert(
impl &&
"expected AsmPrinter::printType to be overriden");
3070 impl->printType(type);
3074 assert(
impl &&
"expected AsmPrinter::printAttribute to be overriden");
3075 impl->printAttribute(attr);
3079 assert(
impl &&
"expected AsmPrinter::printAlias to be overriden");
3080 return impl->printAlias(attr);
3084 assert(
impl &&
"expected AsmPrinter::printAlias to be overriden");
3085 return impl->printAlias(type);
3090 "expected AsmPrinter::printAttributeWithoutType to be overriden");
3095 assert(
impl &&
"expected AsmPrinter::printNamedAttribute to be overriden");
3096 impl->printNamedAttribute(attr);
3100 assert(
impl &&
"expected AsmPrinter::printKeywordOrString to be overriden");
3105 assert(
impl &&
"expected AsmPrinter::printString to be overriden");
3107 printEscapedString(keyword,
getStream());
3112 assert(
impl &&
"expected AsmPrinter::printSymbolName to be overriden");
3117 assert(
impl &&
"expected AsmPrinter::printResourceHandle to be overriden");
3118 impl->printResourceHandle(resource);
3126 return impl->pushCyclicPrinting(opaquePointer);
3143 const char *binopSpelling =
nullptr;
3146 unsigned pos = cast<AffineSymbolExpr>(expr).getPosition();
3148 printValueName(pos,
true);
3154 unsigned pos = cast<AffineDimExpr>(expr).getPosition();
3156 printValueName(pos,
false);
3162 os << cast<AffineConstantExpr>(expr).getValue();
3165 binopSpelling =
" + ";
3168 binopSpelling =
" * ";
3171 binopSpelling =
" floordiv ";
3174 binopSpelling =
" ceildiv ";
3177 binopSpelling =
" mod ";
3181 auto binOp = cast<AffineBinaryOpExpr>(expr);
3191 auto rhsConst = dyn_cast<AffineConstantExpr>(rhsExpr);
3193 rhsConst.getValue() == -1) {
3203 os << binopSpelling;
3217 if (
auto rhs = dyn_cast<AffineBinaryOpExpr>(rhsExpr)) {
3220 if (
auto rrhs = dyn_cast<AffineConstantExpr>(rrhsExpr)) {
3221 if (rrhs.getValue() == -1) {
3238 if (rrhs.getValue() < -1) {
3244 os <<
" * " << -rrhs.getValue();
3254 if (
auto rhsConst = dyn_cast<AffineConstantExpr>(rhsExpr)) {
3255 if (rhsConst.getValue() < 0) {
3257 os <<
" - " << -rhsConst.getValue();
3275 isEq ?
os <<
" == 0" :
os <<
" >= 0";
3281 for (
int i = 0; i < (int)map.
getNumDims() - 1; ++i)
3282 os <<
'd' << i <<
", ";
3291 os <<
's' << i <<
", ";
3300 [&](
AffineExpr expr) { printAffineExpr(expr); });
3307 for (
unsigned i = 1; i < set.
getNumDims(); ++i)
3308 os <<
'd' << i - 1 <<
", ";
3317 os <<
's' << i <<
", ";
3326 for (
int i = 1; i < numConstraints; ++i) {
3330 if (numConstraints >= 1)
3332 set.
isEq(numConstraints - 1));
3351 void printTopLevelOperation(
Operation *op);
3355 void printFullOpWithIndentAndLoc(
Operation *op);
3361 void printCustomOrGenericOp(
Operation *op)
override;
3363 void printGenericOp(
Operation *op,
bool printOpName)
override;
3366 void printBlockName(
Block *block);
3371 void print(
Block *block,
bool printBlockArgs =
true,
3372 bool printBlockTerminator =
true);
3375 void printValueID(
Value value,
bool printResultNo =
true,
3388 void printOptionalLocationSpecifier(
Location loc)
override {
3389 printTrailingLocation(loc);
3399 bool omitType =
false)
override;
3402 void printOperand(Value value)
override { printValueID(value); }
3403 void printOperand(Value value, raw_ostream &os)
override {
3404 printValueID(value,
true, &os);
3408 void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
3409 ArrayRef<StringRef> elidedAttrs = {})
override {
3410 Impl::printOptionalAttrDict(attrs, elidedAttrs);
3412 void printOptionalAttrDictWithKeyword(
3413 ArrayRef<NamedAttribute> attrs,
3414 ArrayRef<StringRef> elidedAttrs = {})
override {
3415 Impl::printOptionalAttrDict(attrs, elidedAttrs,
3420 void printSuccessor(
Block *successor)
override;
3424 void printSuccessorAndUseList(
Block *successor,
3428 void printRegion(Region ®ion,
bool printEntryBlockArgs,
3429 bool printBlockTerminators,
bool printEmptyBlock)
override;
3435 void shadowRegionArgs(Region ®ion,
ValueRange namesToUse)
override {
3441 void printAffineMapOfSSAIds(AffineMapAttr mapAttr,
3446 void printAffineExprOfSSAIds(AffineExpr expr,
ValueRange dimOperands,
3450 void printUsersComment(Operation *op);
3453 void printUsersComment(BlockArgument arg);
3456 void printValueUsers(Value value);
3460 void printUserIDs(Operation *user,
bool prefixComma =
false);
3465 class ResourceBuilder :
public AsmResourceBuilder {
3468 using PrintFn =
function_ref<void(StringRef, ValueFn)>;
3470 ResourceBuilder(PrintFn printFn) : printFn(printFn) {}
3471 ~ResourceBuilder()
override =
default;
3473 void buildBool(StringRef key,
bool data)
final {
3474 printFn(key, [&](raw_ostream &os) { os << (data ?
"true" :
"false"); });
3477 void buildString(StringRef key, StringRef data)
final {
3478 printFn(key, [&](raw_ostream &os) {
3480 llvm::printEscapedString(data, os);
3485 void buildBlob(StringRef key, ArrayRef<char> data,
3486 uint32_t dataAlignment)
final {
3487 printFn(key, [&](raw_ostream &os) {
3489 llvm::support::ulittle32_t dataAlignmentLE(dataAlignment);
3491 << llvm::toHex(StringRef(
reinterpret_cast<char *
>(&dataAlignmentLE),
3492 sizeof(dataAlignment)))
3493 << llvm::toHex(StringRef(data.data(), data.size())) <<
"\"";
3502 void printFileMetadataDictionary(Operation *op);
3508 void printResourceFileMetadata(
function_ref<
void()> checkAddMetadataDict,
3516 SmallVector<StringRef> defaultDialectStack{
"builtin"};
3520void OperationPrinter::printTopLevelOperation(Operation *op) {
3522 state.
getAliasState().printNonDeferredAliases(*
this, newLine);
3525 printFullOpWithIndentAndLoc(op);
3532 printFileMetadataDictionary(op);
3535void OperationPrinter::printFileMetadataDictionary(Operation *op) {
3536 bool sawMetadataEntry =
false;
3537 auto checkAddMetadataDict = [&] {
3538 if (!std::exchange(sawMetadataEntry,
true))
3539 os << newLine <<
"{-#" << newLine;
3543 printResourceFileMetadata(checkAddMetadataDict, op);
3546 if (sawMetadataEntry)
3547 os << newLine <<
"#-}" << newLine;
3550void OperationPrinter::printResourceFileMetadata(
3551 function_ref<
void()> checkAddMetadataDict, Operation *op) {
3553 bool hadResource =
false;
3554 bool needResourceComma =
false;
3555 bool needEntryComma =
false;
3556 auto processProvider = [&](StringRef dictName, StringRef name,
auto &provider,
3557 auto &&...providerArgs) {
3558 bool hadEntry =
false;
3559 auto printFn = [&](StringRef key, ResourceBuilder::ValueFn valueFn) {
3560 checkAddMetadataDict();
3562 std::string resourceStr;
3563 auto printResourceStr = [&](raw_ostream &os) { os << resourceStr; };
3564 std::optional<uint64_t> charLimit =
3566 if (charLimit.has_value()) {
3568 if (charLimit.value() == 0)
3571 llvm::raw_string_ostream ss(resourceStr);
3575 if (resourceStr.size() > charLimit.value())
3579 valueFn = printResourceStr;
3583 if (!std::exchange(hadResource,
true)) {
3584 if (needResourceComma)
3585 os <<
"," << newLine;
3586 os <<
" " << dictName <<
"_resources: {" << newLine;
3589 if (!std::exchange(hadEntry,
true)) {
3591 os <<
"," << newLine;
3592 os <<
" " << name <<
": {" << newLine;
3594 os <<
"," << newLine;
3602 ResourceBuilder entryBuilder(printFn);
3603 provider.buildResources(op, providerArgs..., entryBuilder);
3605 needEntryComma |= hadEntry;
3607 os << newLine <<
" }";
3614 StringRef name = interface.getDialect()->getNamespace();
3615 auto it = dialectResources.find(interface.getDialect());
3616 if (it != dialectResources.end())
3617 processProvider(
"dialect", name, interface, it->second);
3619 processProvider(
"dialect", name, interface,
3623 os << newLine <<
" }";
3627 needEntryComma =
false;
3628 needResourceComma = hadResource;
3629 hadResource =
false;
3631 processProvider(
"external", printer.getName(), printer);
3633 os << newLine <<
" }";
3641void OperationPrinter::printRegionArgument(BlockArgument arg,
3642 ArrayRef<NamedAttribute> argAttrs,
3649 printOptionalAttrDict(argAttrs);
3651 printTrailingLocation(arg.
getLoc(),
false);
3654void OperationPrinter::printFullOpWithIndentAndLoc(Operation *op) {
3658 os.indent(currentIndent);
3660 printTrailingLocation(op->
getLoc());
3662 printUsersComment(op);
3665void OperationPrinter::printFullOp(Operation *op) {
3667 auto printResultGroup = [&](
size_t resultNo,
size_t resultCount) {
3668 printValueID(op->
getResult(resultNo),
false);
3669 if (resultCount > 1)
3670 os <<
':' << resultCount;
3674 ArrayRef<int> resultGroups = state.
getSSANameState().getOpResultGroups(op);
3675 if (!resultGroups.empty()) {
3678 interleaveComma(llvm::seq<int>(0, resultGroups.size() - 1), [&](
int i) {
3679 printResultGroup(resultGroups[i],
3680 resultGroups[i + 1] - resultGroups[i]);
3683 printResultGroup(resultGroups.back(), numResults - resultGroups.back());
3686 printResultGroup(0, numResults);
3692 printCustomOrGenericOp(op);
3695void OperationPrinter::printUsersComment(Operation *op) {
3699 printOperationID(op);
3700 }
else if (numResults && op->
use_empty()) {
3702 }
else if (numResults && !op->
use_empty()) {
3705 unsigned usedInNResults = 0;
3706 unsigned usedInNOperations = 0;
3707 SmallPtrSet<Operation *, 1> userSet;
3708 for (Operation *user : op->
getUsers()) {
3709 if (userSet.insert(user).second) {
3710 ++usedInNOperations;
3711 usedInNResults += user->getNumResults();
3716 bool exactlyOneUniqueUse =
3717 usedInNResults <= 1 && usedInNOperations <= 1 && numResults == 1;
3718 os <<
" // " << (exactlyOneUniqueUse ?
"user" :
"users") <<
": ";
3719 bool shouldPrintBrackets = numResults > 1;
3720 auto printOpResult = [&](OpResult opResult) {
3721 if (shouldPrintBrackets)
3723 printValueUsers(opResult);
3724 if (shouldPrintBrackets)
3728 interleaveComma(op->
getResults(), printOpResult);
3732void OperationPrinter::printUsersComment(BlockArgument arg) {
3738 os <<
" is used by ";
3739 printValueUsers(arg);
3744void OperationPrinter::printValueUsers(Value value) {
3750 SmallPtrSet<Operation *, 1> userSet;
3752 if (userSet.insert(user).second)
3753 printUserIDs(user, index);
3757void OperationPrinter::printUserIDs(Operation *user,
bool prefixComma) {
3762 printOperationID(user);
3765 [
this](Value
result) { printValueID(result); });
3769void OperationPrinter::printCustomOrGenericOp(Operation *op) {
3775 opInfo->printAssembly(op, *
this, defaultDialectStack.back());
3780 if (
auto opPrinter = dialect->getOperationPrinter(op)) {
3785 if (name.count(
'.') == 1)
3786 name.consume_front((defaultDialectStack.back() +
".").str());
3790 opPrinter(op, *
this);
3797 printGenericOp(op,
true);
3800void OperationPrinter::printGenericOp(Operation *op,
bool printOpName) {
3804 interleaveComma(op->
getOperands(), [&](Value value) { printValueID(value); });
3811 [&](
Block *successor) { printBlockName(successor); });
3825 interleaveComma(op->
getRegions(), [&](Region ®ion) {
3826 printRegion(region, true,
3841void OperationPrinter::printBlockName(
Block *block) {
3845void OperationPrinter::print(
Block *block,
bool printBlockArgs,
3846 bool printBlockTerminator) {
3848 if (printBlockArgs) {
3849 os.indent(currentIndent);
3850 printBlockName(block);
3855 interleaveComma(block->
getArguments(), [&](BlockArgument arg) {
3858 printType(arg.getType());
3860 printTrailingLocation(arg.getLoc(), false);
3868 os <<
" // block is not in a region!";
3871 os <<
" // no predecessors";
3874 printBlockName(pred);
3878 SmallVector<BlockInfo, 4> predIDs;
3881 llvm::sort(predIDs, [](BlockInfo
lhs, BlockInfo
rhs) {
3882 return lhs.ordering <
rhs.ordering;
3885 os <<
" // " << predIDs.size() <<
" preds: ";
3887 interleaveComma(predIDs, [&](BlockInfo pred) { os << pred.name; });
3892 currentIndent += indentWidth;
3896 os.indent(currentIndent);
3897 printUsersComment(arg);
3901 bool hasTerminator =
3903 auto range = llvm::make_range(
3905 std::prev(block->
end(),
3906 (!hasTerminator || printBlockTerminator) ? 0 : 1));
3907 for (
auto &op : range) {
3908 printFullOpWithIndentAndLoc(&op);
3911 currentIndent -= indentWidth;
3914void OperationPrinter::printValueID(Value value,
bool printResultNo,
3915 raw_ostream *streamOverride)
const {
3917 streamOverride ? *streamOverride : os);
3920void OperationPrinter::printOperationID(Operation *op,
3921 raw_ostream *streamOverride)
const {
3922 state.
getSSANameState().printOperationID(op, streamOverride ? *streamOverride
3926void OperationPrinter::printSuccessor(
Block *successor) {
3927 printBlockName(successor);
3930void OperationPrinter::printSuccessorAndUseList(
Block *successor,
3932 printBlockName(successor);
3933 if (succOperands.empty())
3937 interleaveComma(succOperands,
3938 [
this](Value operand) { printValueID(operand); });
3940 interleaveComma(succOperands,
3945void OperationPrinter::printRegion(Region ®ion,
bool printEntryBlockArgs,
3946 bool printBlockTerminators,
3947 bool printEmptyBlock) {
3952 os <<
"{" << newLine;
3953 if (!region.
empty()) {
3954 llvm::scope_exit restoreDefaultDialect(
3955 [&]() { defaultDialectStack.pop_back(); });
3956 if (
auto iface = dyn_cast<OpAsmOpInterface>(region.
getParentOp()))
3957 defaultDialectStack.push_back(iface.getDefaultDialect());
3959 defaultDialectStack.push_back(
"");
3961 auto *entryBlock = ®ion.
front();
3965 bool shouldAlwaysPrintBlockHeader =
3966 (printEmptyBlock && entryBlock->empty()) ||
3967 (printEntryBlockArgs && entryBlock->getNumArguments() != 0);
3968 print(entryBlock, shouldAlwaysPrintBlockHeader, printBlockTerminators);
3969 for (
auto &
b : llvm::drop_begin(region.
getBlocks(), 1))
3972 os.indent(currentIndent) <<
"}";
3975void OperationPrinter::printAffineMapOfSSAIds(AffineMapAttr mapAttr,
3978 os <<
"<<NULL AFFINE MAP>>";
3981 AffineMap map = mapAttr.getValue();
3983 auto printValueName = [&](
unsigned pos,
bool isSymbol) {
3984 unsigned index = isSymbol ? numDims + pos : pos;
3985 assert(index < operands.size());
3988 printValueID(operands[index]);
3993 interleaveComma(map.
getResults(), [&](AffineExpr expr) {
3994 printAffineExpr(expr, printValueName);
3998void OperationPrinter::printAffineExprOfSSAIds(AffineExpr expr,
4001 auto printValueName = [&](
unsigned pos,
bool isSymbol) {
4003 return printValueID(dimOperands[pos]);
4005 printValueID(symOperands[pos]);
4008 printAffineExpr(expr, printValueName);
4017 os <<
"<<NULL ATTRIBUTE>>";
4022 print(os, state, elideType);
4028 : AttrTypeElision::Never);
4032 print(llvm::errs());
4033 llvm::errs() <<
"\n";
4038 os <<
"<<NULL ATTRIBUTE>>";
4047 uint64_t posPrior = os.tell();
4049 dialect.printAttribute(*
this, printer);
4050 if (posPrior != os.tell())
4059 os <<
"<<NULL ATTRIBUTE>>";
4069 os <<
"<<NULL TYPE>>";
4081 print(llvm::errs());
4082 llvm::errs() <<
"\n";
4086 print(llvm::errs());
4087 llvm::errs() <<
"\n";
4091 print(llvm::errs());
4092 llvm::errs() <<
"\n";
4097 os <<
"<<NULL AFFINE EXPR>>";
4105 print(llvm::errs());
4106 llvm::errs() <<
"\n";
4111 os <<
"<<NULL AFFINE MAP>>";
4126 os <<
"<<NULL VALUE>>";
4131 return op->
print(os, flags);
4134 os <<
"<block argument> of type '" << arg.
getType()
4139 os <<
"<<NULL VALUE>>";
4144 return op->
print(os, state);
4148 os <<
"<block argument> of type '" << arg.
getType()
4159 llvm::errs() <<
"\n";
4190 if (
auto result = llvm::dyn_cast<OpResult>(*
this)) {
4193 op = llvm::cast<BlockArgument>(*this).getOwner()->
getParentOp();
4195 os <<
"<<UNKNOWN SSA VALUE>>";
4211 OperationPrinter printer(os, state.
getImpl());
4214 printer.printTopLevelOperation(
this);
4216 printer.printFullOpWithIndentAndLoc(
this);
4222 llvm::errs() <<
"\n";
4227 llvm::errs() <<
"\n";
4233 os <<
"<<UNLINKED BLOCK>>\n";
4244 OperationPrinter(os, state.
getImpl()).print(
this);
4253 os <<
"<<UNLINKED BLOCK>>\n";
4260 OperationPrinter printer(os, state.
getImpl());
4261 printer.printBlockName(
this);
4276 if (dimensions.empty())
4279 if (dimensions.empty())
4289 <<
"Failed parsing dimension list.";
4300 <<
"Failed parsing dimension list.";
4302 if (shapeArr.empty()) {
4304 <<
"Failed parsing dimension list. Did you mean an empty list? It "
4305 "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)
AttrTypeElision
This enum describes the different kinds of elision for the type of an attribute when printing it.
@ May
The type may be elided when it matches the default used in the parser (for example i64 is the default...
@ Never
The type must not be elided,.
@ Must
The type must be elided.
LogicalResult pushCyclicPrinting(const void *opaquePointer)
void printIntegerSet(IntegerSet set)
NewLineCounter newLine
A tracker for the number of new lines emitted during printing.
void printOptionalAttrDict(ArrayRef< NamedAttribute > attrs, ArrayRef< StringRef > elidedAttrs={}, bool withKeyword=false)
void printType(Type type)
Print the given type or an alias.
void printLocationInternal(LocationAttr loc, bool pretty=false, bool isTopLevel=false)
void printTypeImpl(Type type)
Print the given type.
void printDenseTypedElementsAttr(DenseTypedElementsAttr attr, bool allowHex)
Print a dense elements attribute in the literal-first syntax.
void printNamedAttribute(NamedAttribute attr)
void increaseIndent()
Increase indentation.
virtual void decreaseIndent()
Decrease indentation.
virtual void printAttributeWithoutType(Attribute attr)
Print the given attribute without its type.
virtual LogicalResult printAlias(Attribute attr)
Print the alias for the given attribute, return failure if no alias could be printed.
virtual void popCyclicPrinting()
Removes the element that was last inserted with a successful call to pushCyclicPrinting.
virtual void increaseIndent()
Increase indentation.
void printFunctionalType(InputRangeT &&inputs, ResultRangeT &&results)
Print the two given type ranges in a functional form.
virtual LogicalResult pushCyclicPrinting(const void *opaquePointer)
Pushes a new attribute or type in the form of a type erased pointer into an internal set.
virtual void printType(Type type)
virtual void printKeywordOrString(StringRef keyword)
Print the given string as a keyword, or a quoted and escaped string if it has any special or non-prin...
virtual void printSymbolName(StringRef symbolRef)
Print the given string as a symbol reference, i.e.
virtual void printString(StringRef string)
Print the given string as a quoted string, escaping any special or non-printable characters in it.
virtual void printAttribute(Attribute attr)
void printDimensionList(ArrayRef< int64_t > shape)
virtual raw_ostream & getStream() const
Return the raw output stream used by this printer.
virtual void printResourceHandle(const AsmDialectResourceHandle &resource)
Print a handle to the given dialect resource.
virtual void printFloat(const APFloat &value)
Print the given floating point value in a stabilized form that can be roundtripped through the IR.
virtual void printNamedAttribute(NamedAttribute attr)
Print the given named attribute.
virtual void printNewline()
Print a newline and indent the printer to the start of the current operation/attribute/type.
This class is used to build resource entries for use by the printer.
virtual void buildString(StringRef key, StringRef data)=0
Build a resource entry represented by the given human-readable string value.
virtual void buildBool(StringRef key, bool data)=0
Build a resource entry represented by the given bool.
virtual ~AsmResourceBuilder()
virtual void buildBlob(StringRef key, ArrayRef< char > data, uint32_t dataAlignment)=0
Build an resource entry represented by the given binary blob data.
This class represents an instance of a resource parser.
StringRef getName() const
Return the name of this parser.
virtual ~AsmResourceParser()
virtual ~AsmResourcePrinter()
static std::unique_ptr< AsmResourcePrinter > fromCallable(StringRef name, CallableT &&printFn)
Return a resource printer implemented via the given callable, whose form should match that of buildRe...
This class provides management for the lifetime of the state used when printing the IR.
DenseMap< Operation *, std::pair< unsigned, unsigned > > LocationMap
This map represents the raw locations of operations within the output stream.
detail::AsmStateImpl & getImpl()
Return an instance of the internal implementation.
void attachResourcePrinter(std::unique_ptr< AsmResourcePrinter > printer)
Attach the given resource printer to the AsmState.
DenseMap< Dialect *, SetVector< AsmDialectResourceHandle > > & getDialectResources() const
Returns a map of dialect resources that were referenced when using this state to print IR.
void attachFallbackResourcePrinter(FallbackAsmResourceMap &map)
Attach resource printers to the AsmState for the fallback resources in the given map.
const OpPrintingFlags & getPrinterFlags() const
Get the printer flags.
AsmState(Operation *op, const OpPrintingFlags &printerFlags=OpPrintingFlags(), LocationMap *locationMap=nullptr, FallbackAsmResourceMap *map=nullptr)
Initialize the asm state at the level of the given operation.
Attributes are known-constant values of operations.
Dialect & getDialect() const
Get the dialect this attribute is registered to.
const void * getAsOpaquePointer() const
Get an opaque pointer to the attribute.
void printStripped(raw_ostream &os) const
Print the attribute without dialect wrapping.
void print(raw_ostream &os, bool elideType=false) const
Print the attribute.
bool hasTrait()
Returns true if the type was registered with a particular trait.
static Attribute getFromOpaquePointer(const void *ptr)
Construct an attribute from the opaque pointer representation.
This class represents an argument of a Block.
Location getLoc() const
Return the location for this argument.
unsigned getArgNumber() const
Returns the number of this argument.
Block represents an ordered list of Operations.
iterator_range< pred_iterator > getPredecessors()
Region * getParent() const
Provide a 'getParent' method for ilist_node_with_parent methods.
Block * getSinglePredecessor()
If this block has exactly one predecessor, return it.
void printAsOperand(raw_ostream &os, bool printType=true)
Print out the name of the block without printing its body.
void print(raw_ostream &os)
BlockArgListType getArguments()
bool isEntryBlock()
Return if this block is the entry block in the parent region.
bool hasNoPredecessors()
Return true if this block has no predecessors.
Operation * getParentOp()
Returns the closest surrounding operation that contains this block.
MLIRContext * getContext() const
An attribute that represents a reference to a dense vector or tensor object.
bool isSplat() const
Returns true if this attribute corresponds to a splat, i.e.
ArrayRef< char > getRawData() const
Return the raw storage data held by this attribute.
ShapedType getType() const
Return the type of this ElementsAttr, guaranteed to be a vector or tensor with static shape.
An attribute that represents a reference to a dense integer vector or tensor object.
This class contains all of the information necessary to report a diagnostic to the DiagnosticEngine.
~DialectAsmParser() override
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
~DialectAsmPrinter() override
A collection of dialect interfaces within a context, for a given concrete interface type.
virtual void printAttribute(Attribute, DialectAsmPrinter &) const
Print an attribute registered to this dialect.
virtual void printType(Type, DialectAsmPrinter &) const
Print a type registered to this dialect.
Attribute getReferencedAttr() const
Returns the referenced attribute.
A fallback map containing external resources not explicitly handled by another parser/printer.
AsmResourceParser & getParserFor(StringRef key)
Return a parser than can be used for parsing entries for the given identifier key.
std::vector< std::unique_ptr< AsmResourcePrinter > > getPrinters()
Build a set of resource printers to print the resources within this map.
A symbol reference with a reference path containing a single element.
An integer set representing a conjunction of one or more affine equalities and inequalities.
unsigned getNumDims() const
unsigned getNumConstraints() const
AffineExpr getConstraint(unsigned idx) const
void print(raw_ostream &os) const
bool isEq(unsigned idx) const
Returns true if the idx^th constraint is an equality, false if it is an inequality.
unsigned getNumSymbols() const
Location objects represent source locations information in MLIR.
T findInstanceOf()
Return an instance of the given location type if one is nested under the current location.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
NamedAttribute represents a combination of a name and an Attribute value.
StringAttr getName() const
Return the name of the attribute.
Attribute getValue() const
Return the value of the attribute.
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
void printFunctionalType(Operation *op)
Print the complete type of an operation in functional form.
Set of flags used to control the behavior of the various IR print methods (e.g.
bool shouldElideElementsAttr(ElementsAttr attr) const
Return if the given ElementsAttr should be elided.
std::optional< int64_t > getLargeElementsAttrLimit() const
Return the size limit for printing large ElementsAttr.
bool shouldUseNameLocAsPrefix() const
Return if the printer should use NameLocs as prefixes when printing SSA IDs.
bool shouldAssumeVerified() const
Return if operation verification should be skipped.
OpPrintingFlags & printLargeElementsAttrWithHex(int64_t largeElementLimit=100)
Enables the printing of large element attributes with a hex string.
bool shouldUseLocalScope() const
Return if the printer should use local scope when dumping the IR.
bool shouldPrintDebugInfoPrettyForm() const
Return if debug information should be printed in the pretty form.
bool shouldPrintElementsAttrWithHex(ElementsAttr attr) const
Return if the given ElementsAttr should be printed as hex string.
bool shouldPrintUniqueSSAIDs() const
Return if printer should use unique SSA IDs.
bool shouldPrintValueUsers() const
Return if the printer should print users of values.
int64_t getLargeElementsAttrHexLimit() const
Return the size limit for printing large ElementsAttr as hex string.
bool shouldPrintGenericOpForm() const
Return if operations should be printed in the generic form.
OpPrintingFlags & elideLargeResourceString(int64_t largeResourceLimit=64)
Enables the elision of large resources strings by omitting them from the dialect_resources section.
bool shouldPrintDebugInfo() const
Return if debug information should be printed.
OpPrintingFlags & elideLargeElementsAttrs(int64_t largeElementLimit=16)
Enables the elision of large elements attributes by printing a lexically valid but otherwise meaningl...
OpPrintingFlags & printNameLocAsPrefix(bool enable=true)
Print SSA IDs using their NameLoc, if provided, as prefix.
OpPrintingFlags & printValueUsers(bool enable=true)
Print users of values as comments.
OpPrintingFlags & enableDebugInfo(bool enable=true, bool prettyForm=false)
Enable or disable printing of debug information (based on enable).
OpPrintingFlags()
Initialize the printing flags with default supplied by the cl::opts above.
bool shouldSkipRegions() const
Return if regions should be skipped.
OpPrintingFlags & printGenericOpForm(bool enable=true)
Always print operations in the generic form.
OpPrintingFlags & useLocalScope(bool enable=true)
Use local scope when printing the operation.
std::optional< uint64_t > getLargeResourceStringLimit() const
Return the size limit in chars for printing large resources.
OpPrintingFlags & assumeVerified(bool enable=true)
Do not verify the operation when using custom operation printers.
OpPrintingFlags & skipRegions(bool skip=true)
Skip printing regions.
OpPrintingFlags & printUniqueSSAIDs(bool enable=true)
Print unique SSA ID numbers for values, block arguments and naming conflicts across all regions.
This is a value defined by a result of an operation.
This class provides the API for ops that are known to be isolated from above.
StringRef getStringRef() const
Return the name of this operation. This always succeeds.
void 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.
PropertyRef getPropertiesStorage()
Return a generic (but typed) reference to the property type storage.
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={})
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
result_type_range getResultTypes()
LLVM_DUMP_METHOD void dumpPretty()
operand_range getOperands()
Returns an iterator on the underlying Value's.
user_range getUsers()
Returns a range of all users.
SuccessorRange getSuccessors()
result_range getResults()
MLIRContext * getContext()
Return the context this operation is associated with.
unsigned getNumResults()
Return the number of results held by this operation.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
BlockArgListType getArguments()
iterator_range< OpIterator > getOps()
unsigned getNumArguments()
BlockArgument getArgument(unsigned i)
Operation * getParentOp()
Return the parent operation this region is attached to.
BlockListType & getBlocks()
This diagnostic handler is a simple RAII class that registers and erases a diagnostic handler on a gi...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
void print(raw_ostream &os) const
Print the current type.
Dialect & getDialect() const
Get the dialect this type is registered to.
bool isSignlessInteger() const
Return true if this is a signless integer type (with the specified width).
static Type getFromOpaquePointer(const void *pointer)
const void * getAsOpaquePointer() const
Methods for supporting PointerLikeTypeTraits.
void walkImmediateSubElements(function_ref< void(Attribute)> walkAttrsFn, function_ref< void(Type)> walkTypesFn) const
Walk all of the immediately nested sub-attributes and sub-types.
bool isUnsignedInteger() const
Return true if this is an unsigned integer type (with the specified width).
bool isIntOrIndex() const
Return true if this is an integer (of any signedness) or an index type.
bool isInteger() const
Return true if this is an integer type (with the specified width).
unsigned getIntOrFloatBitWidth() const
Return the bit width of an integer or a float type, assert failure on other types.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
bool use_empty() const
Returns true if this value has no uses.
void print(raw_ostream &os) const
Type getType() const
Return the type of this value.
void printAsOperand(raw_ostream &os, AsmState &state) const
Print this value as if it were an operand.
user_range getUsers() const
Location getLoc() const
Return the location of this value.
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
SSANameState & getSSANameState()
Get the state used for SSA names.
void registerOperationLocation(Operation *op, unsigned line, unsigned col)
Register the location, line and column, within the buffer that the given operation was printed at.
auto getResourcePrinters()
Return the non-dialect resource printers.
LogicalResult pushCyclicPrinting(const void *opaquePointer)
AliasState & getAliasState()
Get the state used for aliases.
void initializeAliases(Operation *op)
Initialize the alias state to enable the printing of aliases.
const OpPrintingFlags & getPrinterFlags() const
Get the printer flags.
DenseMap< Dialect *, SetVector< AsmDialectResourceHandle > > & getDialectResources()
Return the referenced dialect resources within the printer.
AsmStateImpl(Operation *op, const OpPrintingFlags &printerFlags, AsmState::LocationMap *locationMap)
AsmStateImpl(MLIRContext *ctx, const OpPrintingFlags &printerFlags, AsmState::LocationMap *locationMap)
DistinctState & getDistinctState()
Get the state used for distinct attribute identifiers.
DialectInterfaceCollection< OpAsmDialectInterface > & getDialectInterfaces()
Return the dialects within the context that implement OpAsmDialectInterface.
static DenseArrayAttrImpl get(MLIRContext *context, ArrayRef< int64_t > content)
detail::StorageUserTrait::IsMutable< ConcreteType > IsMutable
This trait is used to determine if an attribute is mutable or not.
void printType(Type type, AsmPrinter &printer)
Prints an LLVM Dialect type.
static void printDimensionList(raw_ostream &stream, Range &&shape)
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
bool operator<(const Fraction &x, const Fraction &y)
Include the generated interface declarations.
detail::DenseArrayAttrImpl< int64_t > DenseI64ArrayAttr
ParseResult parseDimensionList(OpAsmParser &parser, DenseI64ArrayAttr &dimensions)
StringRef toString(AsmResourceEntryKind kind)
raw_ostream & operator<<(raw_ostream &os, const AliasResult &result)
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
void printDimensionList(OpAsmPrinter &printer, Operation *op, ArrayRef< int64_t > dimensions)
@ CeilDiv
RHS of ceildiv is always a constant or a symbolic expression.
@ Mul
RHS of mul is always a constant or a symbolic expression.
@ Mod
RHS of mod is always a constant or a symbolic expression with a positive value.
@ DimId
Dimensional identifier.
@ FloorDiv
RHS of floordiv is always a constant or a symbolic expression.
@ Constant
Constant integer.
@ SymbolId
Symbolic identifier.
llvm::SetVector< T, Vector, Set, N > SetVector
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...