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"
62#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
97 llvm::interleaveComma(operands,
getStream(),
102 llvm::interleaveComma(types, *
this);
110 *this << (operand ? operand.getType() : Type());
126 *this << (result ? result.getType() : Type());
138#include "mlir/IR/OpAsmAttrInterface.cpp.inc"
139#include "mlir/IR/OpAsmOpInterface.cpp.inc"
140#include "mlir/IR/OpAsmTypeInterface.cpp.inc"
144 return entry.
emitError() <<
"unknown 'resource' key '" << entry.
getKey()
145 <<
"' for dialect '" << getDialect()->getNamespace()
157struct AsmPrinterOptions {
158 llvm::cl::opt<int64_t> printElementsAttrWithHexIfLarger{
159 "mlir-print-elementsattrs-with-hex-if-larger",
161 "Print DenseElementsAttrs with a hex string that have "
162 "more elements than the given upper limit (use -1 to disable)")};
164 llvm::cl::opt<unsigned> elideElementsAttrIfLarger{
165 "mlir-elide-elementsattrs-if-larger",
166 llvm::cl::desc(
"Elide ElementsAttrs with \"...\" that have "
167 "more elements than the given upper limit")};
169 llvm::cl::opt<unsigned> elideResourceStringsIfLarger{
170 "mlir-elide-resource-strings-if-larger",
172 "Elide printing value of resources if string is too long in chars.")};
174 llvm::cl::opt<bool> printDebugInfoOpt{
175 "mlir-print-debuginfo", llvm::cl::init(
false),
176 llvm::cl::desc(
"Print debug info in MLIR output")};
178 llvm::cl::opt<bool> printPrettyDebugInfoOpt{
179 "mlir-pretty-debuginfo", llvm::cl::init(
false),
180 llvm::cl::desc(
"Print pretty debug info in MLIR output")};
184 llvm::cl::opt<bool> printGenericOpFormOpt{
185 "mlir-print-op-generic", llvm::cl::init(
false),
186 llvm::cl::desc(
"Print the generic op form"), llvm::cl::Hidden};
188 llvm::cl::opt<bool> assumeVerifiedOpt{
189 "mlir-print-assume-verified", llvm::cl::init(
false),
190 llvm::cl::desc(
"Skip op verification when using custom printers"),
193 llvm::cl::opt<bool> printLocalScopeOpt{
194 "mlir-print-local-scope", llvm::cl::init(
false),
195 llvm::cl::desc(
"Print with local scope and inline information (eliding "
196 "aliases for attributes, types, and locations)")};
198 llvm::cl::opt<bool> skipRegionsOpt{
199 "mlir-print-skip-regions", llvm::cl::init(
false),
200 llvm::cl::desc(
"Skip regions when printing ops.")};
202 llvm::cl::opt<bool> printValueUsers{
203 "mlir-print-value-users", llvm::cl::init(
false),
205 "Print users of operation results and block arguments as a comment")};
207 llvm::cl::opt<bool> printUniqueSSAIDs{
208 "mlir-print-unique-ssa-ids", llvm::cl::init(
false),
209 llvm::cl::desc(
"Print unique SSA ID numbers for values, block arguments "
210 "and naming conflicts across all regions")};
212 llvm::cl::opt<bool> useNameLocAsPrefix{
213 "mlir-use-nameloc-as-prefix", llvm::cl::init(
false),
214 llvm::cl::desc(
"Print SSA IDs using NameLocs as prefixes")};
216 llvm::cl::opt<bool> alwaysUseAliasesOpt{
217 "mlir-print-always-use-aliases", llvm::cl::init(
false),
218 llvm::cl::desc(
"Always use aliases even for non top-level ops")};
233 : printDebugInfoFlag(
false), printDebugInfoPrettyFormFlag(
false),
234 printGenericOpFormFlag(
false), skipRegionsFlag(
false),
235 assumeVerifiedFlag(
false), alwaysUseAliasesFlag(
false),
236 printLocalScope(
false), printValueUsersFlag(
false),
237 printUniqueSSAIDsFlag(
false), useNameLocAsPrefix(
false) {
241 if (
clOptions->elideElementsAttrIfLarger.getNumOccurrences())
242 elementsAttrElementLimit =
clOptions->elideElementsAttrIfLarger;
243 if (
clOptions->printElementsAttrWithHexIfLarger.getNumOccurrences())
244 elementsAttrHexElementLimit =
245 clOptions->printElementsAttrWithHexIfLarger.getValue();
246 if (
clOptions->elideResourceStringsIfLarger.getNumOccurrences())
247 resourceStringCharLimit =
clOptions->elideResourceStringsIfLarger;
248 printDebugInfoFlag =
clOptions->printDebugInfoOpt;
249 printDebugInfoPrettyFormFlag =
clOptions->printPrettyDebugInfoOpt;
250 printGenericOpFormFlag =
clOptions->printGenericOpFormOpt;
251 assumeVerifiedFlag =
clOptions->assumeVerifiedOpt;
252 printLocalScope =
clOptions->printLocalScopeOpt;
253 skipRegionsFlag =
clOptions->skipRegionsOpt;
254 printValueUsersFlag =
clOptions->printValueUsers;
255 printUniqueSSAIDsFlag =
clOptions->printUniqueSSAIDs;
256 useNameLocAsPrefix =
clOptions->useNameLocAsPrefix;
257 alwaysUseAliasesFlag =
clOptions->alwaysUseAliasesOpt;
266 elementsAttrElementLimit = largeElementLimit;
272 elementsAttrHexElementLimit = largeElementLimit;
278 resourceStringCharLimit = largeResourceLimit;
286 printDebugInfoFlag = enable;
287 printDebugInfoPrettyFormFlag = prettyForm;
293 printGenericOpFormFlag = enable;
299 skipRegionsFlag = skip;
305 assumeVerifiedFlag = enable;
310 alwaysUseAliasesFlag = enable;
318 printLocalScope = enable;
324 printValueUsersFlag = enable;
331 printUniqueSSAIDsFlag = enable;
337 return elementsAttrElementLimit &&
338 *elementsAttrElementLimit <
int64_t(attr.getNumElements()) &&
339 !llvm::isa<SplatElementsAttr>(attr);
345 return (elementsAttrHexElementLimit != -1) &&
346 (elementsAttrHexElementLimit <
int64_t(attr.getNumElements())) &&
347 !llvm::isa<SplatElementsAttr>(attr);
351 useNameLocAsPrefix = enable;
357 return elementsAttrElementLimit;
362 return elementsAttrHexElementLimit;
367 return resourceStringCharLimit;
372 return printDebugInfoFlag;
377 return printDebugInfoPrettyFormFlag;
382 return printGenericOpFormFlag;
390 return assumeVerifiedFlag;
394 return alwaysUseAliasesFlag;
402 return printValueUsersFlag;
412 return useNameLocAsPrefix;
423struct NewLineCounter {
424 unsigned curLine = 1;
461 template <
typename Container,
typename UnaryFunctor>
463 llvm::interleaveComma(c,
os, eachFn);
510 function_ref<
void(
unsigned,
bool)> printValueName =
nullptr);
523 bool withKeyword =
false);
526 bool isTopLevel =
false);
544 DenseElementType denseEltType);
568 function_ref<
void(
unsigned,
bool)> printValueName =
nullptr);
598 SymbolAlias(StringRef name, uint32_t suffixIndex,
bool isType,
600 : name(name), suffixIndex(suffixIndex), isType(isType),
601 isDeferrable(isDeferrable) {}
605 os << (isType ?
"!" :
"#") << name;
607 if (isdigit(name.back()))
614 bool isTypeAlias()
const {
return isType; }
617 bool canBeDeferred()
const {
return isDeferrable; }
623 uint32_t suffixIndex : 30;
627 bool isDeferrable : 1;
631 bool isPrinted =
false;
637class AliasInitializer {
640 DialectInterfaceCollection<OpAsmDialectInterface> &interfaces,
641 llvm::BumpPtrAllocator &aliasAllocator)
642 : interfaces(interfaces), aliasAllocator(aliasAllocator),
643 aliasOS(aliasBuffer) {}
645 void initialize(Operation *op,
const OpPrintingFlags &printerFlags,
646 llvm::MapVector<const void *, SymbolAlias> &attrTypeToAlias);
654 std::pair<size_t, size_t>
visit(Attribute attr,
bool canBeDeferred =
false,
655 bool elideType =
false) {
656 return visitImpl(attr, aliases, canBeDeferred, elideType);
663 std::pair<size_t, size_t>
visit(Type type,
bool canBeDeferred =
false) {
664 return visitImpl(type, aliases, canBeDeferred);
668 struct InProgressAliasInfo {
669 InProgressAliasInfo()
670 : aliasDepth(0), isType(
false), canBeDeferred(
false) {}
671 InProgressAliasInfo(StringRef alias)
672 : alias(alias), aliasDepth(1), isType(
false), canBeDeferred(
false) {}
676 if (aliasDepth !=
rhs.aliasDepth)
677 return aliasDepth <
rhs.aliasDepth;
678 if (isType !=
rhs.isType)
680 return alias <
rhs.alias;
685 std::optional<StringRef> alias;
688 unsigned aliasDepth : 30;
692 bool canBeDeferred : 1;
694 SmallVector<size_t> childIndices;
702 template <
typename T,
typename... PrintArgs>
703 std::pair<size_t, size_t>
705 llvm::MapVector<const void *, InProgressAliasInfo> &aliases,
706 bool canBeDeferred, PrintArgs &&...
printArgs);
709 void markAliasNonDeferrable(
size_t aliasIndex);
713 template <
typename T>
714 void generateAlias(T symbol, InProgressAliasInfo &alias,
bool canBeDeferred);
719 uniqueAliasNameIndex(StringRef alias, llvm::StringMap<unsigned> &nameCounts,
720 llvm::StringSet<llvm::BumpPtrAllocator &> &usedAliases);
724 static void initializeAliases(
725 llvm::MapVector<const void *, InProgressAliasInfo> &visitedSymbols,
726 llvm::MapVector<const void *, SymbolAlias> &symbolToAlias);
729 DialectInterfaceCollection<OpAsmDialectInterface> &interfaces;
732 llvm::BumpPtrAllocator &aliasAllocator;
735 llvm::MapVector<const void *, InProgressAliasInfo> aliases;
738 SmallString<32> aliasBuffer;
739 llvm::raw_svector_ostream aliasOS;
747class DummyAliasOperationPrinter :
private OpAsmPrinter {
749 explicit DummyAliasOperationPrinter(
const OpPrintingFlags &printerFlags,
750 AliasInitializer &initializer)
751 : printerFlags(printerFlags), initializer(initializer) {}
755 void printCustomOrGenericOp(Operation *op)
override {
757 if (printerFlags.shouldPrintDebugInfo())
758 initializer.visit(op->
getLoc(),
true);
761 if (!printerFlags.shouldPrintGenericOpForm()) {
772 void printGenericOp(Operation *op,
bool printOpName =
true)
override {
774 if (!printerFlags.shouldSkipRegions()) {
784 if (operand && operand.getType())
791 printAttribute(attr.getValue());
793 op, [&](StringRef, Attribute &attr) { printAttribute(attr); });
799 void print(
Block *block,
bool printBlockArgs =
true,
800 bool printBlockTerminator =
true) {
803 if (printBlockArgs) {
808 if (printerFlags.shouldPrintDebugInfo())
810 initializer.visit(arg.getLoc(),
false);
818 auto range = llvm::make_range(
820 std::prev(block->
end(),
821 (!hasTerminator || printBlockTerminator) ? 0 : 1));
822 for (Operation &op : range)
823 printCustomOrGenericOp(&op);
827 void printRegion(Region ®ion,
bool printEntryBlockArgs,
828 bool printBlockTerminators,
829 bool printEmptyBlock =
false)
override {
832 if (printerFlags.shouldSkipRegions()) {
837 auto *entryBlock = ®ion.
front();
838 print(entryBlock, printEntryBlockArgs, printBlockTerminators);
839 for (
Block &
b : llvm::drop_begin(region, 1))
843 void printRegionArgument(BlockArgument arg, ArrayRef<NamedAttribute> argAttrs,
844 bool omitType)
override {
847 if (printerFlags.shouldPrintDebugInfo())
849 initializer.visit(arg.
getLoc(),
false);
855 initializer.visit(type);
859 void printAttribute(Attribute attr)
override { initializer.visit(attr); }
860 void printAttributeWithoutType(Attribute attr)
override {
861 printAttribute(attr);
863 void printNamedAttribute(NamedAttribute attr)
override {
867 LogicalResult printAlias(Attribute attr)
override {
868 initializer.visit(attr);
871 LogicalResult printAlias(Type type)
override {
872 initializer.visit(type);
877 void printOptionalLocationSpecifier(Location loc)
override {
883 void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
884 ArrayRef<StringRef> elidedAttrs = {})
override {
887 if (elidedAttrs.empty()) {
888 for (
const NamedAttribute &attr : attrs)
889 printAttribute(attr.getValue());
892 llvm::SmallDenseSet<StringRef> elidedAttrsSet(elidedAttrs.begin(),
894 for (
const NamedAttribute &attr : attrs)
895 if (!elidedAttrsSet.contains(attr.getName().strref()))
896 printAttribute(attr.getValue());
898 void printOptionalAttrDictWithKeyword(
899 ArrayRef<NamedAttribute> attrs,
900 ArrayRef<StringRef> elidedAttrs = {})
override {
901 printOptionalAttrDict(attrs, elidedAttrs);
906 raw_ostream &getStream()
const override {
return os; }
910 void printFloat(
const APFloat &)
override {}
911 void printAffineMapOfSSAIds(AffineMapAttr,
ValueRange)
override {}
914 void increaseIndent()
override {}
915 void decreaseIndent()
override {}
916 void printOperand(Value)
override {}
917 void printOperand(Value, raw_ostream &os)
override {
925 void printResourceHandle(
const AsmDialectResourceHandle &)
override {}
926 void printSymbolName(StringRef)
override {}
927 void printSuccessor(
Block *)
override {}
929 void shadowRegionArgs(Region &,
ValueRange)
override {}
932 const OpPrintingFlags &printerFlags;
935 AliasInitializer &initializer;
938 mutable llvm::raw_null_ostream os;
943 explicit DummyAliasDialectAsmPrinter(AliasInitializer &initializer,
945 SmallVectorImpl<size_t> &childIndices)
946 : initializer(initializer), canBeDeferred(canBeDeferred),
947 childIndices(childIndices) {}
952 template <
typename T,
typename... PrintArgs>
953 size_t printAndVisitNestedAliases(T value, PrintArgs &&...
printArgs) {
954 printAndVisitNestedAliasesImpl(value,
printArgs...);
955 return maxAliasDepth;
961 void printAndVisitNestedAliasesImpl(Attribute attr,
bool elideType) {
962 if (!isa<BuiltinDialect>(attr.
getDialect())) {
966 }
else if (llvm::isa<AffineMapAttr, DenseArrayAttr, FloatAttr, IntegerAttr,
967 IntegerSetAttr, UnitAttr>(attr)) {
969 }
else if (
auto distinctAttr = dyn_cast<DistinctAttr>(attr)) {
970 printAttribute(distinctAttr.getReferencedAttr());
971 }
else if (
auto dictAttr = dyn_cast<DictionaryAttr>(attr)) {
972 for (
const NamedAttribute &nestedAttr : dictAttr.getValue()) {
973 printAttribute(nestedAttr.getName());
974 printAttribute(nestedAttr.getValue());
976 }
else if (
auto arrayAttr = dyn_cast<ArrayAttr>(attr)) {
977 for (Attribute nestedAttr : arrayAttr.getValue())
978 printAttribute(nestedAttr);
979 }
else if (
auto typeAttr = dyn_cast<TypeAttr>(attr)) {
981 }
else if (
auto locAttr = dyn_cast<OpaqueLoc>(attr)) {
982 printAttribute(locAttr.getFallbackLocation());
983 }
else if (
auto locAttr = dyn_cast<NameLoc>(attr)) {
984 if (!isa<UnknownLoc>(locAttr.getChildLoc()))
985 printAttribute(locAttr.getChildLoc());
986 }
else if (
auto locAttr = dyn_cast<CallSiteLoc>(attr)) {
987 printAttribute(locAttr.getCallee());
988 printAttribute(locAttr.getCaller());
989 }
else if (
auto locAttr = dyn_cast<FusedLoc>(attr)) {
990 if (Attribute metadata = locAttr.getMetadata())
991 printAttribute(metadata);
992 for (Location nestedLoc : locAttr.getLocations())
993 printAttribute(nestedLoc);
998 if (
auto typedAttr = llvm::dyn_cast<TypedAttr>(attr)) {
999 Type attrType = typedAttr.getType();
1000 if (!llvm::isa<NoneType>(attrType))
1005 void printAndVisitNestedAliasesImpl(Type type) {
1012 if (
auto memrefTy = llvm::dyn_cast<MemRefType>(type)) {
1014 MemRefLayoutAttrInterface layout = memrefTy.getLayout();
1015 if (!llvm::isa<AffineMapAttr>(layout) || !layout.isIdentity())
1016 printAttribute(memrefTy.getLayout());
1017 if (memrefTy.getMemorySpace())
1018 printAttribute(memrefTy.getMemorySpace());
1023 auto visitFn = [&](
auto element) {
1025 (void)printAlias(element);
1032 recordAliasResult(initializer.visit(type, canBeDeferred));
1036 void printAttribute(Attribute attr)
override {
1037 recordAliasResult(initializer.visit(attr, canBeDeferred));
1039 void printAttributeWithoutType(Attribute attr)
override {
1041 initializer.visit(attr, canBeDeferred,
true));
1043 void printNamedAttribute(NamedAttribute attr)
override {
1047 LogicalResult printAlias(Attribute attr)
override {
1048 printAttribute(attr);
1051 LogicalResult printAlias(Type type)
override {
1057 void recordAliasResult(std::pair<size_t, size_t> aliasDepthAndIndex) {
1058 childIndices.push_back(aliasDepthAndIndex.second);
1059 if (aliasDepthAndIndex.first > maxAliasDepth)
1060 maxAliasDepth = aliasDepthAndIndex.first;
1065 raw_ostream &getStream()
const override {
return os; }
1070 void increaseIndent()
override {}
1071 void decreaseIndent()
override {}
1072 void printFloat(
const APFloat &)
override {}
1075 void printSymbolName(StringRef)
override {}
1076 void printResourceHandle(
const AsmDialectResourceHandle &)
override {}
1078 LogicalResult pushCyclicPrinting(
const void *opaquePointer)
override {
1079 return success(cyclicPrintingStack.insert(opaquePointer));
1082 void popCyclicPrinting()
override { cyclicPrintingStack.pop_back(); }
1086 SetVector<const void *> cyclicPrintingStack;
1089 AliasInitializer &initializer;
1095 SmallVectorImpl<size_t> &childIndices;
1098 size_t maxAliasDepth = 0;
1101 mutable llvm::raw_null_ostream os;
1109 StringRef allowedPunctChars =
"$._-") {
1110 assert(!name.empty() &&
"Shouldn't have an empty name here");
1112 auto validChar = [&](
char ch) {
1113 return llvm::isAlnum(ch) || allowedPunctChars.contains(ch);
1116 auto copyNameToBuffer = [&] {
1117 for (
char ch : name) {
1119 buffer.push_back(ch);
1121 buffer.push_back(
'_');
1123 buffer.append(llvm::utohexstr((
unsigned char)ch));
1130 if (isdigit(name[0]) || (!validChar(name[0]) && name[0] !=
' ')) {
1131 buffer.push_back(
'_');
1137 for (
char ch : name) {
1138 if (!validChar(ch)) {
1148unsigned AliasInitializer::uniqueAliasNameIndex(
1149 StringRef alias, llvm::StringMap<unsigned> &nameCounts,
1150 llvm::StringSet<llvm::BumpPtrAllocator &> &usedAliases) {
1151 if (!usedAliases.count(alias)) {
1152 usedAliases.insert(alias);
1158 size_t probeSize = probeAlias.size();
1160 if (isdigit(alias.back())) {
1161 probeAlias.push_back(
'_');
1165 if (nameCounts[probeAlias] == 0)
1166 nameCounts[probeAlias] = 1;
1170 unsigned nameIndex = nameCounts[probeAlias]++;
1171 probeAlias += llvm::utostr(nameIndex);
1172 if (!usedAliases.count(probeAlias)) {
1173 usedAliases.insert(probeAlias);
1177 probeAlias.resize(probeSize);
1183void AliasInitializer::initializeAliases(
1184 llvm::MapVector<const void *, InProgressAliasInfo> &visitedSymbols,
1185 llvm::MapVector<const void *, SymbolAlias> &symbolToAlias) {
1187 unprocessedAliases = visitedSymbols.takeVector();
1188 llvm::stable_sort(unprocessedAliases, llvm::less_second());
1192 llvm::BumpPtrAllocator usedAliasAllocator;
1193 llvm::StringSet<llvm::BumpPtrAllocator &> usedAliases(usedAliasAllocator);
1195 llvm::StringMap<unsigned> nameCounts;
1196 for (
auto &[symbol, aliasInfo] : unprocessedAliases) {
1197 if (!aliasInfo.alias)
1199 StringRef alias = *aliasInfo.alias;
1200 unsigned nameIndex = uniqueAliasNameIndex(alias, nameCounts, usedAliases);
1201 symbolToAlias.insert(
1202 {symbol, SymbolAlias(alias, nameIndex, aliasInfo.isType,
1203 aliasInfo.canBeDeferred)});
1207void AliasInitializer::initialize(
1209 llvm::MapVector<const void *, SymbolAlias> &attrTypeToAlias) {
1213 DummyAliasOperationPrinter aliasPrinter(printerFlags, *
this);
1214 aliasPrinter.printCustomOrGenericOp(op);
1217 initializeAliases(aliases, attrTypeToAlias);
1220template <
typename T,
typename... PrintArgs>
1221std::pair<size_t, size_t> AliasInitializer::visitImpl(
1222 T value, llvm::MapVector<const void *, InProgressAliasInfo> &aliases,
1223 bool canBeDeferred, PrintArgs &&...
printArgs) {
1224 auto [it,
inserted] = aliases.try_emplace(value.getAsOpaquePointer());
1225 size_t aliasIndex = std::distance(aliases.begin(), it);
1229 markAliasNonDeferrable(aliasIndex);
1230 return {
static_cast<size_t>(it->second.aliasDepth), aliasIndex};
1234 generateAlias(value, it->second, canBeDeferred);
1235 it->second.isType = std::is_base_of_v<Type, T>;
1236 it->second.canBeDeferred = canBeDeferred;
1240 DummyAliasDialectAsmPrinter printer(*
this, canBeDeferred, childAliases);
1241 size_t maxAliasDepth =
1242 printer.printAndVisitNestedAliases(value,
printArgs...);
1245 it = std::next(aliases.begin(), aliasIndex);
1248 it->second.childIndices = std::move(childAliases);
1250 it->second.aliasDepth = maxAliasDepth + 1;
1253 return {(size_t)it->second.aliasDepth, aliasIndex};
1256void AliasInitializer::markAliasNonDeferrable(
size_t aliasIndex) {
1257 auto *it = std::next(aliases.begin(), aliasIndex);
1261 if (!it->second.canBeDeferred)
1264 it->second.canBeDeferred =
false;
1267 for (
size_t childIndex : it->second.childIndices)
1268 markAliasNonDeferrable(childIndex);
1271template <
typename T>
1272void AliasInitializer::generateAlias(T symbol, InProgressAliasInfo &alias,
1273 bool canBeDeferred) {
1276 OpAsmDialectInterface::AliasResult symbolInterfaceResult =
1277 OpAsmDialectInterface::AliasResult::NoAlias;
1278 using InterfaceT = std::conditional_t<std::is_base_of_v<Attribute, T>,
1279 OpAsmAttrInterface, OpAsmTypeInterface>;
1280 if (
auto symbolInterface = dyn_cast<InterfaceT>(symbol)) {
1281 symbolInterfaceResult = symbolInterface.getAlias(aliasOS);
1282 if (symbolInterfaceResult != OpAsmDialectInterface::AliasResult::NoAlias) {
1283 nameBuffer = std::move(aliasBuffer);
1284 assert(!nameBuffer.empty() &&
"expected valid alias name");
1288 if (symbolInterfaceResult != OpAsmDialectInterface::AliasResult::FinalAlias) {
1289 for (
const auto &interface : interfaces) {
1290 OpAsmDialectInterface::AliasResult
result =
1291 interface.getAlias(symbol, aliasOS);
1292 if (
result == OpAsmDialectInterface::AliasResult::NoAlias)
1294 nameBuffer = std::move(aliasBuffer);
1295 assert(!nameBuffer.empty() &&
"expected valid alias name");
1296 if (
result == OpAsmDialectInterface::AliasResult::FinalAlias)
1301 if (nameBuffer.empty())
1307 name = name.copy(aliasAllocator);
1308 alias = InProgressAliasInfo(name);
1321 initialize(Operation *op,
const OpPrintingFlags &printerFlags,
1322 DialectInterfaceCollection<OpAsmDialectInterface> &interfaces);
1326 LogicalResult getAlias(Attribute attr, raw_ostream &os)
const;
1330 LogicalResult getAlias(Type ty, raw_ostream &os)
const;
1334 void printNonDeferredAliases(AsmPrinter::Impl &p, NewLineCounter &newLine) {
1335 printAliases(p, newLine,
false);
1339 void printDeferredAliases(AsmPrinter::Impl &p, NewLineCounter &newLine) {
1340 printAliases(p, newLine,
true);
1346 void printAliases(AsmPrinter::Impl &p, NewLineCounter &newLine,
1350 llvm::MapVector<const void *, SymbolAlias> attrTypeToAlias;
1353 llvm::BumpPtrAllocator aliasAllocator;
1357void AliasState::initialize(
1362 attrTypeToAlias.clear();
1363 AliasInitializer initializer(interfaces, aliasAllocator);
1364 initializer.initialize(op, printerFlags, attrTypeToAlias);
1369 if (it == attrTypeToAlias.end())
1371 it->second.print(os);
1377 if (it == attrTypeToAlias.end())
1379 if (!it->second.isPrinted)
1382 it->second.print(os);
1388 auto filterFn = [=](
const auto &aliasIt) {
1389 return aliasIt.second.canBeDeferred() == isDeferred;
1391 for (
auto &[opaqueSymbol, alias] :
1392 llvm::make_filter_range(attrTypeToAlias, filterFn)) {
1396 if (alias.isTypeAlias()) {
1399 alias.isPrinted =
true;
1429 enum :
unsigned { NameSentinel = ~0U };
1431 SSANameState(Operation *op,
const OpPrintingFlags &printerFlags);
1432 SSANameState() =
default;
1437 void printValueID(Value value,
bool printResultNo, raw_ostream &stream)
const;
1440 void printOperationID(Operation *op, raw_ostream &stream)
const;
1444 ArrayRef<int> getOpResultGroups(Operation *op);
1447 BlockInfo getBlockInfo(
Block *block);
1452 void shadowRegionArgs(Region ®ion,
ValueRange namesToUse);
1456 void numberValuesInRegion(Region ®ion);
1457 void numberValuesInBlock(
Block &block);
1458 void numberValuesInOp(Operation &op);
1464 void getResultIDAndNumber(OpResult
result, Value &lookupValue,
1465 std::optional<int> &lookupResultNo)
const;
1468 void setValueName(Value value, StringRef name);
1472 StringRef uniqueValueName(StringRef name);
1495 llvm::ScopedHashTable<StringRef, char> usedNames;
1496 llvm::BumpPtrAllocator usedNameAllocator;
1499 unsigned nextValueID = 0;
1501 unsigned nextArgumentID = 0;
1503 unsigned nextConflictID = 0;
1507 OpPrintingFlags printerFlags;
1512 : printerFlags(printerFlags) {
1513 llvm::SaveAndRestore valueIDSaver(nextValueID);
1514 llvm::SaveAndRestore argumentIDSaver(nextArgumentID);
1515 llvm::SaveAndRestore conflictIDSaver(nextConflictID);
1520 using UsedNamesScopeTy = llvm::ScopedHashTable<StringRef, char>::ScopeTy;
1521 using NamingContext =
1522 std::tuple<Region *, unsigned, unsigned, unsigned, UsedNamesScopeTy *>;
1525 llvm::BumpPtrAllocator allocator;
1528 auto *topLevelNamesScope =
1529 new (allocator.Allocate<UsedNamesScopeTy>()) UsedNamesScopeTy(usedNames);
1533 nameContext.push_back(std::make_tuple(®ion, nextValueID, nextArgumentID,
1534 nextConflictID, topLevelNamesScope));
1536 numberValuesInOp(*op);
1538 while (!nameContext.empty()) {
1540 UsedNamesScopeTy *parentScope;
1544 std::tie(region, std::ignore, std::ignore, std::ignore, parentScope) =
1545 nameContext.pop_back_val();
1547 std::tie(region, nextValueID, nextArgumentID, nextConflictID,
1548 parentScope) = nameContext.pop_back_val();
1552 while (usedNames.getCurScope() != parentScope) {
1553 usedNames.getCurScope()->~UsedNamesScopeTy();
1554 assert((usedNames.getCurScope() !=
nullptr || parentScope ==
nullptr) &&
1555 "top level parentScope must be a nullptr");
1559 auto *curNamesScope =
new (allocator.Allocate<UsedNamesScopeTy>())
1560 UsedNamesScopeTy(usedNames);
1562 numberValuesInRegion(*region);
1566 nameContext.push_back(std::make_tuple(®ion, nextValueID,
1567 nextArgumentID, nextConflictID,
1572 while (usedNames.getCurScope() !=
nullptr)
1573 usedNames.getCurScope()->~UsedNamesScopeTy();
1576void SSANameState::printValueID(
Value value,
bool printResultNo,
1579 stream <<
"<<NULL VALUE>>";
1583 std::optional<int> resultNo;
1584 auto lookupValue = value;
1588 if (OpResult
result = dyn_cast<OpResult>(value))
1589 getResultIDAndNumber(
result, lookupValue, resultNo);
1591 auto it = valueIDs.find(lookupValue);
1592 if (it == valueIDs.end()) {
1593 stream <<
"<<UNKNOWN SSA VALUE>>";
1598 if (it->second != NameSentinel) {
1599 stream << it->second;
1601 auto nameIt = valueNames.find(lookupValue);
1602 assert(nameIt != valueNames.end() &&
"Didn't have a name entry?");
1603 stream << nameIt->second;
1606 if (resultNo && printResultNo)
1607 stream <<
'#' << *resultNo;
1610void SSANameState::printOperationID(Operation *op, raw_ostream &stream)
const {
1611 auto it = operationIDs.find(op);
1612 if (it == operationIDs.end()) {
1613 stream <<
"<<UNKNOWN OPERATION>>";
1615 stream <<
'%' << it->second;
1619ArrayRef<int> SSANameState::getOpResultGroups(Operation *op) {
1620 auto it = opResultGroups.find(op);
1621 return it == opResultGroups.end() ? ArrayRef<int>() : it->second;
1624BlockInfo SSANameState::getBlockInfo(
Block *block) {
1625 auto it = blockNames.find(block);
1626 BlockInfo invalidBlock{-1,
"INVALIDBLOCK"};
1627 return it != blockNames.end() ? it->second : invalidBlock;
1630void SSANameState::shadowRegionArgs(Region ®ion,
ValueRange namesToUse) {
1631 assert(!region.
empty() &&
"cannot shadow arguments of an empty region");
1633 "incorrect number of names passed in");
1635 "only KnownIsolatedFromAbove ops can shadow names");
1637 SmallVector<char, 16> nameStr;
1638 for (
unsigned i = 0, e = namesToUse.size(); i != e; ++i) {
1639 auto nameToUse = namesToUse[i];
1640 if (nameToUse ==
nullptr)
1645 llvm::raw_svector_ostream nameStream(nameStr);
1646 printValueID(nameToUse,
true, nameStream);
1649 assert(valueIDs[nameToReplace] == NameSentinel);
1652 auto name = StringRef(nameStream.str()).drop_front();
1655 valueNames[nameToReplace] = name.copy(usedNameAllocator);
1661StringRef maybeGetValueNameFromLoc(Value value, StringRef name) {
1663 return maybeNameLoc.getName();
1668void SSANameState::numberValuesInRegion(Region ®ion) {
1670 bool opAsmOpInterfaceUsed =
false;
1671 auto setBlockArgNameFn = [&](Value arg, StringRef name) {
1672 assert(!valueIDs.count(arg) &&
"arg numbered multiple times");
1673 assert(llvm::cast<BlockArgument>(arg).getOwner()->getParent() == ®ion &&
1674 "arg not defined in current region");
1675 opAsmOpInterfaceUsed =
true;
1677 name = maybeGetValueNameFromLoc(arg, name);
1678 setValueName(arg, name);
1683 if (
auto asmInterface = dyn_cast<OpAsmOpInterface>(op))
1684 asmInterface.getAsmBlockArgumentNames(region, setBlockArgNameFn);
1686 if (!opAsmOpInterfaceUsed) {
1688 if (
auto interface = dyn_cast<OpAsmTypeInterface>(arg.
getType())) {
1689 interface.getAsmName(
1690 [&](StringRef name) { setBlockArgNameFn(arg, name); });
1698 unsigned nextBlockID = 0;
1699 for (
auto &block : region) {
1702 auto blockInfoIt = blockNames.insert({&block, {-1,
""}});
1703 if (blockInfoIt.second) {
1707 llvm::raw_string_ostream(name) <<
"^bb" << nextBlockID;
1708 blockInfoIt.first->second.name = StringRef(name).copy(usedNameAllocator);
1710 blockInfoIt.first->second.ordering = nextBlockID++;
1712 numberValuesInBlock(block);
1716void SSANameState::numberValuesInBlock(
Block &block) {
1720 SmallString<32> specialNameBuffer(isEntryBlock ?
"arg" :
"");
1721 llvm::raw_svector_ostream specialName(specialNameBuffer);
1723 if (valueIDs.count(arg))
1726 specialNameBuffer.resize(strlen(
"arg"));
1727 specialName << nextArgumentID++;
1729 StringRef specialNameStr = specialName.str();
1731 specialNameStr = maybeGetValueNameFromLoc(arg, specialNameStr);
1732 setValueName(arg, specialNameStr);
1736 for (
auto &op : block)
1737 numberValuesInOp(op);
1740void SSANameState::numberValuesInOp(Operation &op) {
1742 SmallVector<int, 2> resultGroups(1, 0);
1744 bool opAsmOpInterfaceUsed =
false;
1745 auto setResultNameFn = [&](Value
result, StringRef name) {
1746 assert(!valueIDs.count(
result) &&
"result numbered multiple times");
1747 assert(
result.getDefiningOp() == &op &&
"result not defined by 'op'");
1748 opAsmOpInterfaceUsed =
true;
1750 name = maybeGetValueNameFromLoc(
result, name);
1751 setValueName(
result, name);
1754 if (
int resultNo = llvm::cast<OpResult>(
result).getResultNumber())
1755 resultGroups.push_back(resultNo);
1758 auto setBlockNameFn = [&](
Block *block, StringRef name) {
1760 "getAsmBlockArgumentNames callback invoked on a block not directly "
1761 "nested under the current operation");
1762 assert(!blockNames.count(block) &&
"block numbered multiple times");
1763 SmallString<16> tmpBuffer{
"^"};
1765 if (name.data() != tmpBuffer.data()) {
1766 tmpBuffer.append(name);
1767 name = tmpBuffer.str();
1769 name = name.copy(usedNameAllocator);
1770 blockNames[block] = {-1, name};
1774 if (OpAsmOpInterface asmInterface = dyn_cast<OpAsmOpInterface>(&op)) {
1775 asmInterface.getAsmBlockNames(setBlockNameFn);
1776 asmInterface.getAsmResultNames(setResultNameFn);
1778 if (!opAsmOpInterfaceUsed) {
1781 bool allHaveOpAsmTypeInterface =
1783 return isa<OpAsmTypeInterface>(type);
1785 if (allHaveOpAsmTypeInterface) {
1787 auto interface = cast<OpAsmTypeInterface>(
result.
getType());
1788 interface.getAsmName(
1789 [&](StringRef name) { setResultNameFn(
result, name); });
1796 if (numResults == 0) {
1799 if (operationIDs.try_emplace(&op, nextValueID).second)
1808 setValueName(resultBegin, nameLoc.getName());
1813 if (valueIDs.try_emplace(resultBegin, nextValueID).second)
1817 if (resultGroups.size() != 1) {
1818 llvm::array_pod_sort(resultGroups.begin(), resultGroups.end());
1819 opResultGroups.try_emplace(&op, std::move(resultGroups));
1823void SSANameState::getResultIDAndNumber(
1824 OpResult
result, Value &lookupValue,
1825 std::optional<int> &lookupResultNo)
const {
1826 Operation *owner =
result.getOwner();
1829 int resultNo =
result.getResultNumber();
1833 auto resultGroupIt = opResultGroups.find(owner);
1834 if (resultGroupIt == opResultGroups.end()) {
1836 lookupResultNo = resultNo;
1842 ArrayRef<int> resultGroups = resultGroupIt->second;
1843 const auto *it = llvm::upper_bound(resultGroups, resultNo);
1844 int groupResultNo = 0, groupSize = 0;
1847 if (it == resultGroups.end()) {
1848 groupResultNo = resultGroups.back();
1849 groupSize =
static_cast<int>(owner->
getNumResults()) - resultGroups.back();
1852 groupResultNo = *std::prev(it);
1853 groupSize = *it - groupResultNo;
1858 lookupResultNo = resultNo - groupResultNo;
1859 lookupValue = owner->
getResult(groupResultNo);
1862void SSANameState::setValueName(Value value, StringRef name) {
1865 valueIDs[value] = nextValueID++;
1869 valueIDs[value] = NameSentinel;
1870 valueNames[value] = uniqueValueName(name);
1873StringRef SSANameState::uniqueValueName(StringRef name) {
1874 SmallString<16> tmpBuffer;
1878 if (!usedNames.count(name)) {
1879 name = name.copy(usedNameAllocator);
1884 SmallString<64> probeName(name);
1885 probeName.push_back(
'_');
1887 probeName += llvm::utostr(nextConflictID++);
1888 if (!usedNames.count(probeName)) {
1889 name = probeName.str().copy(usedNameAllocator);
1892 probeName.resize(name.size() + 1);
1896 usedNames.insert(name,
char());
1906class DistinctState {
1909 uint64_t getId(DistinctAttr distinctAttr);
1912 uint64_t distinctCounter = 0;
1917uint64_t DistinctState::getId(DistinctAttr distinctAttr) {
1919 distinctAttrMap.try_emplace(distinctAttr, distinctCounter);
1922 return it->getSecond();
1943 llvm_unreachable(
"unknown AsmResourceEntryKind");
1947 std::unique_ptr<ResourceCollection> &collection = keyToResources[key.str()];
1949 collection = std::make_unique<ResourceCollection>(key);
1953std::vector<std::unique_ptr<AsmResourcePrinter>>
1955 std::vector<std::unique_ptr<AsmResourcePrinter>> printers;
1956 for (
auto &it : keyToResources) {
1957 ResourceCollection *collection = it.second.get();
1959 return collection->buildResources(op, builder);
1961 printers.emplace_back(
1967LogicalResult FallbackAsmResourceMap::ResourceCollection::parseResource(
1971 FailureOr<AsmResourceBlob> blob = entry.
parseAsBlob();
1974 resources.emplace_back(entry.
getKey(), std::move(*blob));
1981 resources.emplace_back(entry.
getKey(), *value);
1984 case AsmResourceEntryKind::String: {
1988 resources.emplace_back(entry.
getKey(), std::move(*str));
1995void FallbackAsmResourceMap::ResourceCollection::buildResources(
1996 Operation *op, AsmResourceBuilder &builder)
const {
1997 for (
const auto &entry : resources) {
1998 if (
const auto *value = std::get_if<AsmResourceBlob>(&entry.value))
2000 else if (
const auto *value = std::get_if<bool>(&entry.value))
2002 else if (
const auto *value = std::get_if<std::string>(&entry.value))
2005 llvm_unreachable(
"unknown AsmResourceEntryKind");
2019 : interfaces(op->
getContext()), nameState(op, printerFlags),
2020 printerFlags(printerFlags), locationMap(locationMap) {}
2023 : interfaces(ctx), printerFlags(printerFlags), locationMap(locationMap) {}
2029 dialectResources.clear();
2030 aliasState.initialize(op, printerFlags, interfaces);
2050 return llvm::make_pointee_range(externalResourcePrinters);
2060 (*locationMap)[op] = std::make_pair(line, col);
2066 return dialectResources;
2070 return success(cyclicPrintingStack.insert(opaquePointer));
2086 AliasState aliasState;
2089 SSANameState nameState;
2092 DistinctState distinctState;
2108template <
typename Range>
2112 [&stream](
const auto &dimSize) {
2113 if (ShapedType::isDynamic(dimSize))
2131 return printerFlags;
2135 auto parentThreadId = llvm::get_threadid();
2137 if (parentThreadId == llvm::get_threadid()) {
2139 diag.print(llvm::dbgs());
2140 llvm::dbgs() <<
"\n";
2148 <<
"' failed to verify and will be printed in generic form";
2152 return printerFlags;
2171 return impl->getPrinterFlags();
2175 std::unique_ptr<AsmResourcePrinter> printer) {
2176 impl->externalResourcePrinters.emplace_back(std::move(printer));
2181 return impl->getDialectResources();
2203 if (!isTopLevel && succeeded(
state.getAliasState().getAlias(loc,
os)))
2207 .Case([&](OpaqueLoc loc) {
2210 .Case([&](UnknownLoc loc) {
2218 os << loc.getFilename().getValue();
2221 if (loc.getEndColumn() == loc.getStartColumn() &&
2222 loc.getStartLine() == loc.getEndLine()) {
2223 os <<
':' << loc.getStartLine() <<
':' << loc.getStartColumn();
2226 if (loc.getStartLine() == loc.getEndLine()) {
2227 os <<
':' << loc.getStartLine() <<
':' << loc.getStartColumn()
2228 <<
" to :" << loc.getEndColumn();
2231 os <<
':' << loc.getStartLine() <<
':' << loc.getStartColumn() <<
" to "
2232 << loc.getEndLine() <<
':' << loc.getEndColumn();
2234 .Case([&](NameLoc loc) {
2238 auto childLoc = loc.getChildLoc();
2239 if (!llvm::isa<UnknownLoc>(childLoc)) {
2245 .Case([&](CallSiteLoc loc) {
2252 if (llvm::isa<NameLoc>(callee)) {
2253 if (llvm::isa<FileLineColLoc>(caller)) {
2271 if (
Attribute metadata = loc.getMetadata()) {
2278 printLocationInternal(loc, pretty);
2292 bool *printedHex =
nullptr) {
2297 bool isInf = apValue.isInfinity();
2298 bool isNaN = apValue.isNaN();
2299 if (!isInf && !isNaN) {
2301 bool isLossless = apValue.toStringRoundTrip(strValue,
2309 assert(((strValue[0] >=
'0' && strValue[0] <=
'9') ||
2310 ((strValue[0] ==
'-' || strValue[0] ==
'+') &&
2311 (strValue[1] >=
'0' && strValue[1] <=
'9'))) &&
2312 "[-+]?[0-9] regex does not match!");
2323 apValue.toString(strValue);
2326 if (strValue.str().contains(
'.')) {
2337 APInt apInt = apValue.bitcastToAPInt();
2338 apInt.toString(str, 16,
false,
2358 if (symName.empty() || !isalpha(symName.front()))
2363 symName = symName.drop_while(
2364 [](
char c) {
return llvm::isAlnum(c) || c ==
'.' || c ==
'_'; });
2365 if (symName.empty())
2370 return symName.front() ==
'<' && symName.back() ==
'>';
2375 StringRef dialectName, StringRef symString) {
2376 os << symPrefix << dialectName;
2381 os <<
'.' << symString;
2385 os <<
'<' << symString <<
'>';
2394 if (name.empty() || (!isalpha(name[0]) && name[0] !=
'_'))
2396 return llvm::all_of(name.drop_front(), [](
unsigned char c) {
2397 return isalnum(c) || c ==
'_' || c ==
'$' || c ==
'.';
2412 printEscapedString(keyword, os);
2420 if (symbolRef.empty()) {
2421 os <<
"@<<INVALID EMPTY SYMBOL>>";
2434 os << R
"(dense_resource<__elided__>)";
2439 auto *
interface = cast<OpAsmDialectInterface>(resource.getDialect());
2445 return state.getAliasState().getAlias(attr,
os);
2449 return state.getAliasState().getAlias(type,
os);
2455 os <<
"<<NULL ATTRIBUTE>>";
2466 if (!isa<BuiltinDialect>(attr.
getDialect())) {
2468 }
else if (
auto opaqueAttr = llvm::dyn_cast<OpaqueAttr>(attr)) {
2470 opaqueAttr.getAttrData());
2471 }
else if (llvm::isa<UnitAttr>(attr)) {
2474 }
else if (
auto distinctAttr = llvm::dyn_cast<DistinctAttr>(attr)) {
2475 os <<
"distinct[" <<
state.getDistinctState().getId(distinctAttr) <<
"]<";
2481 }
else if (
auto dictAttr = llvm::dyn_cast<DictionaryAttr>(attr)) {
2487 }
else if (
auto intAttr = llvm::dyn_cast<IntegerAttr>(attr)) {
2488 Type intType = intAttr.getType();
2490 os << (intAttr.getValue().getBoolValue() ?
"true" :
"false");
2501 intAttr.getValue().print(
os, !isUnsigned);
2507 }
else if (
auto floatAttr = llvm::dyn_cast<FloatAttr>(attr)) {
2508 bool printedHex =
false;
2516 }
else if (
auto strAttr = llvm::dyn_cast<StringAttr>(attr)) {
2519 }
else if (
auto arrayAttr = llvm::dyn_cast<ArrayAttr>(attr)) {
2522 printAttribute(attr, AttrTypeElision::May);
2526 }
else if (
auto affineMapAttr = llvm::dyn_cast<AffineMapAttr>(attr)) {
2527 os <<
"affine_map<";
2528 affineMapAttr.getValue().print(
os);
2534 }
else if (
auto integerSetAttr = llvm::dyn_cast<IntegerSetAttr>(attr)) {
2535 os <<
"affine_set<";
2536 integerSetAttr.getValue().print(
os);
2542 }
else if (
auto typeAttr = llvm::dyn_cast<TypeAttr>(attr)) {
2545 }
else if (
auto refAttr = llvm::dyn_cast<SymbolRefAttr>(attr)) {
2552 }
else if (
auto intOrFpEltAttr =
2553 llvm::dyn_cast<DenseTypedElementsAttr>(attr)) {
2554 if (
printerFlags.shouldElideElementsAttr(intOrFpEltAttr)) {
2561 Type eltType = intOrFpEltAttr.getElementType();
2562 if (isa<FloatType, IntegerType, IndexType, ComplexType>(eltType)) {
2566 cast<DenseElementType>(eltType));
2572 }
else if (
auto strEltAttr = llvm::dyn_cast<DenseStringElementsAttr>(attr)) {
2573 if (
printerFlags.shouldElideElementsAttr(strEltAttr)) {
2581 }
else if (
auto sparseEltAttr = llvm::dyn_cast<SparseElementsAttr>(attr)) {
2582 if (
printerFlags.shouldElideElementsAttr(sparseEltAttr.getIndices()) ||
2583 printerFlags.shouldElideElementsAttr(sparseEltAttr.getValues())) {
2588 if (
indices.getNumElements() != 0) {
2595 }
else if (
auto stridedLayoutAttr = llvm::dyn_cast<StridedLayoutAttr>(attr)) {
2596 stridedLayoutAttr.print(
os);
2597 }
else if (
auto denseArrayAttr = llvm::dyn_cast<DenseArrayAttr>(attr)) {
2599 printType(denseArrayAttr.getElementType());
2600 if (!denseArrayAttr.empty()) {
2606 }
else if (
auto resourceAttr =
2607 llvm::dyn_cast<DenseResourceElementsAttr>(attr)) {
2608 os <<
"dense_resource<";
2611 }
else if (
auto locAttr = llvm::dyn_cast<LocationAttr>(attr)) {
2614 llvm::report_fatal_error(
"Unknown builtin attribute");
2618 if (
auto typedAttr = llvm::dyn_cast<TypedAttr>(attr)) {
2619 Type attrType = typedAttr.getType();
2620 if (!llvm::isa<NoneType>(attrType)) {
2632 os << (value.getBoolValue() ?
"true" :
"false");
2642 return printEltFn(0);
2645 auto numElements = type.getNumElements();
2646 if (numElements == 0)
2654 int64_t rank = type.getRank();
2657 unsigned openBrackets = 0;
2659 auto shape = type.getShape();
2660 auto bumpCounter = [&] {
2662 ++counter[rank - 1];
2664 for (
unsigned i = rank - 1; i > 0; --i)
2665 if (counter[i] >=
shape[i]) {
2674 for (
unsigned idx = 0, e = numElements; idx != e; ++idx) {
2677 while (openBrackets++ < rank)
2679 openBrackets = rank;
2683 while (openBrackets-- > 0)
2689 if (
auto stringAttr = llvm::dyn_cast<DenseStringElementsAttr>(attr))
2698 auto type = attr.getType();
2699 auto elementType = type.getElementType();
2703 (elementType.isIntOrIndexOrFloat() ||
2704 llvm::isa<ComplexType>(elementType)) &&
2707 if (llvm::endianness::native == llvm::endianness::big) {
2712 DenseTypedElementsAttr::convertEndianOfArrayRefForBEmachine(
2713 rawData, convRawData, type);
2722 if (ComplexType complexTy = llvm::dyn_cast<ComplexType>(elementType)) {
2723 Type complexElementType = complexTy.getElementType();
2727 if (llvm::isa<IntegerType>(complexElementType)) {
2730 auto complexValue = *(valueIt + index);
2732 printDenseIntElement(complexValue.real(), os, complexElementType);
2734 printDenseIntElement(complexValue.imag(), os, complexElementType);
2740 auto complexValue = *(valueIt + index);
2742 printFloatValue(complexValue.real(), os);
2744 printFloatValue(complexValue.imag(), os);
2748 }
else if (elementType.isIntOrIndex()) {
2749 auto valueIt = attr.value_begin<APInt>();
2751 printDenseIntElement(*(valueIt + index), os, elementType);
2753 }
else if (llvm::isa<MXI8Type>(elementType)) {
2754 auto valueIt = attr.value_begin<
Attribute>();
2756 auto value = llvm::cast<IntegerAttr>(*(valueIt + index));
2757 printDenseIntElement(value.getValue(), os, value.getType());
2760 assert(llvm::isa<FloatType>(elementType) &&
"unexpected element type");
2761 auto valueIt = attr.value_begin<APFloat>();
2763 printFloatValue(*(valueIt + index), os);
2769 DenseStringElementsAttr attr) {
2783 size_t bitSize = denseEltType.getDenseElementBitSize();
2784 size_t byteSize = llvm::divideCeil(bitSize,
static_cast<size_t>(CHAR_BIT));
2789 size_t offset = attr.isSplat() ? 0 : index * byteSize;
2790 ArrayRef<char> elemData = rawData.slice(offset, byteSize);
2791 Attribute elemAttr = denseEltType.convertToAttribute(elemData);
2792 printAttributeImpl(elemAttr);
2797 Type type = attr.getElementType();
2799 unsigned byteSize = bitwidth / 8;
2802 auto printElementAt = [&](
unsigned i) {
2803 APInt value(bitwidth, 0);
2805 llvm::LoadIntFromMemory(
2806 value,
reinterpret_cast<const uint8_t *
>(data.begin() + byteSize * i),
2817 llvm::interleaveComma(llvm::seq<unsigned>(0, attr.size()),
getStream(),
2823 os <<
"<<NULL TYPE>>";
2835 .Case([&](OpaqueType opaqueTy) {
2837 opaqueTy.getTypeData());
2839 .Case<IndexType>([&](
Type) {
os <<
"index"; })
2840 .Case<Float4E2M1FNType>([&](
Type) {
os <<
"f4E2M1FN"; })
2841 .Case<Float6E2M3FNType>([&](
Type) {
os <<
"f6E2M3FN"; })
2842 .Case<Float6E3M2FNType>([&](
Type) {
os <<
"f6E3M2FN"; })
2843 .Case<Float8E5M2Type>([&](
Type) {
os <<
"f8E5M2"; })
2844 .Case<Float8E4M3Type>([&](
Type) {
os <<
"f8E4M3"; })
2845 .Case<Float8E4M3FNType>([&](
Type) {
os <<
"f8E4M3FN"; })
2846 .Case<Float8E5M2FNUZType>([&](
Type) {
os <<
"f8E5M2FNUZ"; })
2847 .Case<Float8E4M3FNUZType>([&](
Type) {
os <<
"f8E4M3FNUZ"; })
2848 .Case<Float8E4M3B11FNUZType>([&](
Type) {
os <<
"f8E4M3B11FNUZ"; })
2849 .Case<Float8E3M4Type>([&](
Type) {
os <<
"f8E3M4"; })
2850 .Case<Float8E8M0FNUType>([&](
Type) {
os <<
"f8E8M0FNU"; })
2851 .Case<Float8E5M3FNUType>([&](
Type) {
os <<
"f8E5M3FNU"; })
2852 .Case<BFloat16Type>([&](
Type) {
os <<
"bf16"; })
2853 .Case<Float16Type>([&](
Type) {
os <<
"f16"; })
2854 .Case<FloatTF32Type>([&](
Type) {
os <<
"tf32"; })
2855 .Case<Float32Type>([&](
Type) {
os <<
"f32"; })
2856 .Case<Float64Type>([&](
Type) {
os <<
"f64"; })
2857 .Case<Float80Type>([&](
Type) {
os <<
"f80"; })
2858 .Case<Float128Type>([&](
Type) {
os <<
"f128"; })
2859 .Case<MXI8Type>([&](
Type) {
os <<
"mxi8"; })
2860 .Case([&](IntegerType integerTy) {
2861 if (integerTy.isSigned())
2863 else if (integerTy.isUnsigned())
2865 os <<
'i' << integerTy.getWidth();
2867 .Case([&](FunctionType funcTy) {
2872 if (results.size() == 1 && !llvm::isa<FunctionType>(results[0])) {
2880 .Case([&](VectorType vectorTy) {
2881 auto scalableDims = vectorTy.getScalableDims();
2883 auto vShape = vectorTy.getShape();
2884 unsigned lastDim = vShape.size();
2885 unsigned dimIdx = 0;
2886 for (dimIdx = 0; dimIdx < lastDim; dimIdx++) {
2887 if (!scalableDims.empty() && scalableDims[dimIdx])
2889 os << vShape[dimIdx];
2890 if (!scalableDims.empty() && scalableDims[dimIdx])
2897 .Case([&](RankedTensorType tensorTy) {
2900 if (!tensorTy.getShape().empty())
2904 if (tensorTy.getEncoding()) {
2910 .Case([&](UnrankedTensorType tensorTy) {
2915 .Case([&](MemRefType memrefTy) {
2918 if (!memrefTy.getShape().empty())
2921 MemRefLayoutAttrInterface layout = memrefTy.getLayout();
2922 if (!llvm::isa<AffineMapAttr>(layout) || !layout.isIdentity()) {
2927 if (memrefTy.getMemorySpace()) {
2937 if (memrefTy.getMemorySpace()) {
2943 .Case([&](ComplexType complexTy) {
2948 .Case([&](TupleType tupleTy) {
2951 [&](
Type type) { printType(type); });
2954 .Case<NoneType>([&](
Type) {
os <<
"none"; })
2955 .Case<TokenType>([&](
Type) {
os <<
"token"; })
2956 .Case([&](GraphType graphTy) {
2961 if (results.size() == 1 && !isa<FunctionType, GraphType>(results[0])) {
2980 auto printFilteredAttributesFn = [&](
auto filteredAttrs) {
2983 os <<
" attributes";
2993 if (elidedAttrs.empty())
2994 return printFilteredAttributesFn(attrs);
2997 llvm::SmallDenseSet<StringRef> elidedAttrsSet(elidedAttrs.begin(),
2999 auto filteredAttrs = llvm::make_filter_range(attrs, [&](
NamedAttribute attr) {
3000 return !elidedAttrsSet.contains(attr.
getName().strref());
3002 if (!filteredAttrs.empty())
3003 printFilteredAttributesFn(filteredAttrs);
3010 if (llvm::isa<UnitAttr>(attr.
getValue()))
3021 std::string attrName;
3023 llvm::raw_string_ostream attrNameStr(attrName);
3033 dialect.printAttribute(attr, printer);
3042 std::string typeName;
3044 llvm::raw_string_ostream typeNameStr(typeName);
3054 dialect.printType(type, printer);
3061 llvm::printEscapedString(str,
os);
3066 os <<
"\"0x" << llvm::toHex(str) <<
"\"";
3073 return state.pushCyclicPrinting(opaquePointer);
3089 assert(
impl &&
"expected AsmPrinter::getStream to be overriden");
3090 return impl->getStream();
3094 assert(
impl &&
"expected AsmPrinter::printNewLine to be overriden");
3095 impl->printNewline();
3099 assert(
impl &&
"expected AsmPrinter::increaseIndent to be overriden");
3100 impl->increaseIndent();
3104 assert(
impl &&
"expected AsmPrinter::decreaseIndent to be overriden");
3105 impl->decreaseIndent();
3110 assert(
impl &&
"expected AsmPrinter::printFloat to be overriden");
3115 assert(
impl &&
"expected AsmPrinter::printType to be overriden");
3116 impl->printType(type);
3120 assert(
impl &&
"expected AsmPrinter::printAttribute to be overriden");
3121 impl->printAttribute(attr);
3125 assert(
impl &&
"expected AsmPrinter::printAlias to be overriden");
3126 return impl->printAlias(attr);
3130 assert(
impl &&
"expected AsmPrinter::printAlias to be overriden");
3131 return impl->printAlias(type);
3136 "expected AsmPrinter::printAttributeWithoutType to be overriden");
3141 assert(
impl &&
"expected AsmPrinter::printNamedAttribute to be overriden");
3142 impl->printNamedAttribute(attr);
3146 assert(
impl &&
"expected AsmPrinter::printKeywordOrString to be overriden");
3151 assert(
impl &&
"expected AsmPrinter::printString to be overriden");
3153 printEscapedString(keyword,
getStream());
3158 assert(
impl &&
"expected AsmPrinter::printSymbolName to be overriden");
3163 assert(
impl &&
"expected AsmPrinter::printResourceHandle to be overriden");
3164 impl->printResourceHandle(resource);
3172 return impl->pushCyclicPrinting(opaquePointer);
3189 const char *binopSpelling =
nullptr;
3192 unsigned pos = cast<AffineSymbolExpr>(expr).getPosition();
3194 printValueName(pos,
true);
3200 unsigned pos = cast<AffineDimExpr>(expr).getPosition();
3202 printValueName(pos,
false);
3208 os << cast<AffineConstantExpr>(expr).getValue();
3211 binopSpelling =
" + ";
3214 binopSpelling =
" * ";
3217 binopSpelling =
" floordiv ";
3220 binopSpelling =
" ceildiv ";
3223 binopSpelling =
" mod ";
3227 auto binOp = cast<AffineBinaryOpExpr>(expr);
3237 auto rhsConst = dyn_cast<AffineConstantExpr>(rhsExpr);
3239 rhsConst.getValue() == -1) {
3249 os << binopSpelling;
3263 if (
auto rhs = dyn_cast<AffineBinaryOpExpr>(rhsExpr)) {
3266 if (
auto rrhs = dyn_cast<AffineConstantExpr>(rrhsExpr)) {
3267 if (rrhs.getValue() == -1) {
3284 if (rrhs.getValue() < -1) {
3292 os <<
" * " << -
static_cast<uint64_t
>(rrhs.getValue());
3302 if (
auto rhsConst = dyn_cast<AffineConstantExpr>(rhsExpr)) {
3303 if (rhsConst.getValue() < 0) {
3306 os <<
" - " << -
static_cast<uint64_t
>(rhsConst.getValue());
3324 isEq ?
os <<
" == 0" :
os <<
" >= 0";
3330 for (
int i = 0; i < (int)map.
getNumDims() - 1; ++i)
3331 os <<
'd' << i <<
", ";
3340 os <<
's' << i <<
", ";
3349 [&](
AffineExpr expr) { printAffineExpr(expr); });
3356 for (
unsigned i = 1; i < set.
getNumDims(); ++i)
3357 os <<
'd' << i - 1 <<
", ";
3366 os <<
's' << i <<
", ";
3375 for (
int i = 1; i < numConstraints; ++i) {
3379 if (numConstraints >= 1)
3381 set.
isEq(numConstraints - 1));
3400 void printTopLevelOperation(
Operation *op);
3404 void printFullOpWithIndentAndLoc(
Operation *op);
3410 void printCustomOrGenericOp(
Operation *op)
override;
3412 void printGenericOp(
Operation *op,
bool printOpName)
override;
3415 void printBlockName(
Block *block);
3420 void print(
Block *block,
bool printBlockArgs =
true,
3421 bool printBlockTerminator =
true);
3424 void printValueID(
Value value,
bool printResultNo =
true,
3437 void printOptionalLocationSpecifier(
Location loc)
override {
3438 printTrailingLocation(loc);
3448 bool omitType =
false)
override;
3451 void printOperand(Value value)
override { printValueID(value); }
3452 void printOperand(Value value, raw_ostream &os)
override {
3453 printValueID(value,
true, &os);
3457 void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
3458 ArrayRef<StringRef> elidedAttrs = {})
override {
3459 Impl::printOptionalAttrDict(attrs, elidedAttrs);
3461 void printOptionalAttrDictWithKeyword(
3462 ArrayRef<NamedAttribute> attrs,
3463 ArrayRef<StringRef> elidedAttrs = {})
override {
3464 Impl::printOptionalAttrDict(attrs, elidedAttrs,
3469 void printSuccessor(
Block *successor)
override;
3473 void printSuccessorAndUseList(
Block *successor,
3477 void printRegion(Region ®ion,
bool printEntryBlockArgs,
3478 bool printBlockTerminators,
bool printEmptyBlock)
override;
3484 void shadowRegionArgs(Region ®ion,
ValueRange namesToUse)
override {
3490 void printAffineMapOfSSAIds(AffineMapAttr mapAttr,
3495 void printAffineExprOfSSAIds(AffineExpr expr,
ValueRange dimOperands,
3499 void printUsersComment(Operation *op);
3502 void printUsersComment(BlockArgument arg);
3505 void printValueUsers(Value value);
3509 void printUserIDs(Operation *user,
bool prefixComma =
false);
3514 class ResourceBuilder :
public AsmResourceBuilder {
3520 using PrintFn =
function_ref<void(StringRef, ValueFn, int64_t sizeHint)>;
3522 ResourceBuilder(PrintFn printFn) : printFn(printFn) {}
3523 ~ResourceBuilder()
override =
default;
3525 void buildBool(StringRef key,
bool data)
final {
3527 key, [&](raw_ostream &os) { os << (data ?
"true" :
"false"); },
3531 void buildString(StringRef key, StringRef data)
final {
3534 [&](raw_ostream &os) {
3536 llvm::printEscapedString(data, os);
3542 void buildBlob(StringRef key, ArrayRef<char> data,
3543 uint32_t dataAlignment)
final {
3546 int64_t sizeHint = 2 * int64_t(
sizeof(dataAlignment) + data.size()) + 4;
3549 [&](raw_ostream &os) {
3552 llvm::support::ulittle32_t dataAlignmentLE(dataAlignment);
3555 StringRef(
reinterpret_cast<char *
>(&dataAlignmentLE),
3556 sizeof(dataAlignment)))
3557 << llvm::toHex(StringRef(data.data(), data.size())) <<
"\"";
3567 void printFileMetadataDictionary(Operation *op);
3573 void printResourceFileMetadata(
function_ref<
void()> checkAddMetadataDict,
3581 SmallVector<StringRef> defaultDialectStack{
"builtin"};
3585void OperationPrinter::printTopLevelOperation(Operation *op) {
3587 state.
getAliasState().printNonDeferredAliases(*
this, newLine);
3590 printFullOpWithIndentAndLoc(op);
3597 printFileMetadataDictionary(op);
3600void OperationPrinter::printFileMetadataDictionary(Operation *op) {
3601 bool sawMetadataEntry =
false;
3602 auto checkAddMetadataDict = [&] {
3603 if (!std::exchange(sawMetadataEntry,
true))
3604 os << newLine <<
"{-#" << newLine;
3608 printResourceFileMetadata(checkAddMetadataDict, op);
3611 if (sawMetadataEntry)
3612 os << newLine <<
"#-}" << newLine;
3615void OperationPrinter::printResourceFileMetadata(
3616 function_ref<
void()> checkAddMetadataDict, Operation *op) {
3618 bool hadResource =
false;
3619 bool needResourceComma =
false;
3620 bool needEntryComma =
false;
3621 auto processProvider = [&](StringRef dictName, StringRef name,
auto &provider,
3622 auto &&...providerArgs) {
3623 bool hadEntry =
false;
3624 auto printFn = [&](StringRef key, ResourceBuilder::ValueFn valueFn,
3626 checkAddMetadataDict();
3628 std::string resourceStr;
3629 auto printResourceStr = [&](raw_ostream &os) { os << resourceStr; };
3630 std::optional<uint64_t> charLimit =
3632 if (charLimit.has_value()) {
3634 if (charLimit.value() == 0)
3639 if (sizeHint >= 0 && uint64_t(sizeHint) > charLimit.value())
3642 llvm::raw_string_ostream ss(resourceStr);
3646 if (resourceStr.size() > charLimit.value())
3650 valueFn = printResourceStr;
3654 if (!std::exchange(hadResource,
true)) {
3655 if (needResourceComma)
3656 os <<
"," << newLine;
3657 os <<
" " << dictName <<
"_resources: {" << newLine;
3660 if (!std::exchange(hadEntry,
true)) {
3662 os <<
"," << newLine;
3663 os <<
" " << name <<
": {" << newLine;
3665 os <<
"," << newLine;
3673 ResourceBuilder entryBuilder(printFn);
3674 provider.buildResources(op, providerArgs..., entryBuilder);
3676 needEntryComma |= hadEntry;
3678 os << newLine <<
" }";
3685 StringRef name = interface.getDialect()->getNamespace();
3686 auto it = dialectResources.find(interface.getDialect());
3687 if (it != dialectResources.end())
3688 processProvider(
"dialect", name, interface, it->second);
3690 processProvider(
"dialect", name, interface,
3694 os << newLine <<
" }";
3698 needEntryComma =
false;
3699 needResourceComma = hadResource;
3700 hadResource =
false;
3702 processProvider(
"external", printer.getName(), printer);
3704 os << newLine <<
" }";
3712void OperationPrinter::printRegionArgument(BlockArgument arg,
3713 ArrayRef<NamedAttribute> argAttrs,
3720 printOptionalAttrDict(argAttrs);
3722 printTrailingLocation(arg.
getLoc(),
false);
3725void OperationPrinter::printFullOpWithIndentAndLoc(Operation *op) {
3729 os.indent(currentIndent);
3731 printTrailingLocation(op->
getLoc());
3733 printUsersComment(op);
3736void OperationPrinter::printFullOp(Operation *op) {
3738 auto printResultGroup = [&](
size_t resultNo,
size_t resultCount) {
3739 printValueID(op->
getResult(resultNo),
false);
3740 if (resultCount > 1)
3741 os <<
':' << resultCount;
3745 ArrayRef<int> resultGroups = state.
getSSANameState().getOpResultGroups(op);
3746 if (!resultGroups.empty()) {
3749 interleaveComma(llvm::seq<int>(0, resultGroups.size() - 1), [&](
int i) {
3750 printResultGroup(resultGroups[i],
3751 resultGroups[i + 1] - resultGroups[i]);
3754 printResultGroup(resultGroups.back(), numResults - resultGroups.back());
3757 printResultGroup(0, numResults);
3763 printCustomOrGenericOp(op);
3766void OperationPrinter::printUsersComment(Operation *op) {
3770 printOperationID(op);
3771 }
else if (numResults && op->
use_empty()) {
3773 }
else if (numResults && !op->
use_empty()) {
3776 unsigned usedInNResults = 0;
3777 unsigned usedInNOperations = 0;
3778 SmallPtrSet<Operation *, 1> userSet;
3779 for (Operation *user : op->
getUsers()) {
3780 if (userSet.insert(user).second) {
3781 ++usedInNOperations;
3782 usedInNResults += user->getNumResults();
3787 bool exactlyOneUniqueUse =
3788 usedInNResults <= 1 && usedInNOperations <= 1 && numResults == 1;
3789 os <<
" // " << (exactlyOneUniqueUse ?
"user" :
"users") <<
": ";
3790 bool shouldPrintBrackets = numResults > 1;
3791 auto printOpResult = [&](OpResult opResult) {
3792 if (shouldPrintBrackets)
3794 printValueUsers(opResult);
3795 if (shouldPrintBrackets)
3799 interleaveComma(op->
getResults(), printOpResult);
3803void OperationPrinter::printUsersComment(BlockArgument arg) {
3809 os <<
" is used by ";
3810 printValueUsers(arg);
3815void OperationPrinter::printValueUsers(Value value) {
3821 SmallPtrSet<Operation *, 1> userSet;
3823 if (userSet.insert(user).second)
3824 printUserIDs(user, index);
3828void OperationPrinter::printUserIDs(Operation *user,
bool prefixComma) {
3833 printOperationID(user);
3836 [
this](Value
result) { printValueID(result); });
3840void OperationPrinter::printCustomOrGenericOp(Operation *op) {
3846 opInfo->printAssembly(op, *
this, defaultDialectStack.back());
3851 if (
auto opPrinter = dialect->getOperationPrinter(op)) {
3856 if (name.count(
'.') == 1)
3857 name.consume_front((defaultDialectStack.back() +
".").str());
3861 opPrinter(op, *
this);
3868 printGenericOp(op,
true);
3871void OperationPrinter::printGenericOp(Operation *op,
bool printOpName) {
3875 interleaveComma(op->
getOperands(), [&](Value value) { printValueID(value); });
3882 [&](
Block *successor) { printBlockName(successor); });
3896 interleaveComma(op->
getRegions(), [&](Region ®ion) {
3897 printRegion(region, true,
3910void OperationPrinter::printBlockName(
Block *block) {
3914void OperationPrinter::print(
Block *block,
bool printBlockArgs,
3915 bool printBlockTerminator) {
3917 if (printBlockArgs) {
3918 os.indent(currentIndent);
3919 printBlockName(block);
3924 interleaveComma(block->
getArguments(), [&](BlockArgument arg) {
3927 printType(arg.getType());
3929 printTrailingLocation(arg.getLoc(), false);
3937 os <<
" // block is not in a region!";
3940 os <<
" // no predecessors";
3943 printBlockName(pred);
3947 SmallVector<BlockInfo, 4> predIDs;
3950 llvm::sort(predIDs, [](BlockInfo
lhs, BlockInfo
rhs) {
3951 return lhs.ordering <
rhs.ordering;
3954 os <<
" // " << predIDs.size() <<
" preds: ";
3956 interleaveComma(predIDs, [&](BlockInfo pred) { os << pred.name; });
3961 currentIndent += indentWidth;
3965 os.indent(currentIndent);
3966 printUsersComment(arg);
3970 bool hasTerminator =
3972 auto range = llvm::make_range(
3974 std::prev(block->
end(),
3975 (!hasTerminator || printBlockTerminator) ? 0 : 1));
3976 for (
auto &op : range) {
3977 printFullOpWithIndentAndLoc(&op);
3980 currentIndent -= indentWidth;
3983void OperationPrinter::printValueID(Value value,
bool printResultNo,
3984 raw_ostream *streamOverride)
const {
3986 streamOverride ? *streamOverride : os);
3989void OperationPrinter::printOperationID(Operation *op,
3990 raw_ostream *streamOverride)
const {
3991 state.
getSSANameState().printOperationID(op, streamOverride ? *streamOverride
3995void OperationPrinter::printSuccessor(
Block *successor) {
3996 printBlockName(successor);
3999void OperationPrinter::printSuccessorAndUseList(
Block *successor,
4001 printBlockName(successor);
4002 if (succOperands.empty())
4006 interleaveComma(succOperands,
4007 [
this](Value operand) { printValueID(operand); });
4009 interleaveComma(succOperands,
4014void OperationPrinter::printRegion(Region ®ion,
bool printEntryBlockArgs,
4015 bool printBlockTerminators,
4016 bool printEmptyBlock) {
4021 os <<
"{" << newLine;
4022 if (!region.
empty()) {
4023 llvm::scope_exit restoreDefaultDialect(
4024 [&]() { defaultDialectStack.pop_back(); });
4025 if (
auto iface = dyn_cast<OpAsmOpInterface>(region.
getParentOp()))
4026 defaultDialectStack.push_back(iface.getDefaultDialect());
4028 defaultDialectStack.push_back(
"");
4030 auto *entryBlock = ®ion.
front();
4034 bool shouldAlwaysPrintBlockHeader =
4035 (printEmptyBlock && entryBlock->empty()) ||
4036 (printEntryBlockArgs && entryBlock->getNumArguments() != 0);
4037 print(entryBlock, shouldAlwaysPrintBlockHeader, printBlockTerminators);
4038 for (
auto &
b : llvm::drop_begin(region.
getBlocks(), 1))
4041 os.indent(currentIndent) <<
"}";
4044void OperationPrinter::printAffineMapOfSSAIds(AffineMapAttr mapAttr,
4047 os <<
"<<NULL AFFINE MAP>>";
4050 AffineMap map = mapAttr.getValue();
4052 auto printValueName = [&](
unsigned pos,
bool isSymbol) {
4053 unsigned index = isSymbol ? numDims + pos : pos;
4054 assert(index < operands.size());
4057 printValueID(operands[index]);
4062 interleaveComma(map.
getResults(), [&](AffineExpr expr) {
4063 printAffineExpr(expr, printValueName);
4067void OperationPrinter::printAffineExprOfSSAIds(AffineExpr expr,
4070 auto printValueName = [&](
unsigned pos,
bool isSymbol) {
4072 return printValueID(dimOperands[pos]);
4074 printValueID(symOperands[pos]);
4077 printAffineExpr(expr, printValueName);
4086 os <<
"<<NULL ATTRIBUTE>>";
4091 print(os, state, elideType);
4097 : AttrTypeElision::Never);
4100#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4102 print(llvm::errs());
4103 llvm::errs() <<
"\n";
4109 os <<
"<<NULL ATTRIBUTE>>";
4118 uint64_t posPrior = os.tell();
4120 dialect.printAttribute(*
this, printer);
4121 if (posPrior != os.tell())
4130 os <<
"<<NULL ATTRIBUTE>>";
4140 os <<
"<<NULL TYPE>>";
4151#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4153 print(llvm::errs());
4154 llvm::errs() <<
"\n";
4158 print(llvm::errs());
4159 llvm::errs() <<
"\n";
4163 print(llvm::errs());
4164 llvm::errs() <<
"\n";
4170 os <<
"<<NULL AFFINE EXPR>>";
4177#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4179 print(llvm::errs());
4180 llvm::errs() <<
"\n";
4186 os <<
"<<NULL AFFINE MAP>>";
4201 os <<
"<<NULL VALUE>>";
4206 return op->
print(os, flags);
4209 os <<
"<block argument> of type '" << arg.
getType()
4214 os <<
"<<NULL VALUE>>";
4219 return op->
print(os, state);
4223 os <<
"<block argument> of type '" << arg.
getType()
4232#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4235 llvm::errs() <<
"\n";
4267 if (
auto result = llvm::dyn_cast<OpResult>(*
this)) {
4270 op = llvm::cast<BlockArgument>(*this).getOwner()->
getParentOp();
4272 os <<
"<<UNKNOWN SSA VALUE>>";
4288 OperationPrinter printer(os, state.
getImpl());
4296 printer.printTopLevelOperation(
this);
4298 printer.printFullOpWithIndentAndLoc(
this);
4302#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4305 llvm::errs() <<
"\n";
4311 llvm::errs() <<
"\n";
4317 os <<
"<<UNLINKED BLOCK>>\n";
4328 OperationPrinter(os, state.
getImpl()).print(
this);
4331#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4339 os <<
"<<UNLINKED BLOCK>>\n";
4346 OperationPrinter printer(os, state.
getImpl());
4347 printer.printBlockName(
this);
4362 if (dimensions.empty())
4365 if (dimensions.empty())
4375 <<
"Failed parsing dimension list.";
4386 <<
"Failed parsing dimension list.";
4388 if (shapeArr.empty()) {
4390 <<
"Failed parsing dimension list. Did you mean an empty list? It "
4391 "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.
LLVM_DUMP_METHOD void dump() const
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
LLVM_DUMP_METHOD void dump() 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.
LLVM_DUMP_METHOD void dump() const
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()
LLVM_DUMP_METHOD void dump()
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
LLVM_DUMP_METHOD void dump() 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.
LLVM_DUMP_METHOD void dump() const
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...
LLVM_DUMP_METHOD void dump()
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).
LLVM_DUMP_METHOD void dump() const
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.
LLVM_DUMP_METHOD void dump() const
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...