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"
95 llvm::interleaveComma(operands,
getStream(),
100 llvm::interleaveComma(types, *
this);
108 *this << (operand ? operand.getType() : Type());
124 *this << (result ? result.getType() : Type());
136#include "mlir/IR/OpAsmAttrInterface.cpp.inc"
137#include "mlir/IR/OpAsmOpInterface.cpp.inc"
138#include "mlir/IR/OpAsmTypeInterface.cpp.inc"
142 return entry.
emitError() <<
"unknown 'resource' key '" << entry.
getKey()
143 <<
"' for dialect '" << getDialect()->getNamespace()
155struct AsmPrinterOptions {
156 llvm::cl::opt<int64_t> printElementsAttrWithHexIfLarger{
157 "mlir-print-elementsattrs-with-hex-if-larger",
159 "Print DenseElementsAttrs with a hex string that have "
160 "more elements than the given upper limit (use -1 to disable)")};
162 llvm::cl::opt<unsigned> elideElementsAttrIfLarger{
163 "mlir-elide-elementsattrs-if-larger",
164 llvm::cl::desc(
"Elide ElementsAttrs with \"...\" that have "
165 "more elements than the given upper limit")};
167 llvm::cl::opt<unsigned> elideResourceStringsIfLarger{
168 "mlir-elide-resource-strings-if-larger",
170 "Elide printing value of resources if string is too long in chars.")};
172 llvm::cl::opt<bool> printDebugInfoOpt{
173 "mlir-print-debuginfo", llvm::cl::init(
false),
174 llvm::cl::desc(
"Print debug info in MLIR output")};
176 llvm::cl::opt<bool> printPrettyDebugInfoOpt{
177 "mlir-pretty-debuginfo", llvm::cl::init(
false),
178 llvm::cl::desc(
"Print pretty debug info in MLIR output")};
182 llvm::cl::opt<bool> printGenericOpFormOpt{
183 "mlir-print-op-generic", llvm::cl::init(
false),
184 llvm::cl::desc(
"Print the generic op form"), llvm::cl::Hidden};
186 llvm::cl::opt<bool> assumeVerifiedOpt{
187 "mlir-print-assume-verified", llvm::cl::init(
false),
188 llvm::cl::desc(
"Skip op verification when using custom printers"),
191 llvm::cl::opt<bool> printLocalScopeOpt{
192 "mlir-print-local-scope", llvm::cl::init(
false),
193 llvm::cl::desc(
"Print with local scope and inline information (eliding "
194 "aliases for attributes, types, and locations)")};
196 llvm::cl::opt<bool> skipRegionsOpt{
197 "mlir-print-skip-regions", llvm::cl::init(
false),
198 llvm::cl::desc(
"Skip regions when printing ops.")};
200 llvm::cl::opt<bool> printValueUsers{
201 "mlir-print-value-users", llvm::cl::init(
false),
203 "Print users of operation results and block arguments as a comment")};
205 llvm::cl::opt<bool> printUniqueSSAIDs{
206 "mlir-print-unique-ssa-ids", llvm::cl::init(
false),
207 llvm::cl::desc(
"Print unique SSA ID numbers for values, block arguments "
208 "and naming conflicts across all regions")};
210 llvm::cl::opt<bool> useNameLocAsPrefix{
211 "mlir-use-nameloc-as-prefix", llvm::cl::init(
false),
212 llvm::cl::desc(
"Print SSA IDs using NameLocs as prefixes")};
214 llvm::cl::opt<bool> alwaysUseAliasesOpt{
215 "mlir-print-always-use-aliases", llvm::cl::init(
false),
216 llvm::cl::desc(
"Always use aliases even for non top-level ops")};
231 : printDebugInfoFlag(
false), printDebugInfoPrettyFormFlag(
false),
232 printGenericOpFormFlag(
false), skipRegionsFlag(
false),
233 assumeVerifiedFlag(
false), alwaysUseAliasesFlag(
false),
234 printLocalScope(
false), printValueUsersFlag(
false),
235 printUniqueSSAIDsFlag(
false), useNameLocAsPrefix(
false) {
239 if (
clOptions->elideElementsAttrIfLarger.getNumOccurrences())
240 elementsAttrElementLimit =
clOptions->elideElementsAttrIfLarger;
241 if (
clOptions->printElementsAttrWithHexIfLarger.getNumOccurrences())
242 elementsAttrHexElementLimit =
243 clOptions->printElementsAttrWithHexIfLarger.getValue();
244 if (
clOptions->elideResourceStringsIfLarger.getNumOccurrences())
245 resourceStringCharLimit =
clOptions->elideResourceStringsIfLarger;
246 printDebugInfoFlag =
clOptions->printDebugInfoOpt;
247 printDebugInfoPrettyFormFlag =
clOptions->printPrettyDebugInfoOpt;
248 printGenericOpFormFlag =
clOptions->printGenericOpFormOpt;
249 assumeVerifiedFlag =
clOptions->assumeVerifiedOpt;
250 printLocalScope =
clOptions->printLocalScopeOpt;
251 skipRegionsFlag =
clOptions->skipRegionsOpt;
252 printValueUsersFlag =
clOptions->printValueUsers;
253 printUniqueSSAIDsFlag =
clOptions->printUniqueSSAIDs;
254 useNameLocAsPrefix =
clOptions->useNameLocAsPrefix;
255 alwaysUseAliasesFlag =
clOptions->alwaysUseAliasesOpt;
264 elementsAttrElementLimit = largeElementLimit;
270 elementsAttrHexElementLimit = largeElementLimit;
276 resourceStringCharLimit = largeResourceLimit;
284 printDebugInfoFlag = enable;
285 printDebugInfoPrettyFormFlag = prettyForm;
291 printGenericOpFormFlag = enable;
297 skipRegionsFlag = skip;
303 assumeVerifiedFlag = enable;
308 alwaysUseAliasesFlag = enable;
316 printLocalScope = enable;
322 printValueUsersFlag = enable;
329 printUniqueSSAIDsFlag = enable;
335 return elementsAttrElementLimit &&
336 *elementsAttrElementLimit <
int64_t(attr.getNumElements()) &&
337 !llvm::isa<SplatElementsAttr>(attr);
343 return (elementsAttrHexElementLimit != -1) &&
344 (elementsAttrHexElementLimit <
int64_t(attr.getNumElements())) &&
345 !llvm::isa<SplatElementsAttr>(attr);
349 useNameLocAsPrefix = enable;
355 return elementsAttrElementLimit;
360 return elementsAttrHexElementLimit;
365 return resourceStringCharLimit;
370 return printDebugInfoFlag;
375 return printDebugInfoPrettyFormFlag;
380 return printGenericOpFormFlag;
388 return assumeVerifiedFlag;
392 return alwaysUseAliasesFlag;
400 return printValueUsersFlag;
410 return useNameLocAsPrefix;
421struct NewLineCounter {
422 unsigned curLine = 1;
459 template <
typename Container,
typename UnaryFunctor>
461 llvm::interleaveComma(c,
os, eachFn);
508 function_ref<
void(
unsigned,
bool)> printValueName =
nullptr);
521 bool withKeyword =
false);
524 bool isTopLevel =
false);
542 DenseElementType denseEltType);
566 function_ref<
void(
unsigned,
bool)> printValueName =
nullptr);
596 SymbolAlias(StringRef name, uint32_t suffixIndex,
bool isType,
598 : name(name), suffixIndex(suffixIndex), isType(isType),
599 isDeferrable(isDeferrable) {}
603 os << (isType ?
"!" :
"#") << name;
605 if (isdigit(name.back()))
612 bool isTypeAlias()
const {
return isType; }
615 bool canBeDeferred()
const {
return isDeferrable; }
621 uint32_t suffixIndex : 30;
625 bool isDeferrable : 1;
629 bool isPrinted =
false;
635class AliasInitializer {
638 DialectInterfaceCollection<OpAsmDialectInterface> &interfaces,
639 llvm::BumpPtrAllocator &aliasAllocator)
640 : interfaces(interfaces), aliasAllocator(aliasAllocator),
641 aliasOS(aliasBuffer) {}
643 void initialize(Operation *op,
const OpPrintingFlags &printerFlags,
644 llvm::MapVector<const void *, SymbolAlias> &attrTypeToAlias);
652 std::pair<size_t, size_t>
visit(Attribute attr,
bool canBeDeferred =
false,
653 bool elideType =
false) {
654 return visitImpl(attr, aliases, canBeDeferred, elideType);
661 std::pair<size_t, size_t>
visit(Type type,
bool canBeDeferred =
false) {
662 return visitImpl(type, aliases, canBeDeferred);
666 struct InProgressAliasInfo {
667 InProgressAliasInfo()
668 : aliasDepth(0), isType(
false), canBeDeferred(
false) {}
669 InProgressAliasInfo(StringRef alias)
670 : alias(alias), aliasDepth(1), isType(
false), canBeDeferred(
false) {}
674 if (aliasDepth !=
rhs.aliasDepth)
675 return aliasDepth <
rhs.aliasDepth;
676 if (isType !=
rhs.isType)
678 return alias <
rhs.alias;
683 std::optional<StringRef> alias;
686 unsigned aliasDepth : 30;
690 bool canBeDeferred : 1;
692 SmallVector<size_t> childIndices;
700 template <
typename T,
typename... PrintArgs>
701 std::pair<size_t, size_t>
703 llvm::MapVector<const void *, InProgressAliasInfo> &aliases,
704 bool canBeDeferred, PrintArgs &&...
printArgs);
707 void markAliasNonDeferrable(
size_t aliasIndex);
711 template <
typename T>
712 void generateAlias(T symbol, InProgressAliasInfo &alias,
bool canBeDeferred);
717 uniqueAliasNameIndex(StringRef alias, llvm::StringMap<unsigned> &nameCounts,
718 llvm::StringSet<llvm::BumpPtrAllocator &> &usedAliases);
722 static void initializeAliases(
723 llvm::MapVector<const void *, InProgressAliasInfo> &visitedSymbols,
724 llvm::MapVector<const void *, SymbolAlias> &symbolToAlias);
727 DialectInterfaceCollection<OpAsmDialectInterface> &interfaces;
730 llvm::BumpPtrAllocator &aliasAllocator;
733 llvm::MapVector<const void *, InProgressAliasInfo> aliases;
736 SmallString<32> aliasBuffer;
737 llvm::raw_svector_ostream aliasOS;
745class DummyAliasOperationPrinter :
private OpAsmPrinter {
747 explicit DummyAliasOperationPrinter(
const OpPrintingFlags &printerFlags,
748 AliasInitializer &initializer)
749 : printerFlags(printerFlags), initializer(initializer) {}
753 void printCustomOrGenericOp(Operation *op)
override {
755 if (printerFlags.shouldPrintDebugInfo())
756 initializer.visit(op->
getLoc(),
true);
759 if (!printerFlags.shouldPrintGenericOpForm()) {
770 void printGenericOp(Operation *op,
bool printOpName =
true)
override {
772 if (!printerFlags.shouldSkipRegions()) {
782 if (operand && operand.getType())
789 printAttribute(attr.getValue());
791 op, [&](StringRef, Attribute &attr) { printAttribute(attr); });
797 void print(
Block *block,
bool printBlockArgs =
true,
798 bool printBlockTerminator =
true) {
801 if (printBlockArgs) {
806 if (printerFlags.shouldPrintDebugInfo())
808 initializer.visit(arg.getLoc(),
false);
816 auto range = llvm::make_range(
818 std::prev(block->
end(),
819 (!hasTerminator || printBlockTerminator) ? 0 : 1));
820 for (Operation &op : range)
821 printCustomOrGenericOp(&op);
825 void printRegion(Region ®ion,
bool printEntryBlockArgs,
826 bool printBlockTerminators,
827 bool printEmptyBlock =
false)
override {
830 if (printerFlags.shouldSkipRegions()) {
835 auto *entryBlock = ®ion.
front();
836 print(entryBlock, printEntryBlockArgs, printBlockTerminators);
837 for (
Block &
b : llvm::drop_begin(region, 1))
841 void printRegionArgument(BlockArgument arg, ArrayRef<NamedAttribute> argAttrs,
842 bool omitType)
override {
845 if (printerFlags.shouldPrintDebugInfo())
847 initializer.visit(arg.
getLoc(),
false);
853 initializer.visit(type);
857 void printAttribute(Attribute attr)
override { initializer.visit(attr); }
858 void printAttributeWithoutType(Attribute attr)
override {
859 printAttribute(attr);
861 void printNamedAttribute(NamedAttribute attr)
override {
865 LogicalResult printAlias(Attribute attr)
override {
866 initializer.visit(attr);
869 LogicalResult printAlias(Type type)
override {
870 initializer.visit(type);
875 void printOptionalLocationSpecifier(Location loc)
override {
881 void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
882 ArrayRef<StringRef> elidedAttrs = {})
override {
885 if (elidedAttrs.empty()) {
886 for (
const NamedAttribute &attr : attrs)
887 printAttribute(attr.getValue());
890 llvm::SmallDenseSet<StringRef> elidedAttrsSet(elidedAttrs.begin(),
892 for (
const NamedAttribute &attr : attrs)
893 if (!elidedAttrsSet.contains(attr.getName().strref()))
894 printAttribute(attr.getValue());
896 void printOptionalAttrDictWithKeyword(
897 ArrayRef<NamedAttribute> attrs,
898 ArrayRef<StringRef> elidedAttrs = {})
override {
899 printOptionalAttrDict(attrs, elidedAttrs);
904 raw_ostream &getStream()
const override {
return os; }
908 void printFloat(
const APFloat &)
override {}
909 void printAffineMapOfSSAIds(AffineMapAttr,
ValueRange)
override {}
912 void increaseIndent()
override {}
913 void decreaseIndent()
override {}
914 void printOperand(Value)
override {}
915 void printOperand(Value, raw_ostream &os)
override {
923 void printResourceHandle(
const AsmDialectResourceHandle &)
override {}
924 void printSymbolName(StringRef)
override {}
925 void printSuccessor(
Block *)
override {}
927 void shadowRegionArgs(Region &,
ValueRange)
override {}
930 const OpPrintingFlags &printerFlags;
933 AliasInitializer &initializer;
936 mutable llvm::raw_null_ostream os;
941 explicit DummyAliasDialectAsmPrinter(AliasInitializer &initializer,
943 SmallVectorImpl<size_t> &childIndices)
944 : initializer(initializer), canBeDeferred(canBeDeferred),
945 childIndices(childIndices) {}
950 template <
typename T,
typename... PrintArgs>
951 size_t printAndVisitNestedAliases(T value, PrintArgs &&...
printArgs) {
952 printAndVisitNestedAliasesImpl(value,
printArgs...);
953 return maxAliasDepth;
959 void printAndVisitNestedAliasesImpl(Attribute attr,
bool elideType) {
960 if (!isa<BuiltinDialect>(attr.
getDialect())) {
964 }
else if (llvm::isa<AffineMapAttr, DenseArrayAttr, FloatAttr, IntegerAttr,
965 IntegerSetAttr, UnitAttr>(attr)) {
967 }
else if (
auto distinctAttr = dyn_cast<DistinctAttr>(attr)) {
968 printAttribute(distinctAttr.getReferencedAttr());
969 }
else if (
auto dictAttr = dyn_cast<DictionaryAttr>(attr)) {
970 for (
const NamedAttribute &nestedAttr : dictAttr.getValue()) {
971 printAttribute(nestedAttr.getName());
972 printAttribute(nestedAttr.getValue());
974 }
else if (
auto arrayAttr = dyn_cast<ArrayAttr>(attr)) {
975 for (Attribute nestedAttr : arrayAttr.getValue())
976 printAttribute(nestedAttr);
977 }
else if (
auto typeAttr = dyn_cast<TypeAttr>(attr)) {
979 }
else if (
auto locAttr = dyn_cast<OpaqueLoc>(attr)) {
980 printAttribute(locAttr.getFallbackLocation());
981 }
else if (
auto locAttr = dyn_cast<NameLoc>(attr)) {
982 if (!isa<UnknownLoc>(locAttr.getChildLoc()))
983 printAttribute(locAttr.getChildLoc());
984 }
else if (
auto locAttr = dyn_cast<CallSiteLoc>(attr)) {
985 printAttribute(locAttr.getCallee());
986 printAttribute(locAttr.getCaller());
987 }
else if (
auto locAttr = dyn_cast<FusedLoc>(attr)) {
988 if (Attribute metadata = locAttr.getMetadata())
989 printAttribute(metadata);
990 for (Location nestedLoc : locAttr.getLocations())
991 printAttribute(nestedLoc);
996 if (
auto typedAttr = llvm::dyn_cast<TypedAttr>(attr)) {
997 Type attrType = typedAttr.getType();
998 if (!llvm::isa<NoneType>(attrType))
1003 void printAndVisitNestedAliasesImpl(Type type) {
1010 if (
auto memrefTy = llvm::dyn_cast<MemRefType>(type)) {
1012 MemRefLayoutAttrInterface layout = memrefTy.getLayout();
1013 if (!llvm::isa<AffineMapAttr>(layout) || !layout.isIdentity())
1014 printAttribute(memrefTy.getLayout());
1015 if (memrefTy.getMemorySpace())
1016 printAttribute(memrefTy.getMemorySpace());
1021 auto visitFn = [&](
auto element) {
1023 (void)printAlias(element);
1030 recordAliasResult(initializer.visit(type, canBeDeferred));
1034 void printAttribute(Attribute attr)
override {
1035 recordAliasResult(initializer.visit(attr, canBeDeferred));
1037 void printAttributeWithoutType(Attribute attr)
override {
1039 initializer.visit(attr, canBeDeferred,
true));
1041 void printNamedAttribute(NamedAttribute attr)
override {
1045 LogicalResult printAlias(Attribute attr)
override {
1046 printAttribute(attr);
1049 LogicalResult printAlias(Type type)
override {
1055 void recordAliasResult(std::pair<size_t, size_t> aliasDepthAndIndex) {
1056 childIndices.push_back(aliasDepthAndIndex.second);
1057 if (aliasDepthAndIndex.first > maxAliasDepth)
1058 maxAliasDepth = aliasDepthAndIndex.first;
1063 raw_ostream &getStream()
const override {
return os; }
1068 void increaseIndent()
override {}
1069 void decreaseIndent()
override {}
1070 void printFloat(
const APFloat &)
override {}
1073 void printSymbolName(StringRef)
override {}
1074 void printResourceHandle(
const AsmDialectResourceHandle &)
override {}
1076 LogicalResult pushCyclicPrinting(
const void *opaquePointer)
override {
1077 return success(cyclicPrintingStack.insert(opaquePointer));
1080 void popCyclicPrinting()
override { cyclicPrintingStack.pop_back(); }
1084 SetVector<const void *> cyclicPrintingStack;
1087 AliasInitializer &initializer;
1093 SmallVectorImpl<size_t> &childIndices;
1096 size_t maxAliasDepth = 0;
1099 mutable llvm::raw_null_ostream os;
1107 StringRef allowedPunctChars =
"$._-") {
1108 assert(!name.empty() &&
"Shouldn't have an empty name here");
1110 auto validChar = [&](
char ch) {
1111 return llvm::isAlnum(ch) || allowedPunctChars.contains(ch);
1114 auto copyNameToBuffer = [&] {
1115 for (
char ch : name) {
1117 buffer.push_back(ch);
1119 buffer.push_back(
'_');
1121 buffer.append(llvm::utohexstr((
unsigned char)ch));
1128 if (isdigit(name[0]) || (!validChar(name[0]) && name[0] !=
' ')) {
1129 buffer.push_back(
'_');
1135 for (
char ch : name) {
1136 if (!validChar(ch)) {
1146unsigned AliasInitializer::uniqueAliasNameIndex(
1147 StringRef alias, llvm::StringMap<unsigned> &nameCounts,
1148 llvm::StringSet<llvm::BumpPtrAllocator &> &usedAliases) {
1149 if (!usedAliases.count(alias)) {
1150 usedAliases.insert(alias);
1156 size_t probeSize = probeAlias.size();
1158 if (isdigit(alias.back())) {
1159 probeAlias.push_back(
'_');
1163 if (nameCounts[probeAlias] == 0)
1164 nameCounts[probeAlias] = 1;
1168 unsigned nameIndex = nameCounts[probeAlias]++;
1169 probeAlias += llvm::utostr(nameIndex);
1170 if (!usedAliases.count(probeAlias)) {
1171 usedAliases.insert(probeAlias);
1175 probeAlias.resize(probeSize);
1181void AliasInitializer::initializeAliases(
1182 llvm::MapVector<const void *, InProgressAliasInfo> &visitedSymbols,
1183 llvm::MapVector<const void *, SymbolAlias> &symbolToAlias) {
1185 unprocessedAliases = visitedSymbols.takeVector();
1186 llvm::stable_sort(unprocessedAliases, llvm::less_second());
1190 llvm::BumpPtrAllocator usedAliasAllocator;
1191 llvm::StringSet<llvm::BumpPtrAllocator &> usedAliases(usedAliasAllocator);
1193 llvm::StringMap<unsigned> nameCounts;
1194 for (
auto &[symbol, aliasInfo] : unprocessedAliases) {
1195 if (!aliasInfo.alias)
1197 StringRef alias = *aliasInfo.alias;
1198 unsigned nameIndex = uniqueAliasNameIndex(alias, nameCounts, usedAliases);
1199 symbolToAlias.insert(
1200 {symbol, SymbolAlias(alias, nameIndex, aliasInfo.isType,
1201 aliasInfo.canBeDeferred)});
1205void AliasInitializer::initialize(
1207 llvm::MapVector<const void *, SymbolAlias> &attrTypeToAlias) {
1211 DummyAliasOperationPrinter aliasPrinter(printerFlags, *
this);
1212 aliasPrinter.printCustomOrGenericOp(op);
1215 initializeAliases(aliases, attrTypeToAlias);
1218template <
typename T,
typename... PrintArgs>
1219std::pair<size_t, size_t> AliasInitializer::visitImpl(
1220 T value, llvm::MapVector<const void *, InProgressAliasInfo> &aliases,
1221 bool canBeDeferred, PrintArgs &&...
printArgs) {
1222 auto [it,
inserted] = aliases.try_emplace(value.getAsOpaquePointer());
1223 size_t aliasIndex = std::distance(aliases.begin(), it);
1227 markAliasNonDeferrable(aliasIndex);
1228 return {
static_cast<size_t>(it->second.aliasDepth), aliasIndex};
1232 generateAlias(value, it->second, canBeDeferred);
1233 it->second.isType = std::is_base_of_v<Type, T>;
1234 it->second.canBeDeferred = canBeDeferred;
1238 DummyAliasDialectAsmPrinter printer(*
this, canBeDeferred, childAliases);
1239 size_t maxAliasDepth =
1240 printer.printAndVisitNestedAliases(value,
printArgs...);
1243 it = std::next(aliases.begin(), aliasIndex);
1246 it->second.childIndices = std::move(childAliases);
1248 it->second.aliasDepth = maxAliasDepth + 1;
1251 return {(size_t)it->second.aliasDepth, aliasIndex};
1254void AliasInitializer::markAliasNonDeferrable(
size_t aliasIndex) {
1255 auto *it = std::next(aliases.begin(), aliasIndex);
1259 if (!it->second.canBeDeferred)
1262 it->second.canBeDeferred =
false;
1265 for (
size_t childIndex : it->second.childIndices)
1266 markAliasNonDeferrable(childIndex);
1269template <
typename T>
1270void AliasInitializer::generateAlias(T symbol, InProgressAliasInfo &alias,
1271 bool canBeDeferred) {
1274 OpAsmDialectInterface::AliasResult symbolInterfaceResult =
1275 OpAsmDialectInterface::AliasResult::NoAlias;
1276 using InterfaceT = std::conditional_t<std::is_base_of_v<Attribute, T>,
1277 OpAsmAttrInterface, OpAsmTypeInterface>;
1278 if (
auto symbolInterface = dyn_cast<InterfaceT>(symbol)) {
1279 symbolInterfaceResult = symbolInterface.getAlias(aliasOS);
1280 if (symbolInterfaceResult != OpAsmDialectInterface::AliasResult::NoAlias) {
1281 nameBuffer = std::move(aliasBuffer);
1282 assert(!nameBuffer.empty() &&
"expected valid alias name");
1286 if (symbolInterfaceResult != OpAsmDialectInterface::AliasResult::FinalAlias) {
1287 for (
const auto &interface : interfaces) {
1288 OpAsmDialectInterface::AliasResult
result =
1289 interface.getAlias(symbol, aliasOS);
1290 if (
result == OpAsmDialectInterface::AliasResult::NoAlias)
1292 nameBuffer = std::move(aliasBuffer);
1293 assert(!nameBuffer.empty() &&
"expected valid alias name");
1294 if (
result == OpAsmDialectInterface::AliasResult::FinalAlias)
1299 if (nameBuffer.empty())
1305 name = name.copy(aliasAllocator);
1306 alias = InProgressAliasInfo(name);
1319 initialize(Operation *op,
const OpPrintingFlags &printerFlags,
1320 DialectInterfaceCollection<OpAsmDialectInterface> &interfaces);
1324 LogicalResult getAlias(Attribute attr, raw_ostream &os)
const;
1328 LogicalResult getAlias(Type ty, raw_ostream &os)
const;
1332 void printNonDeferredAliases(AsmPrinter::Impl &p, NewLineCounter &newLine) {
1333 printAliases(p, newLine,
false);
1337 void printDeferredAliases(AsmPrinter::Impl &p, NewLineCounter &newLine) {
1338 printAliases(p, newLine,
true);
1344 void printAliases(AsmPrinter::Impl &p, NewLineCounter &newLine,
1348 llvm::MapVector<const void *, SymbolAlias> attrTypeToAlias;
1351 llvm::BumpPtrAllocator aliasAllocator;
1355void AliasState::initialize(
1360 attrTypeToAlias.clear();
1361 AliasInitializer initializer(interfaces, aliasAllocator);
1362 initializer.initialize(op, printerFlags, attrTypeToAlias);
1367 if (it == attrTypeToAlias.end())
1369 it->second.print(os);
1375 if (it == attrTypeToAlias.end())
1377 if (!it->second.isPrinted)
1380 it->second.print(os);
1386 auto filterFn = [=](
const auto &aliasIt) {
1387 return aliasIt.second.canBeDeferred() == isDeferred;
1389 for (
auto &[opaqueSymbol, alias] :
1390 llvm::make_filter_range(attrTypeToAlias, filterFn)) {
1394 if (alias.isTypeAlias()) {
1397 alias.isPrinted =
true;
1427 enum :
unsigned { NameSentinel = ~0U };
1429 SSANameState(Operation *op,
const OpPrintingFlags &printerFlags);
1430 SSANameState() =
default;
1435 void printValueID(Value value,
bool printResultNo, raw_ostream &stream)
const;
1438 void printOperationID(Operation *op, raw_ostream &stream)
const;
1442 ArrayRef<int> getOpResultGroups(Operation *op);
1445 BlockInfo getBlockInfo(
Block *block);
1450 void shadowRegionArgs(Region ®ion,
ValueRange namesToUse);
1454 void numberValuesInRegion(Region ®ion);
1455 void numberValuesInBlock(
Block &block);
1456 void numberValuesInOp(Operation &op);
1462 void getResultIDAndNumber(OpResult
result, Value &lookupValue,
1463 std::optional<int> &lookupResultNo)
const;
1466 void setValueName(Value value, StringRef name);
1470 StringRef uniqueValueName(StringRef name);
1493 llvm::ScopedHashTable<StringRef, char> usedNames;
1494 llvm::BumpPtrAllocator usedNameAllocator;
1497 unsigned nextValueID = 0;
1499 unsigned nextArgumentID = 0;
1501 unsigned nextConflictID = 0;
1505 OpPrintingFlags printerFlags;
1510 : printerFlags(printerFlags) {
1511 llvm::SaveAndRestore valueIDSaver(nextValueID);
1512 llvm::SaveAndRestore argumentIDSaver(nextArgumentID);
1513 llvm::SaveAndRestore conflictIDSaver(nextConflictID);
1518 using UsedNamesScopeTy = llvm::ScopedHashTable<StringRef, char>::ScopeTy;
1519 using NamingContext =
1520 std::tuple<Region *, unsigned, unsigned, unsigned, UsedNamesScopeTy *>;
1523 llvm::BumpPtrAllocator allocator;
1526 auto *topLevelNamesScope =
1527 new (allocator.Allocate<UsedNamesScopeTy>()) UsedNamesScopeTy(usedNames);
1531 nameContext.push_back(std::make_tuple(®ion, nextValueID, nextArgumentID,
1532 nextConflictID, topLevelNamesScope));
1534 numberValuesInOp(*op);
1536 while (!nameContext.empty()) {
1538 UsedNamesScopeTy *parentScope;
1542 std::tie(region, std::ignore, std::ignore, std::ignore, parentScope) =
1543 nameContext.pop_back_val();
1545 std::tie(region, nextValueID, nextArgumentID, nextConflictID,
1546 parentScope) = nameContext.pop_back_val();
1550 while (usedNames.getCurScope() != parentScope) {
1551 usedNames.getCurScope()->~UsedNamesScopeTy();
1552 assert((usedNames.getCurScope() !=
nullptr || parentScope ==
nullptr) &&
1553 "top level parentScope must be a nullptr");
1557 auto *curNamesScope =
new (allocator.Allocate<UsedNamesScopeTy>())
1558 UsedNamesScopeTy(usedNames);
1560 numberValuesInRegion(*region);
1564 nameContext.push_back(std::make_tuple(®ion, nextValueID,
1565 nextArgumentID, nextConflictID,
1570 while (usedNames.getCurScope() !=
nullptr)
1571 usedNames.getCurScope()->~UsedNamesScopeTy();
1574void SSANameState::printValueID(
Value value,
bool printResultNo,
1577 stream <<
"<<NULL VALUE>>";
1581 std::optional<int> resultNo;
1582 auto lookupValue = value;
1586 if (OpResult
result = dyn_cast<OpResult>(value))
1587 getResultIDAndNumber(
result, lookupValue, resultNo);
1589 auto it = valueIDs.find(lookupValue);
1590 if (it == valueIDs.end()) {
1591 stream <<
"<<UNKNOWN SSA VALUE>>";
1596 if (it->second != NameSentinel) {
1597 stream << it->second;
1599 auto nameIt = valueNames.find(lookupValue);
1600 assert(nameIt != valueNames.end() &&
"Didn't have a name entry?");
1601 stream << nameIt->second;
1604 if (resultNo && printResultNo)
1605 stream <<
'#' << *resultNo;
1608void SSANameState::printOperationID(Operation *op, raw_ostream &stream)
const {
1609 auto it = operationIDs.find(op);
1610 if (it == operationIDs.end()) {
1611 stream <<
"<<UNKNOWN OPERATION>>";
1613 stream <<
'%' << it->second;
1617ArrayRef<int> SSANameState::getOpResultGroups(Operation *op) {
1618 auto it = opResultGroups.find(op);
1619 return it == opResultGroups.end() ? ArrayRef<int>() : it->second;
1622BlockInfo SSANameState::getBlockInfo(
Block *block) {
1623 auto it = blockNames.find(block);
1624 BlockInfo invalidBlock{-1,
"INVALIDBLOCK"};
1625 return it != blockNames.end() ? it->second : invalidBlock;
1628void SSANameState::shadowRegionArgs(Region ®ion,
ValueRange namesToUse) {
1629 assert(!region.
empty() &&
"cannot shadow arguments of an empty region");
1631 "incorrect number of names passed in");
1633 "only KnownIsolatedFromAbove ops can shadow names");
1635 SmallVector<char, 16> nameStr;
1636 for (
unsigned i = 0, e = namesToUse.size(); i != e; ++i) {
1637 auto nameToUse = namesToUse[i];
1638 if (nameToUse ==
nullptr)
1643 llvm::raw_svector_ostream nameStream(nameStr);
1644 printValueID(nameToUse,
true, nameStream);
1647 assert(valueIDs[nameToReplace] == NameSentinel);
1650 auto name = StringRef(nameStream.str()).drop_front();
1653 valueNames[nameToReplace] = name.copy(usedNameAllocator);
1659StringRef maybeGetValueNameFromLoc(Value value, StringRef name) {
1661 return maybeNameLoc.getName();
1666void SSANameState::numberValuesInRegion(Region ®ion) {
1668 bool opAsmOpInterfaceUsed =
false;
1669 auto setBlockArgNameFn = [&](Value arg, StringRef name) {
1670 assert(!valueIDs.count(arg) &&
"arg numbered multiple times");
1671 assert(llvm::cast<BlockArgument>(arg).getOwner()->getParent() == ®ion &&
1672 "arg not defined in current region");
1673 opAsmOpInterfaceUsed =
true;
1675 name = maybeGetValueNameFromLoc(arg, name);
1676 setValueName(arg, name);
1681 if (
auto asmInterface = dyn_cast<OpAsmOpInterface>(op))
1682 asmInterface.getAsmBlockArgumentNames(region, setBlockArgNameFn);
1684 if (!opAsmOpInterfaceUsed) {
1686 if (
auto interface = dyn_cast<OpAsmTypeInterface>(arg.
getType())) {
1687 interface.getAsmName(
1688 [&](StringRef name) { setBlockArgNameFn(arg, name); });
1696 unsigned nextBlockID = 0;
1697 for (
auto &block : region) {
1700 auto blockInfoIt = blockNames.insert({&block, {-1,
""}});
1701 if (blockInfoIt.second) {
1705 llvm::raw_string_ostream(name) <<
"^bb" << nextBlockID;
1706 blockInfoIt.first->second.name = StringRef(name).copy(usedNameAllocator);
1708 blockInfoIt.first->second.ordering = nextBlockID++;
1710 numberValuesInBlock(block);
1714void SSANameState::numberValuesInBlock(
Block &block) {
1718 SmallString<32> specialNameBuffer(isEntryBlock ?
"arg" :
"");
1719 llvm::raw_svector_ostream specialName(specialNameBuffer);
1721 if (valueIDs.count(arg))
1724 specialNameBuffer.resize(strlen(
"arg"));
1725 specialName << nextArgumentID++;
1727 StringRef specialNameStr = specialName.str();
1729 specialNameStr = maybeGetValueNameFromLoc(arg, specialNameStr);
1730 setValueName(arg, specialNameStr);
1734 for (
auto &op : block)
1735 numberValuesInOp(op);
1738void SSANameState::numberValuesInOp(Operation &op) {
1740 SmallVector<int, 2> resultGroups(1, 0);
1742 bool opAsmOpInterfaceUsed =
false;
1743 auto setResultNameFn = [&](Value
result, StringRef name) {
1744 assert(!valueIDs.count(
result) &&
"result numbered multiple times");
1745 assert(
result.getDefiningOp() == &op &&
"result not defined by 'op'");
1746 opAsmOpInterfaceUsed =
true;
1748 name = maybeGetValueNameFromLoc(
result, name);
1749 setValueName(
result, name);
1752 if (
int resultNo = llvm::cast<OpResult>(
result).getResultNumber())
1753 resultGroups.push_back(resultNo);
1756 auto setBlockNameFn = [&](
Block *block, StringRef name) {
1758 "getAsmBlockArgumentNames callback invoked on a block not directly "
1759 "nested under the current operation");
1760 assert(!blockNames.count(block) &&
"block numbered multiple times");
1761 SmallString<16> tmpBuffer{
"^"};
1763 if (name.data() != tmpBuffer.data()) {
1764 tmpBuffer.append(name);
1765 name = tmpBuffer.str();
1767 name = name.copy(usedNameAllocator);
1768 blockNames[block] = {-1, name};
1772 if (OpAsmOpInterface asmInterface = dyn_cast<OpAsmOpInterface>(&op)) {
1773 asmInterface.getAsmBlockNames(setBlockNameFn);
1774 asmInterface.getAsmResultNames(setResultNameFn);
1776 if (!opAsmOpInterfaceUsed) {
1779 bool allHaveOpAsmTypeInterface =
1781 return isa<OpAsmTypeInterface>(type);
1783 if (allHaveOpAsmTypeInterface) {
1785 auto interface = cast<OpAsmTypeInterface>(
result.
getType());
1786 interface.getAsmName(
1787 [&](StringRef name) { setResultNameFn(
result, name); });
1794 if (numResults == 0) {
1797 if (operationIDs.try_emplace(&op, nextValueID).second)
1806 setValueName(resultBegin, nameLoc.getName());
1811 if (valueIDs.try_emplace(resultBegin, nextValueID).second)
1815 if (resultGroups.size() != 1) {
1816 llvm::array_pod_sort(resultGroups.begin(), resultGroups.end());
1817 opResultGroups.try_emplace(&op, std::move(resultGroups));
1821void SSANameState::getResultIDAndNumber(
1822 OpResult
result, Value &lookupValue,
1823 std::optional<int> &lookupResultNo)
const {
1824 Operation *owner =
result.getOwner();
1827 int resultNo =
result.getResultNumber();
1831 auto resultGroupIt = opResultGroups.find(owner);
1832 if (resultGroupIt == opResultGroups.end()) {
1834 lookupResultNo = resultNo;
1840 ArrayRef<int> resultGroups = resultGroupIt->second;
1841 const auto *it = llvm::upper_bound(resultGroups, resultNo);
1842 int groupResultNo = 0, groupSize = 0;
1845 if (it == resultGroups.end()) {
1846 groupResultNo = resultGroups.back();
1847 groupSize =
static_cast<int>(owner->
getNumResults()) - resultGroups.back();
1850 groupResultNo = *std::prev(it);
1851 groupSize = *it - groupResultNo;
1856 lookupResultNo = resultNo - groupResultNo;
1857 lookupValue = owner->
getResult(groupResultNo);
1860void SSANameState::setValueName(Value value, StringRef name) {
1863 valueIDs[value] = nextValueID++;
1867 valueIDs[value] = NameSentinel;
1868 valueNames[value] = uniqueValueName(name);
1871StringRef SSANameState::uniqueValueName(StringRef name) {
1872 SmallString<16> tmpBuffer;
1876 if (!usedNames.count(name)) {
1877 name = name.copy(usedNameAllocator);
1882 SmallString<64> probeName(name);
1883 probeName.push_back(
'_');
1885 probeName += llvm::utostr(nextConflictID++);
1886 if (!usedNames.count(probeName)) {
1887 name = probeName.str().copy(usedNameAllocator);
1890 probeName.resize(name.size() + 1);
1894 usedNames.insert(name,
char());
1904class DistinctState {
1907 uint64_t getId(DistinctAttr distinctAttr);
1910 uint64_t distinctCounter = 0;
1915uint64_t DistinctState::getId(DistinctAttr distinctAttr) {
1917 distinctAttrMap.try_emplace(distinctAttr, distinctCounter);
1920 return it->getSecond();
1941 llvm_unreachable(
"unknown AsmResourceEntryKind");
1945 std::unique_ptr<ResourceCollection> &collection = keyToResources[key.str()];
1947 collection = std::make_unique<ResourceCollection>(key);
1951std::vector<std::unique_ptr<AsmResourcePrinter>>
1953 std::vector<std::unique_ptr<AsmResourcePrinter>> printers;
1954 for (
auto &it : keyToResources) {
1955 ResourceCollection *collection = it.second.get();
1957 return collection->buildResources(op, builder);
1959 printers.emplace_back(
1965LogicalResult FallbackAsmResourceMap::ResourceCollection::parseResource(
1969 FailureOr<AsmResourceBlob> blob = entry.
parseAsBlob();
1972 resources.emplace_back(entry.
getKey(), std::move(*blob));
1979 resources.emplace_back(entry.
getKey(), *value);
1982 case AsmResourceEntryKind::String: {
1986 resources.emplace_back(entry.
getKey(), std::move(*str));
1993void FallbackAsmResourceMap::ResourceCollection::buildResources(
1994 Operation *op, AsmResourceBuilder &builder)
const {
1995 for (
const auto &entry : resources) {
1996 if (
const auto *value = std::get_if<AsmResourceBlob>(&entry.value))
1998 else if (
const auto *value = std::get_if<bool>(&entry.value))
2000 else if (
const auto *value = std::get_if<std::string>(&entry.value))
2003 llvm_unreachable(
"unknown AsmResourceEntryKind");
2017 : interfaces(op->
getContext()), nameState(op, printerFlags),
2018 printerFlags(printerFlags), locationMap(locationMap) {}
2021 : interfaces(ctx), printerFlags(printerFlags), locationMap(locationMap) {}
2027 dialectResources.clear();
2028 aliasState.initialize(op, printerFlags, interfaces);
2048 return llvm::make_pointee_range(externalResourcePrinters);
2058 (*locationMap)[op] = std::make_pair(line, col);
2064 return dialectResources;
2068 return success(cyclicPrintingStack.insert(opaquePointer));
2084 AliasState aliasState;
2087 SSANameState nameState;
2090 DistinctState distinctState;
2106template <
typename Range>
2110 [&stream](
const auto &dimSize) {
2111 if (ShapedType::isDynamic(dimSize))
2129 return printerFlags;
2133 auto parentThreadId = llvm::get_threadid();
2135 if (parentThreadId == llvm::get_threadid()) {
2137 diag.print(llvm::dbgs());
2138 llvm::dbgs() <<
"\n";
2146 <<
"' failed to verify and will be printed in generic form";
2150 return printerFlags;
2169 return impl->getPrinterFlags();
2173 std::unique_ptr<AsmResourcePrinter> printer) {
2174 impl->externalResourcePrinters.emplace_back(std::move(printer));
2179 return impl->getDialectResources();
2201 if (!isTopLevel && succeeded(
state.getAliasState().getAlias(loc,
os)))
2205 .Case([&](OpaqueLoc loc) {
2208 .Case([&](UnknownLoc loc) {
2216 os << loc.getFilename().getValue();
2219 if (loc.getEndColumn() == loc.getStartColumn() &&
2220 loc.getStartLine() == loc.getEndLine()) {
2221 os <<
':' << loc.getStartLine() <<
':' << loc.getStartColumn();
2224 if (loc.getStartLine() == loc.getEndLine()) {
2225 os <<
':' << loc.getStartLine() <<
':' << loc.getStartColumn()
2226 <<
" to :" << loc.getEndColumn();
2229 os <<
':' << loc.getStartLine() <<
':' << loc.getStartColumn() <<
" to "
2230 << loc.getEndLine() <<
':' << loc.getEndColumn();
2232 .Case([&](NameLoc loc) {
2236 auto childLoc = loc.getChildLoc();
2237 if (!llvm::isa<UnknownLoc>(childLoc)) {
2243 .Case([&](CallSiteLoc loc) {
2250 if (llvm::isa<NameLoc>(callee)) {
2251 if (llvm::isa<FileLineColLoc>(caller)) {
2269 if (
Attribute metadata = loc.getMetadata()) {
2276 printLocationInternal(loc, pretty);
2290 bool *printedHex =
nullptr) {
2295 bool isInf = apValue.isInfinity();
2296 bool isNaN = apValue.isNaN();
2297 if (!isInf && !isNaN) {
2299 apValue.toString(strValue, 6, 0,
2305 assert(((strValue[0] >=
'0' && strValue[0] <=
'9') ||
2306 ((strValue[0] ==
'-' || strValue[0] ==
'+') &&
2307 (strValue[1] >=
'0' && strValue[1] <=
'9'))) &&
2308 "[-+]?[0-9] regex does not match!");
2312 if (APFloat(apValue.getSemantics(), strValue).bitwiseIsEqual(apValue)) {
2320 apValue.toString(strValue);
2323 if (strValue.str().contains(
'.')) {
2334 APInt apInt = apValue.bitcastToAPInt();
2335 apInt.toString(str, 16,
false,
2355 if (symName.empty() || !isalpha(symName.front()))
2360 symName = symName.drop_while(
2361 [](
char c) {
return llvm::isAlnum(c) || c ==
'.' || c ==
'_'; });
2362 if (symName.empty())
2367 return symName.front() ==
'<' && symName.back() ==
'>';
2372 StringRef dialectName, StringRef symString) {
2373 os << symPrefix << dialectName;
2378 os <<
'.' << symString;
2382 os <<
'<' << symString <<
'>';
2391 if (name.empty() || (!isalpha(name[0]) && name[0] !=
'_'))
2393 return llvm::all_of(name.drop_front(), [](
unsigned char c) {
2394 return isalnum(c) || c ==
'_' || c ==
'$' || c ==
'.';
2409 printEscapedString(keyword, os);
2417 if (symbolRef.empty()) {
2418 os <<
"@<<INVALID EMPTY SYMBOL>>";
2431 os << R
"(dense_resource<__elided__>)";
2436 auto *
interface = cast<OpAsmDialectInterface>(resource.getDialect());
2442 return state.getAliasState().getAlias(attr,
os);
2446 return state.getAliasState().getAlias(type,
os);
2452 os <<
"<<NULL ATTRIBUTE>>";
2463 if (!isa<BuiltinDialect>(attr.
getDialect())) {
2465 }
else if (
auto opaqueAttr = llvm::dyn_cast<OpaqueAttr>(attr)) {
2467 opaqueAttr.getAttrData());
2468 }
else if (llvm::isa<UnitAttr>(attr)) {
2471 }
else if (
auto distinctAttr = llvm::dyn_cast<DistinctAttr>(attr)) {
2472 os <<
"distinct[" <<
state.getDistinctState().getId(distinctAttr) <<
"]<";
2478 }
else if (
auto dictAttr = llvm::dyn_cast<DictionaryAttr>(attr)) {
2484 }
else if (
auto intAttr = llvm::dyn_cast<IntegerAttr>(attr)) {
2485 Type intType = intAttr.getType();
2487 os << (intAttr.getValue().getBoolValue() ?
"true" :
"false");
2498 intAttr.getValue().print(
os, !isUnsigned);
2504 }
else if (
auto floatAttr = llvm::dyn_cast<FloatAttr>(attr)) {
2505 bool printedHex =
false;
2513 }
else if (
auto strAttr = llvm::dyn_cast<StringAttr>(attr)) {
2516 }
else if (
auto arrayAttr = llvm::dyn_cast<ArrayAttr>(attr)) {
2519 printAttribute(attr, AttrTypeElision::May);
2523 }
else if (
auto affineMapAttr = llvm::dyn_cast<AffineMapAttr>(attr)) {
2524 os <<
"affine_map<";
2525 affineMapAttr.getValue().print(
os);
2531 }
else if (
auto integerSetAttr = llvm::dyn_cast<IntegerSetAttr>(attr)) {
2532 os <<
"affine_set<";
2533 integerSetAttr.getValue().print(
os);
2539 }
else if (
auto typeAttr = llvm::dyn_cast<TypeAttr>(attr)) {
2542 }
else if (
auto refAttr = llvm::dyn_cast<SymbolRefAttr>(attr)) {
2549 }
else if (
auto intOrFpEltAttr =
2550 llvm::dyn_cast<DenseTypedElementsAttr>(attr)) {
2551 if (
printerFlags.shouldElideElementsAttr(intOrFpEltAttr)) {
2558 Type eltType = intOrFpEltAttr.getElementType();
2559 if (isa<FloatType, IntegerType, IndexType, ComplexType>(eltType)) {
2563 cast<DenseElementType>(eltType));
2569 }
else if (
auto strEltAttr = llvm::dyn_cast<DenseStringElementsAttr>(attr)) {
2570 if (
printerFlags.shouldElideElementsAttr(strEltAttr)) {
2578 }
else if (
auto sparseEltAttr = llvm::dyn_cast<SparseElementsAttr>(attr)) {
2579 if (
printerFlags.shouldElideElementsAttr(sparseEltAttr.getIndices()) ||
2580 printerFlags.shouldElideElementsAttr(sparseEltAttr.getValues())) {
2585 if (
indices.getNumElements() != 0) {
2592 }
else if (
auto stridedLayoutAttr = llvm::dyn_cast<StridedLayoutAttr>(attr)) {
2593 stridedLayoutAttr.print(
os);
2594 }
else if (
auto denseArrayAttr = llvm::dyn_cast<DenseArrayAttr>(attr)) {
2596 printType(denseArrayAttr.getElementType());
2597 if (!denseArrayAttr.empty()) {
2603 }
else if (
auto resourceAttr =
2604 llvm::dyn_cast<DenseResourceElementsAttr>(attr)) {
2605 os <<
"dense_resource<";
2608 }
else if (
auto locAttr = llvm::dyn_cast<LocationAttr>(attr)) {
2611 llvm::report_fatal_error(
"Unknown builtin attribute");
2615 if (
auto typedAttr = llvm::dyn_cast<TypedAttr>(attr)) {
2616 Type attrType = typedAttr.getType();
2617 if (!llvm::isa<NoneType>(attrType)) {
2629 os << (value.getBoolValue() ?
"true" :
"false");
2639 return printEltFn(0);
2642 auto numElements = type.getNumElements();
2643 if (numElements == 0)
2651 int64_t rank = type.getRank();
2654 unsigned openBrackets = 0;
2656 auto shape = type.getShape();
2657 auto bumpCounter = [&] {
2659 ++counter[rank - 1];
2661 for (
unsigned i = rank - 1; i > 0; --i)
2662 if (counter[i] >=
shape[i]) {
2671 for (
unsigned idx = 0, e = numElements; idx != e; ++idx) {
2674 while (openBrackets++ < rank)
2676 openBrackets = rank;
2680 while (openBrackets-- > 0)
2686 if (
auto stringAttr = llvm::dyn_cast<DenseStringElementsAttr>(attr))
2695 auto type = attr.getType();
2696 auto elementType = type.getElementType();
2699 if (allowHex &&
printerFlags.shouldPrintElementsAttrWithHex(attr)) {
2701 if (llvm::endianness::native == llvm::endianness::big) {
2706 DenseTypedElementsAttr::convertEndianOfArrayRefForBEmachine(
2707 rawData, convRawData, type);
2716 if (ComplexType complexTy = llvm::dyn_cast<ComplexType>(elementType)) {
2717 Type complexElementType = complexTy.getElementType();
2721 if (llvm::isa<IntegerType>(complexElementType)) {
2724 auto complexValue = *(valueIt + index);
2726 printDenseIntElement(complexValue.real(), os, complexElementType);
2728 printDenseIntElement(complexValue.imag(), os, complexElementType);
2734 auto complexValue = *(valueIt + index);
2736 printFloatValue(complexValue.real(), os);
2738 printFloatValue(complexValue.imag(), os);
2742 }
else if (elementType.isIntOrIndex()) {
2743 auto valueIt = attr.value_begin<APInt>();
2745 printDenseIntElement(*(valueIt + index), os, elementType);
2748 assert(llvm::isa<FloatType>(elementType) &&
"unexpected element type");
2749 auto valueIt = attr.value_begin<APFloat>();
2751 printFloatValue(*(valueIt + index), os);
2757 DenseStringElementsAttr attr) {
2771 size_t bitSize = denseEltType.getDenseElementBitSize();
2772 size_t byteSize = llvm::divideCeil(bitSize,
static_cast<size_t>(CHAR_BIT));
2777 size_t offset = attr.isSplat() ? 0 : index * byteSize;
2778 ArrayRef<char> elemData = rawData.slice(offset, byteSize);
2779 Attribute elemAttr = denseEltType.convertToAttribute(elemData);
2780 printAttributeImpl(elemAttr);
2785 Type type = attr.getElementType();
2787 unsigned byteSize = bitwidth / 8;
2790 auto printElementAt = [&](
unsigned i) {
2791 APInt value(bitwidth, 0);
2793 llvm::LoadIntFromMemory(
2794 value,
reinterpret_cast<const uint8_t *
>(data.begin() + byteSize * i),
2805 llvm::interleaveComma(llvm::seq<unsigned>(0, attr.size()),
getStream(),
2811 os <<
"<<NULL TYPE>>";
2823 .Case([&](OpaqueType opaqueTy) {
2825 opaqueTy.getTypeData());
2827 .Case<IndexType>([&](
Type) {
os <<
"index"; })
2828 .Case<Float4E2M1FNType>([&](
Type) {
os <<
"f4E2M1FN"; })
2829 .Case<Float6E2M3FNType>([&](
Type) {
os <<
"f6E2M3FN"; })
2830 .Case<Float6E3M2FNType>([&](
Type) {
os <<
"f6E3M2FN"; })
2831 .Case<Float8E5M2Type>([&](
Type) {
os <<
"f8E5M2"; })
2832 .Case<Float8E4M3Type>([&](
Type) {
os <<
"f8E4M3"; })
2833 .Case<Float8E4M3FNType>([&](
Type) {
os <<
"f8E4M3FN"; })
2834 .Case<Float8E5M2FNUZType>([&](
Type) {
os <<
"f8E5M2FNUZ"; })
2835 .Case<Float8E4M3FNUZType>([&](
Type) {
os <<
"f8E4M3FNUZ"; })
2836 .Case<Float8E4M3B11FNUZType>([&](
Type) {
os <<
"f8E4M3B11FNUZ"; })
2837 .Case<Float8E3M4Type>([&](
Type) {
os <<
"f8E3M4"; })
2838 .Case<Float8E8M0FNUType>([&](
Type) {
os <<
"f8E8M0FNU"; })
2839 .Case<Float8E5M3FNUType>([&](
Type) {
os <<
"f8E5M3FNU"; })
2840 .Case<BFloat16Type>([&](
Type) {
os <<
"bf16"; })
2841 .Case<Float16Type>([&](
Type) {
os <<
"f16"; })
2842 .Case<FloatTF32Type>([&](
Type) {
os <<
"tf32"; })
2843 .Case<Float32Type>([&](
Type) {
os <<
"f32"; })
2844 .Case<Float64Type>([&](
Type) {
os <<
"f64"; })
2845 .Case<Float80Type>([&](
Type) {
os <<
"f80"; })
2846 .Case<Float128Type>([&](
Type) {
os <<
"f128"; })
2847 .Case([&](IntegerType integerTy) {
2848 if (integerTy.isSigned())
2850 else if (integerTy.isUnsigned())
2852 os <<
'i' << integerTy.getWidth();
2854 .Case([&](FunctionType funcTy) {
2859 if (results.size() == 1 && !llvm::isa<FunctionType>(results[0])) {
2867 .Case([&](VectorType vectorTy) {
2868 auto scalableDims = vectorTy.getScalableDims();
2870 auto vShape = vectorTy.getShape();
2871 unsigned lastDim = vShape.size();
2872 unsigned dimIdx = 0;
2873 for (dimIdx = 0; dimIdx < lastDim; dimIdx++) {
2874 if (!scalableDims.empty() && scalableDims[dimIdx])
2876 os << vShape[dimIdx];
2877 if (!scalableDims.empty() && scalableDims[dimIdx])
2884 .Case([&](RankedTensorType tensorTy) {
2887 if (!tensorTy.getShape().empty())
2891 if (tensorTy.getEncoding()) {
2897 .Case([&](UnrankedTensorType tensorTy) {
2902 .Case([&](MemRefType memrefTy) {
2905 if (!memrefTy.getShape().empty())
2908 MemRefLayoutAttrInterface layout = memrefTy.getLayout();
2909 if (!llvm::isa<AffineMapAttr>(layout) || !layout.isIdentity()) {
2914 if (memrefTy.getMemorySpace()) {
2924 if (memrefTy.getMemorySpace()) {
2930 .Case([&](ComplexType complexTy) {
2935 .Case([&](TupleType tupleTy) {
2938 [&](
Type type) { printType(type); });
2941 .Case<NoneType>([&](
Type) {
os <<
"none"; })
2942 .Case<TokenType>([&](
Type) {
os <<
"token"; })
2943 .Case([&](GraphType graphTy) {
2948 if (results.size() == 1 && !isa<FunctionType, GraphType>(results[0])) {
2967 auto printFilteredAttributesFn = [&](
auto filteredAttrs) {
2970 os <<
" attributes";
2980 if (elidedAttrs.empty())
2981 return printFilteredAttributesFn(attrs);
2984 llvm::SmallDenseSet<StringRef> elidedAttrsSet(elidedAttrs.begin(),
2986 auto filteredAttrs = llvm::make_filter_range(attrs, [&](
NamedAttribute attr) {
2987 return !elidedAttrsSet.contains(attr.
getName().strref());
2989 if (!filteredAttrs.empty())
2990 printFilteredAttributesFn(filteredAttrs);
2997 if (llvm::isa<UnitAttr>(attr.
getValue()))
3008 std::string attrName;
3010 llvm::raw_string_ostream attrNameStr(attrName);
3020 dialect.printAttribute(attr, printer);
3029 std::string typeName;
3031 llvm::raw_string_ostream typeNameStr(typeName);
3041 dialect.printType(type, printer);
3048 llvm::printEscapedString(str,
os);
3053 os <<
"\"0x" << llvm::toHex(str) <<
"\"";
3060 return state.pushCyclicPrinting(opaquePointer);
3076 assert(
impl &&
"expected AsmPrinter::getStream to be overriden");
3077 return impl->getStream();
3081 assert(
impl &&
"expected AsmPrinter::printNewLine to be overriden");
3082 impl->printNewline();
3086 assert(
impl &&
"expected AsmPrinter::increaseIndent to be overriden");
3087 impl->increaseIndent();
3091 assert(
impl &&
"expected AsmPrinter::decreaseIndent to be overriden");
3092 impl->decreaseIndent();
3097 assert(
impl &&
"expected AsmPrinter::printFloat to be overriden");
3102 assert(
impl &&
"expected AsmPrinter::printType to be overriden");
3103 impl->printType(type);
3107 assert(
impl &&
"expected AsmPrinter::printAttribute to be overriden");
3108 impl->printAttribute(attr);
3112 assert(
impl &&
"expected AsmPrinter::printAlias to be overriden");
3113 return impl->printAlias(attr);
3117 assert(
impl &&
"expected AsmPrinter::printAlias to be overriden");
3118 return impl->printAlias(type);
3123 "expected AsmPrinter::printAttributeWithoutType to be overriden");
3128 assert(
impl &&
"expected AsmPrinter::printNamedAttribute to be overriden");
3129 impl->printNamedAttribute(attr);
3133 assert(
impl &&
"expected AsmPrinter::printKeywordOrString to be overriden");
3138 assert(
impl &&
"expected AsmPrinter::printString to be overriden");
3140 printEscapedString(keyword,
getStream());
3145 assert(
impl &&
"expected AsmPrinter::printSymbolName to be overriden");
3150 assert(
impl &&
"expected AsmPrinter::printResourceHandle to be overriden");
3151 impl->printResourceHandle(resource);
3159 return impl->pushCyclicPrinting(opaquePointer);
3176 const char *binopSpelling =
nullptr;
3179 unsigned pos = cast<AffineSymbolExpr>(expr).getPosition();
3181 printValueName(pos,
true);
3187 unsigned pos = cast<AffineDimExpr>(expr).getPosition();
3189 printValueName(pos,
false);
3195 os << cast<AffineConstantExpr>(expr).getValue();
3198 binopSpelling =
" + ";
3201 binopSpelling =
" * ";
3204 binopSpelling =
" floordiv ";
3207 binopSpelling =
" ceildiv ";
3210 binopSpelling =
" mod ";
3214 auto binOp = cast<AffineBinaryOpExpr>(expr);
3224 auto rhsConst = dyn_cast<AffineConstantExpr>(rhsExpr);
3226 rhsConst.getValue() == -1) {
3236 os << binopSpelling;
3250 if (
auto rhs = dyn_cast<AffineBinaryOpExpr>(rhsExpr)) {
3253 if (
auto rrhs = dyn_cast<AffineConstantExpr>(rrhsExpr)) {
3254 if (rrhs.getValue() == -1) {
3271 if (rrhs.getValue() < -1) {
3279 os <<
" * " << -
static_cast<uint64_t
>(rrhs.getValue());
3289 if (
auto rhsConst = dyn_cast<AffineConstantExpr>(rhsExpr)) {
3290 if (rhsConst.getValue() < 0) {
3293 os <<
" - " << -
static_cast<uint64_t
>(rhsConst.getValue());
3311 isEq ?
os <<
" == 0" :
os <<
" >= 0";
3317 for (
int i = 0; i < (int)map.
getNumDims() - 1; ++i)
3318 os <<
'd' << i <<
", ";
3327 os <<
's' << i <<
", ";
3336 [&](
AffineExpr expr) { printAffineExpr(expr); });
3343 for (
unsigned i = 1; i < set.
getNumDims(); ++i)
3344 os <<
'd' << i - 1 <<
", ";
3353 os <<
's' << i <<
", ";
3362 for (
int i = 1; i < numConstraints; ++i) {
3366 if (numConstraints >= 1)
3368 set.
isEq(numConstraints - 1));
3387 void printTopLevelOperation(
Operation *op);
3391 void printFullOpWithIndentAndLoc(
Operation *op);
3397 void printCustomOrGenericOp(
Operation *op)
override;
3399 void printGenericOp(
Operation *op,
bool printOpName)
override;
3402 void printBlockName(
Block *block);
3407 void print(
Block *block,
bool printBlockArgs =
true,
3408 bool printBlockTerminator =
true);
3411 void printValueID(
Value value,
bool printResultNo =
true,
3424 void printOptionalLocationSpecifier(
Location loc)
override {
3425 printTrailingLocation(loc);
3435 bool omitType =
false)
override;
3438 void printOperand(Value value)
override { printValueID(value); }
3439 void printOperand(Value value, raw_ostream &os)
override {
3440 printValueID(value,
true, &os);
3444 void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
3445 ArrayRef<StringRef> elidedAttrs = {})
override {
3446 Impl::printOptionalAttrDict(attrs, elidedAttrs);
3448 void printOptionalAttrDictWithKeyword(
3449 ArrayRef<NamedAttribute> attrs,
3450 ArrayRef<StringRef> elidedAttrs = {})
override {
3451 Impl::printOptionalAttrDict(attrs, elidedAttrs,
3456 void printSuccessor(
Block *successor)
override;
3460 void printSuccessorAndUseList(
Block *successor,
3464 void printRegion(Region ®ion,
bool printEntryBlockArgs,
3465 bool printBlockTerminators,
bool printEmptyBlock)
override;
3471 void shadowRegionArgs(Region ®ion,
ValueRange namesToUse)
override {
3477 void printAffineMapOfSSAIds(AffineMapAttr mapAttr,
3482 void printAffineExprOfSSAIds(AffineExpr expr,
ValueRange dimOperands,
3486 void printUsersComment(Operation *op);
3489 void printUsersComment(BlockArgument arg);
3492 void printValueUsers(Value value);
3496 void printUserIDs(Operation *user,
bool prefixComma =
false);
3501 class ResourceBuilder :
public AsmResourceBuilder {
3507 using PrintFn =
function_ref<void(StringRef, ValueFn, int64_t sizeHint)>;
3509 ResourceBuilder(PrintFn printFn) : printFn(printFn) {}
3510 ~ResourceBuilder()
override =
default;
3512 void buildBool(StringRef key,
bool data)
final {
3514 key, [&](raw_ostream &os) { os << (data ?
"true" :
"false"); },
3518 void buildString(StringRef key, StringRef data)
final {
3521 [&](raw_ostream &os) {
3523 llvm::printEscapedString(data, os);
3529 void buildBlob(StringRef key, ArrayRef<char> data,
3530 uint32_t dataAlignment)
final {
3533 int64_t sizeHint = 2 * int64_t(
sizeof(dataAlignment) + data.size()) + 4;
3536 [&](raw_ostream &os) {
3539 llvm::support::ulittle32_t dataAlignmentLE(dataAlignment);
3542 StringRef(
reinterpret_cast<char *
>(&dataAlignmentLE),
3543 sizeof(dataAlignment)))
3544 << llvm::toHex(StringRef(data.data(), data.size())) <<
"\"";
3554 void printFileMetadataDictionary(Operation *op);
3560 void printResourceFileMetadata(
function_ref<
void()> checkAddMetadataDict,
3568 SmallVector<StringRef> defaultDialectStack{
"builtin"};
3572void OperationPrinter::printTopLevelOperation(Operation *op) {
3574 state.
getAliasState().printNonDeferredAliases(*
this, newLine);
3577 printFullOpWithIndentAndLoc(op);
3584 printFileMetadataDictionary(op);
3587void OperationPrinter::printFileMetadataDictionary(Operation *op) {
3588 bool sawMetadataEntry =
false;
3589 auto checkAddMetadataDict = [&] {
3590 if (!std::exchange(sawMetadataEntry,
true))
3591 os << newLine <<
"{-#" << newLine;
3595 printResourceFileMetadata(checkAddMetadataDict, op);
3598 if (sawMetadataEntry)
3599 os << newLine <<
"#-}" << newLine;
3602void OperationPrinter::printResourceFileMetadata(
3603 function_ref<
void()> checkAddMetadataDict, Operation *op) {
3605 bool hadResource =
false;
3606 bool needResourceComma =
false;
3607 bool needEntryComma =
false;
3608 auto processProvider = [&](StringRef dictName, StringRef name,
auto &provider,
3609 auto &&...providerArgs) {
3610 bool hadEntry =
false;
3611 auto printFn = [&](StringRef key, ResourceBuilder::ValueFn valueFn,
3613 checkAddMetadataDict();
3615 std::string resourceStr;
3616 auto printResourceStr = [&](raw_ostream &os) { os << resourceStr; };
3617 std::optional<uint64_t> charLimit =
3619 if (charLimit.has_value()) {
3621 if (charLimit.value() == 0)
3626 if (sizeHint >= 0 && uint64_t(sizeHint) > charLimit.value())
3629 llvm::raw_string_ostream ss(resourceStr);
3633 if (resourceStr.size() > charLimit.value())
3637 valueFn = printResourceStr;
3641 if (!std::exchange(hadResource,
true)) {
3642 if (needResourceComma)
3643 os <<
"," << newLine;
3644 os <<
" " << dictName <<
"_resources: {" << newLine;
3647 if (!std::exchange(hadEntry,
true)) {
3649 os <<
"," << newLine;
3650 os <<
" " << name <<
": {" << newLine;
3652 os <<
"," << newLine;
3660 ResourceBuilder entryBuilder(printFn);
3661 provider.buildResources(op, providerArgs..., entryBuilder);
3663 needEntryComma |= hadEntry;
3665 os << newLine <<
" }";
3672 StringRef name = interface.getDialect()->getNamespace();
3673 auto it = dialectResources.find(interface.getDialect());
3674 if (it != dialectResources.end())
3675 processProvider(
"dialect", name, interface, it->second);
3677 processProvider(
"dialect", name, interface,
3681 os << newLine <<
" }";
3685 needEntryComma =
false;
3686 needResourceComma = hadResource;
3687 hadResource =
false;
3689 processProvider(
"external", printer.getName(), printer);
3691 os << newLine <<
" }";
3699void OperationPrinter::printRegionArgument(BlockArgument arg,
3700 ArrayRef<NamedAttribute> argAttrs,
3707 printOptionalAttrDict(argAttrs);
3709 printTrailingLocation(arg.
getLoc(),
false);
3712void OperationPrinter::printFullOpWithIndentAndLoc(Operation *op) {
3716 os.indent(currentIndent);
3718 printTrailingLocation(op->
getLoc());
3720 printUsersComment(op);
3723void OperationPrinter::printFullOp(Operation *op) {
3725 auto printResultGroup = [&](
size_t resultNo,
size_t resultCount) {
3726 printValueID(op->
getResult(resultNo),
false);
3727 if (resultCount > 1)
3728 os <<
':' << resultCount;
3732 ArrayRef<int> resultGroups = state.
getSSANameState().getOpResultGroups(op);
3733 if (!resultGroups.empty()) {
3736 interleaveComma(llvm::seq<int>(0, resultGroups.size() - 1), [&](
int i) {
3737 printResultGroup(resultGroups[i],
3738 resultGroups[i + 1] - resultGroups[i]);
3741 printResultGroup(resultGroups.back(), numResults - resultGroups.back());
3744 printResultGroup(0, numResults);
3750 printCustomOrGenericOp(op);
3753void OperationPrinter::printUsersComment(Operation *op) {
3757 printOperationID(op);
3758 }
else if (numResults && op->
use_empty()) {
3760 }
else if (numResults && !op->
use_empty()) {
3763 unsigned usedInNResults = 0;
3764 unsigned usedInNOperations = 0;
3765 SmallPtrSet<Operation *, 1> userSet;
3766 for (Operation *user : op->
getUsers()) {
3767 if (userSet.insert(user).second) {
3768 ++usedInNOperations;
3769 usedInNResults += user->getNumResults();
3774 bool exactlyOneUniqueUse =
3775 usedInNResults <= 1 && usedInNOperations <= 1 && numResults == 1;
3776 os <<
" // " << (exactlyOneUniqueUse ?
"user" :
"users") <<
": ";
3777 bool shouldPrintBrackets = numResults > 1;
3778 auto printOpResult = [&](OpResult opResult) {
3779 if (shouldPrintBrackets)
3781 printValueUsers(opResult);
3782 if (shouldPrintBrackets)
3786 interleaveComma(op->
getResults(), printOpResult);
3790void OperationPrinter::printUsersComment(BlockArgument arg) {
3796 os <<
" is used by ";
3797 printValueUsers(arg);
3802void OperationPrinter::printValueUsers(Value value) {
3808 SmallPtrSet<Operation *, 1> userSet;
3810 if (userSet.insert(user).second)
3811 printUserIDs(user, index);
3815void OperationPrinter::printUserIDs(Operation *user,
bool prefixComma) {
3820 printOperationID(user);
3823 [
this](Value
result) { printValueID(result); });
3827void OperationPrinter::printCustomOrGenericOp(Operation *op) {
3833 opInfo->printAssembly(op, *
this, defaultDialectStack.back());
3838 if (
auto opPrinter = dialect->getOperationPrinter(op)) {
3843 if (name.count(
'.') == 1)
3844 name.consume_front((defaultDialectStack.back() +
".").str());
3848 opPrinter(op, *
this);
3855 printGenericOp(op,
true);
3858void OperationPrinter::printGenericOp(Operation *op,
bool printOpName) {
3862 interleaveComma(op->
getOperands(), [&](Value value) { printValueID(value); });
3869 [&](
Block *successor) { printBlockName(successor); });
3883 interleaveComma(op->
getRegions(), [&](Region ®ion) {
3884 printRegion(region, true,
3897void OperationPrinter::printBlockName(
Block *block) {
3901void OperationPrinter::print(
Block *block,
bool printBlockArgs,
3902 bool printBlockTerminator) {
3904 if (printBlockArgs) {
3905 os.indent(currentIndent);
3906 printBlockName(block);
3911 interleaveComma(block->
getArguments(), [&](BlockArgument arg) {
3914 printType(arg.getType());
3916 printTrailingLocation(arg.getLoc(), false);
3924 os <<
" // block is not in a region!";
3927 os <<
" // no predecessors";
3930 printBlockName(pred);
3934 SmallVector<BlockInfo, 4> predIDs;
3937 llvm::sort(predIDs, [](BlockInfo
lhs, BlockInfo
rhs) {
3938 return lhs.ordering <
rhs.ordering;
3941 os <<
" // " << predIDs.size() <<
" preds: ";
3943 interleaveComma(predIDs, [&](BlockInfo pred) { os << pred.name; });
3948 currentIndent += indentWidth;
3952 os.indent(currentIndent);
3953 printUsersComment(arg);
3957 bool hasTerminator =
3959 auto range = llvm::make_range(
3961 std::prev(block->
end(),
3962 (!hasTerminator || printBlockTerminator) ? 0 : 1));
3963 for (
auto &op : range) {
3964 printFullOpWithIndentAndLoc(&op);
3967 currentIndent -= indentWidth;
3970void OperationPrinter::printValueID(Value value,
bool printResultNo,
3971 raw_ostream *streamOverride)
const {
3973 streamOverride ? *streamOverride : os);
3976void OperationPrinter::printOperationID(Operation *op,
3977 raw_ostream *streamOverride)
const {
3978 state.
getSSANameState().printOperationID(op, streamOverride ? *streamOverride
3982void OperationPrinter::printSuccessor(
Block *successor) {
3983 printBlockName(successor);
3986void OperationPrinter::printSuccessorAndUseList(
Block *successor,
3988 printBlockName(successor);
3989 if (succOperands.empty())
3993 interleaveComma(succOperands,
3994 [
this](Value operand) { printValueID(operand); });
3996 interleaveComma(succOperands,
4001void OperationPrinter::printRegion(Region ®ion,
bool printEntryBlockArgs,
4002 bool printBlockTerminators,
4003 bool printEmptyBlock) {
4008 os <<
"{" << newLine;
4009 if (!region.
empty()) {
4010 llvm::scope_exit restoreDefaultDialect(
4011 [&]() { defaultDialectStack.pop_back(); });
4012 if (
auto iface = dyn_cast<OpAsmOpInterface>(region.
getParentOp()))
4013 defaultDialectStack.push_back(iface.getDefaultDialect());
4015 defaultDialectStack.push_back(
"");
4017 auto *entryBlock = ®ion.
front();
4021 bool shouldAlwaysPrintBlockHeader =
4022 (printEmptyBlock && entryBlock->empty()) ||
4023 (printEntryBlockArgs && entryBlock->getNumArguments() != 0);
4024 print(entryBlock, shouldAlwaysPrintBlockHeader, printBlockTerminators);
4025 for (
auto &
b : llvm::drop_begin(region.
getBlocks(), 1))
4028 os.indent(currentIndent) <<
"}";
4031void OperationPrinter::printAffineMapOfSSAIds(AffineMapAttr mapAttr,
4034 os <<
"<<NULL AFFINE MAP>>";
4037 AffineMap map = mapAttr.getValue();
4039 auto printValueName = [&](
unsigned pos,
bool isSymbol) {
4040 unsigned index = isSymbol ? numDims + pos : pos;
4041 assert(index < operands.size());
4044 printValueID(operands[index]);
4049 interleaveComma(map.
getResults(), [&](AffineExpr expr) {
4050 printAffineExpr(expr, printValueName);
4054void OperationPrinter::printAffineExprOfSSAIds(AffineExpr expr,
4057 auto printValueName = [&](
unsigned pos,
bool isSymbol) {
4059 return printValueID(dimOperands[pos]);
4061 printValueID(symOperands[pos]);
4064 printAffineExpr(expr, printValueName);
4073 os <<
"<<NULL ATTRIBUTE>>";
4078 print(os, state, elideType);
4084 : AttrTypeElision::Never);
4088 print(llvm::errs());
4089 llvm::errs() <<
"\n";
4094 os <<
"<<NULL ATTRIBUTE>>";
4103 uint64_t posPrior = os.tell();
4105 dialect.printAttribute(*
this, printer);
4106 if (posPrior != os.tell())
4115 os <<
"<<NULL ATTRIBUTE>>";
4125 os <<
"<<NULL TYPE>>";
4137 print(llvm::errs());
4138 llvm::errs() <<
"\n";
4142 print(llvm::errs());
4143 llvm::errs() <<
"\n";
4147 print(llvm::errs());
4148 llvm::errs() <<
"\n";
4153 os <<
"<<NULL AFFINE EXPR>>";
4161 print(llvm::errs());
4162 llvm::errs() <<
"\n";
4167 os <<
"<<NULL AFFINE MAP>>";
4182 os <<
"<<NULL VALUE>>";
4187 return op->
print(os, flags);
4190 os <<
"<block argument> of type '" << arg.
getType()
4195 os <<
"<<NULL VALUE>>";
4200 return op->
print(os, state);
4204 os <<
"<block argument> of type '" << arg.
getType()
4215 llvm::errs() <<
"\n";
4246 if (
auto result = llvm::dyn_cast<OpResult>(*
this)) {
4249 op = llvm::cast<BlockArgument>(*this).getOwner()->
getParentOp();
4251 os <<
"<<UNKNOWN SSA VALUE>>";
4267 OperationPrinter printer(os, state.
getImpl());
4275 printer.printTopLevelOperation(
this);
4277 printer.printFullOpWithIndentAndLoc(
this);
4283 llvm::errs() <<
"\n";
4288 llvm::errs() <<
"\n";
4294 os <<
"<<UNLINKED BLOCK>>\n";
4305 OperationPrinter(os, state.
getImpl()).print(
this);
4314 os <<
"<<UNLINKED BLOCK>>\n";
4321 OperationPrinter printer(os, state.
getImpl());
4322 printer.printBlockName(
this);
4337 if (dimensions.empty())
4340 if (dimensions.empty())
4350 <<
"Failed parsing dimension list.";
4361 <<
"Failed parsing dimension list.";
4363 if (shapeArr.empty()) {
4365 <<
"Failed parsing dimension list. Did you mean an empty list? It "
4366 "must be denoted by \"[]\".";
if(failed(verifyVectorMemoryOp(getOperation(), memrefType, getVectorType()))) return failure()
static void printSymbolReference(StringRef symbolRef, raw_ostream &os)
Print the given string as a symbol reference.
static void printFloatValue(const APFloat &apValue, raw_ostream &os, bool *printedHex=nullptr)
Print a floating point value in a way that the parser will be able to round-trip losslessly.
static StringRef sanitizeIdentifier(StringRef name, SmallString< 16 > &buffer, StringRef allowedPunctChars="$._-")
Sanitize the given name such that it can be used as a valid identifier.
static void printElidedElementsAttr(raw_ostream &os)
static bool isBareIdentifier(StringRef name)
Returns true if the given string can be represented as a bare identifier.
static void printDenseElementsAttrImpl(bool isSplat, ShapedType type, raw_ostream &os, function_ref< void(unsigned)> printEltFn)
static void printKeywordOrString(StringRef keyword, raw_ostream &os)
Print the given string as a keyword, or a quoted and escaped string if it has any special or non-prin...
static bool isDialectSymbolSimpleEnoughForPrettyForm(StringRef symName)
Returns true if the given dialect symbol data is simple enough to print in the pretty form.
static void printDialectSymbol(raw_ostream &os, StringRef symPrefix, StringRef dialectName, StringRef symString)
Print the given dialect symbol to the stream.
static OpPrintingFlags verifyOpAndAdjustFlags(Operation *op, OpPrintingFlags printerFlags)
Verifies the operation and switches to generic op printing if verification fails.
static void printDenseIntElement(const APInt &value, raw_ostream &os, Type type)
Print the integer element of a DenseElementsAttr.
MLIR_CRUNNERUTILS_EXPORT void printString(char const *s)
MLIR_CRUNNERUTILS_EXPORT void printNewline()
static llvm::ManagedStatic< DebugCounterOptions > clOptions
static void visit(Operation *op, DenseSet< Operation * > &visited)
Visits all the pdl.operand(s), pdl.result(s), and pdl.operation(s) connected to the given operation.
LogicalResult initialize(unsigned origNumLoops, ArrayRef< ReassociationIndices > foldedIterationDims)
static Operation * findParent(Operation *op, bool shouldUseLocalScope)
*if copies could not be generated due to yet unimplemented cases *copyInPlacementStart and copyOutPlacementStart in copyPlacementBlock *specify the insertion points where the incoming copies and outgoing should be inserted(the insertion happens right before the *insertion point). Since `begin` can itself be invalidated due to the memref *rewriting done from this method
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)
static const llvm::fltSemantics * getFloatSemantics(TruncfSrcElemTypes etype)
Float semantics the element type attributes of xevm.truncf and xevm.extf stand for.
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 printOperands(OperandRange operands)
Print a comma separated range of operation operands out of line to avoid instantiating the range iter...
void printOperandTypes(ValueTypeRange< OperandRange > types)
Print the types of a comma separated range of operation operands.
void printFunctionalType(Operation *op)
Print the complete type of an operation in functional form.
virtual void printOperand(Value value)=0
Print implementations for various things an operation contains.
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 & alwaysUseAliases(bool enable=true)
Always use aliases even for non top-level ops.
bool shouldAlwaysUseAliases() const
Return if aliases should always be used.
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.
This class implements the operand iterators for the Operation class.
StringRef getStringRef() const
Return the name of this operation. This always succeeds.
void walkInherentAttrs(Operation *op, InherentAttrVisitor visitor) const
Visit the inherent attributes stored in the properties of op.
void printAssembly(Operation *op, OpAsmPrinter &p, StringRef defaultDialect) const
This hook implements the AsmPrinter for this operation.
void print(raw_ostream &os) const
Operation is the basic unit of execution within MLIR.
Dialect * getDialect()
Return the dialect this operation is associated with, or nullptr if the associated dialect is not loa...
bool use_empty()
Returns true if this operation has no uses.
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
unsigned getNumSuccessors()
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
unsigned getNumRegions()
Returns the number of regions held by this operation.
Location getLoc()
The source location the operation was defined or derived from.
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
std::optional< RegisteredOperationName > getRegisteredInfo()
If this operation has a registered operation description, return it.
DictionaryAttr getRawDictionaryAttrs()
Return all attributes that are not stored as properties.
unsigned getNumOperands()
Attribute getPropertiesAsAttribute()
Return the properties converted to an attribute.
OperationName getName()
The name of an operation is the key identifier for it.
void print(raw_ostream &os, const OpPrintingFlags &flags={})
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
result_type_range getResultTypes()
LLVM_DUMP_METHOD void dumpPretty()
operand_range getOperands()
Returns an iterator on the underlying Value's.
user_range getUsers()
Returns a range of all users.
SuccessorRange getSuccessors()
result_range getResults()
MLIRContext * getContext()
Return the context this operation is associated with.
unsigned getNumResults()
Return the number of results held by this operation.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
BlockArgListType getArguments()
iterator_range< OpIterator > getOps()
unsigned getNumArguments()
BlockArgument getArgument(unsigned i)
Operation * getParentOp()
Return the parent operation this region is attached to.
BlockListType & getBlocks()
This diagnostic handler is a simple RAII class that registers and erases a diagnostic handler on a gi...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
void print(raw_ostream &os) const
Print the current type.
Dialect & getDialect() const
Get the dialect this type is registered to.
bool isSignlessInteger() const
Return true if this is a signless integer type (with the specified width).
static Type getFromOpaquePointer(const void *pointer)
const void * getAsOpaquePointer() const
Methods for supporting PointerLikeTypeTraits.
void walkImmediateSubElements(function_ref< void(Attribute)> walkAttrsFn, function_ref< void(Type)> walkTypesFn) const
Walk all of the immediately nested sub-attributes and sub-types.
bool isUnsignedInteger() const
Return true if this is an unsigned integer type (with the specified width).
bool isIntOrIndex() const
Return true if this is an integer (of any signedness) or an index type.
bool isInteger() const
Return true if this is an integer type (with the specified width).
unsigned getIntOrFloatBitWidth() const
Return the bit width of an integer or a float type, assert failure on other types.
This class implements iteration on the types of a given range of values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
bool use_empty() const
Returns true if this value has no uses.
void print(raw_ostream &os) const
Type getType() const
Return the type of this value.
void printAsOperand(raw_ostream &os, AsmState &state) const
Print this value as if it were an operand.
user_range getUsers() const
Location getLoc() const
Return the location of this value.
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
SSANameState & getSSANameState()
Get the state used for SSA names.
void registerOperationLocation(Operation *op, unsigned line, unsigned col)
Register the location, line and column, within the buffer that the given operation was printed at.
auto getResourcePrinters()
Return the non-dialect resource printers.
LogicalResult pushCyclicPrinting(const void *opaquePointer)
AliasState & getAliasState()
Get the state used for aliases.
void initializeAliases(Operation *op)
Initialize the alias state to enable the printing of aliases.
const OpPrintingFlags & getPrinterFlags() const
Get the printer flags.
DenseMap< Dialect *, SetVector< AsmDialectResourceHandle > > & getDialectResources()
Return the referenced dialect resources within the printer.
AsmStateImpl(Operation *op, const OpPrintingFlags &printerFlags, AsmState::LocationMap *locationMap)
AsmStateImpl(MLIRContext *ctx, const OpPrintingFlags &printerFlags, AsmState::LocationMap *locationMap)
DistinctState & getDistinctState()
Get the state used for distinct attribute identifiers.
DialectInterfaceCollection< OpAsmDialectInterface > & getDialectInterfaces()
Return the dialects within the context that implement OpAsmDialectInterface.
static DenseArrayAttrImpl get(MLIRContext *context, ArrayRef< int64_t > content)
detail::StorageUserTrait::IsMutable< ConcreteType > IsMutable
This trait is used to determine if an attribute is mutable or not.
void printType(Type type, AsmPrinter &printer)
Prints an LLVM Dialect type.
static void printDimensionList(raw_ostream &stream, Range &&shape)
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
bool operator<(const Fraction &x, const Fraction &y)
Include the generated interface declarations.
detail::DenseArrayAttrImpl< int64_t > DenseI64ArrayAttr
ParseResult parseDimensionList(OpAsmParser &parser, DenseI64ArrayAttr &dimensions)
StringRef toString(AsmResourceEntryKind kind)
raw_ostream & operator<<(raw_ostream &os, const AliasResult &result)
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
void printDimensionList(OpAsmPrinter &printer, Operation *op, ArrayRef< int64_t > dimensions)
@ CeilDiv
RHS of ceildiv is always a constant or a symbolic expression.
@ Mul
RHS of mul is always a constant or a symbolic expression.
@ Mod
RHS of mod is always a constant or a symbolic expression with a positive value.
@ DimId
Dimensional identifier.
@ FloorDiv
RHS of floordiv is always a constant or a symbolic expression.
@ Constant
Constant integer.
@ SymbolId
Symbolic identifier.
llvm::SetVector< T, Vector, Set, N > SetVector
std::conditional_t< std::is_floating_point_v< T >, std::complex< T >, NonFloatComplex< T > > Complex
void registerAsmPrinterCLOptions()
Register a set of useful command-line options that can be used to configure various flags within the ...
llvm::TypeSwitch< T, ResultT > TypeSwitch
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
AsmResourceEntryKind
This enum represents the different kinds of resource values.
@ Blob
A blob of data with an accompanying alignment.
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
llvm::function_ref< Fn > function_ref
Represents a range (offset, size, and stride) where each element of the triple may be dynamic or stat...