24#include "llvm/ADT/StringExtras.h"
25#include "llvm/ADT/StringRef.h"
26#include "llvm/Support/FormatVariadic.h"
27#include "llvm/Support/Path.h"
28#include "llvm/Support/raw_ostream.h"
29#include "llvm/TableGen/CodeGenHelpers.h"
30#include "llvm/TableGen/Error.h"
31#include "llvm/TableGen/Record.h"
45 StringRef inputFilename = records.getInputFilename();
48 StringRef nameRef = sys::path::filename(inputFilename);
49 nameRef.consume_back(
".td");
52 std::string uniqueName(tag);
53 for (
char c : nameRef) {
54 if (isAlnum(c) || c ==
'_')
55 uniqueName.push_back(c);
57 uniqueName.append(utohexstr((
unsigned char)c));
63 raw_ostream &os,
const RecordKeeper &records, StringRef tag)
67 emitTypeConstraints();
68 emitAttrConstraints();
69 emitPropConstraints();
70 emitSuccessorConstraints();
71 emitRegionConstraints();
76 collectPatternConstraints(constraints);
86 const auto *it = typeConstraints.find(constraint);
87 assert(it != typeConstraints.end() &&
"expected to find a type constraint");
95 const auto *it = attrConstraints.find(constraint);
96 return it == attrConstraints.end() ? std::optional<StringRef>()
97 : StringRef(it->second);
104 const auto *it = propConstraints.find(constraint);
105 return it == propConstraints.end() ? std::optional<StringRef>()
106 : StringRef(it->second);
111 const auto *it = successorConstraints.find(constraint);
112 assert(it != successorConstraints.end() &&
113 "expected to find a sucessor constraint");
119 const auto *it = regionConstraints.find(constraint);
120 assert(it != regionConstraints.end() &&
121 "expected to find a region constraint");
135 raw_string_ostream os(
result);
138 StringRef msg = msgStr;
141 auto split = msg.split(
"{{");
143 if (split.second.empty()) {
153 while (!msg.empty()) {
154 split = msg.split(
"}}");
155 StringRef var = split.first;
156 StringRef rest = split.second;
158 os <<
" << " <<
tgfmt(var, &ctx);
168 split = rest.split(
"{{");
186static ::llvm::LogicalResult {0}(
187 ::mlir::Operation *op, ::mlir::Type type, ::llvm::StringRef valueKind,
188 unsigned valueIndex) {
190 return op->emitOpError(valueKind) << " #" << valueIndex
191 << " must be {2}, but got " << type;
193 return ::mlir::success();
204static ::llvm::LogicalResult {0}(
205 ::mlir::Attribute attr, ::llvm::StringRef attrName, llvm::function_ref<::mlir::InFlightDiagnostic()> emitError) {{
207 return emitError() << "attribute '" << attrName
208 << "' failed to satisfy constraint: {2}";
209 return ::mlir::success();
211static ::llvm::LogicalResult {0}(
212 ::mlir::Operation *op, ::mlir::Attribute attr, ::llvm::StringRef attrName) {{
213 return {0}(attr, attrName, [op]() {{
214 return op->emitOpError();
223 static ::llvm::LogicalResult {0}(
224 {3} prop, ::llvm::StringRef propName, llvm::function_ref<::mlir::InFlightDiagnostic()> emitError) {{
226 return emitError() << "property '" << propName
227 << "' failed to satisfy constraint: {2}";
228 return ::mlir::success();
230 static ::llvm::LogicalResult {0}(
231 ::mlir::Operation *op, {3} prop, ::llvm::StringRef propName) {{
232 return {0}(prop, propName, [op]() {{
233 return op->emitOpError();
240static ::llvm::LogicalResult {0}(
241 ::mlir::Operation *op, ::mlir::Block *successor,
242 ::llvm::StringRef successorName, unsigned successorIndex) {
244 return op->emitOpError("successor #") << successorIndex << " ('"
245 << successorName << "') failed to verify constraint: {2}";
247 return ::mlir::success();
254static ::llvm::LogicalResult {0}(
255 ::mlir::Operation *op, ::mlir::Region ®ion, ::llvm::StringRef regionName,
256 unsigned regionIndex) {
258 return op->emitOpError("region #") << regionIndex
259 << (regionName.empty() ? " " : " ('" + regionName + "') ")
260 << "failed to verify constraint: {2}";
262 return ::mlir::success();
274static ::llvm::LogicalResult {0}(
275 ::mlir::PatternRewriter &rewriter, ::mlir::Operation *op, {3},
276 ::llvm::StringRef failureStr) {
278 return rewriter.notifyMatchFailure(op, [&](::mlir::Diagnostic &diag) {
279 diag << failureStr << ": {2}";
282 return ::mlir::success();
286void StaticVerifierFunctionEmitter::emitConstraints(
287 const ConstraintMap &constraints, StringRef selfName,
292 for (
auto &it : constraints) {
293 os << formatv(codeTemplate, it.second,
294 tgfmt(it.first.getConditionTemplate(), &ctx),
298void StaticVerifierFunctionEmitter::emitTypeConstraints() {
303void StaticVerifierFunctionEmitter::emitAttrConstraints() {
310void StaticVerifierFunctionEmitter::emitPropConstraints() {
313 for (
auto &it : propConstraints) {
314 auto propConstraint = cast<PropConstraint>(it.first);
316 tgfmt(propConstraint.getConditionTemplate(), &ctx),
318 propConstraint.getInterfaceType());
322void StaticVerifierFunctionEmitter::emitSuccessorConstraints() {
327void StaticVerifierFunctionEmitter::emitRegionConstraints() {
335 for (
auto &it : typeConstraints) {
337 tgfmt(it.first.getConditionTemplate(), &ctx),
339 "::mlir::Type type");
342 for (
auto &it : attrConstraints) {
344 tgfmt(it.first.getConditionTemplate(), &ctx),
346 "::mlir::Attribute attr");
349 for (
auto &it : propConstraints) {
350 PropConstraint propConstraint = cast<PropConstraint>(it.first);
354 if (interfaceType.empty()) {
356 os <<
"template <typename T>";
361 Twine(interfaceType) +
" prop");
376 auto test =
tgfmt(attr.getConditionTemplate(),
379 return !StringRef(test).contains(
"<no-subst-found>");
392 return !StringRef(test).contains(
"<no-subst-found>") && test !=
"true" &&
396std::string StaticVerifierFunctionEmitter::getUniqueName(StringRef kind,
398 return (
"__mlir_ods_local_" + kind +
"_constraint_" + uniqueOutputLabel +
403void StaticVerifierFunctionEmitter::collectConstraint(ConstraintMap &map,
406 auto [it,
inserted] = map.try_emplace(constraint);
408 it->second = getUniqueName(kind, map.size());
415 if (value.hasPredicate())
416 collectConstraint(typeConstraints,
"type", value.constraint);
419 for (
const Record *def : opDefs) {
426 if (!namedAttr.attr.getPredicate().isNull() &&
427 !namedAttr.attr.isDerivedAttr() &&
429 collectConstraint(attrConstraints,
"attr", namedAttr.attr);
433 if (!namedProp.prop.getPredicate().isNull() &&
435 collectConstraint(propConstraints,
"prop", namedProp.prop);
440 if (!successor.constraint.getPredicate().isNull()) {
441 collectConstraint(successorConstraints,
"successor",
442 successor.constraint);
447 if (!region.constraint.getPredicate().isNull())
448 collectConstraint(regionConstraints,
"region", region.constraint);
452void StaticVerifierFunctionEmitter::collectPatternConstraints(
454 for (
auto &leaf : constraints) {
455 assert(leaf.isOperandMatcher() || leaf.isAttrMatcher() ||
456 leaf.isPropMatcher());
457 Constraint constraint = leaf.getAsConstraint();
458 if (leaf.isOperandMatcher())
459 collectConstraint(typeConstraints,
"type", constraint);
460 else if (leaf.isAttrMatcher())
461 collectConstraint(attrConstraints,
"attr", constraint);
462 else if (leaf.isPropMatcher())
463 collectConstraint(propConstraints,
"prop", constraint);
473 raw_string_ostream os(ret);
474 os.write_escaped(value);
static const char *const successorConstraintCode
Code for a successor constraint.
static const char *const patternConstraintCode
Code for a pattern type or attribute constraint.
static const char *const regionConstraintCode
Code for a region constraint.
static const char *const typeConstraintCode
Code templates for emitting type, attribute, successor, and region constraints.
static std::string getUniqueOutputLabel(const RecordKeeper &records, StringRef tag)
Generate a unique label based on the current file name to prevent name collisions if multiple generat...
static const char *const propConstraintCode
Code for a property constraint.
static bool canUniqueAttrConstraint(Attribute attr)
An attribute constraint that references anything other than itself and the current op cannot be gener...
static bool canUniquePropConstraint(Property prop)
A property constraint that references anything other than itself and the current op cannot be generic...
static const char *const attrConstraintCode
Code for an attribute constraint.
*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
Attributes are known-constant values of operations.
StringRef getSummary() const
std::string getConditionTemplate() const
Format context containing substitutions for special placeholders.
FmtContext & withBuilder(Twine subst)
FmtContext & withSelf(Twine subst)
FmtContext & addSubst(StringRef placeholder, const Twine &subst)
Wrapper class that contains a MLIR op's information (e.g., operands, attributes) defined in TableGen ...
llvm::iterator_range< const_region_iterator > getRegions() const
const_value_range getResults() const
const_value_range getOperands() const
llvm::iterator_range< const_property_iterator > getProperties() const
llvm::iterator_range< const_attribute_iterator > getAttributes() const
llvm::iterator_range< const_value_iterator > const_value_range
llvm::iterator_range< const_successor_iterator > getSuccessors() const
StringRef getInterfaceType() const
StringRef getInterfaceType() const
StringRef getRegionConstraintFn(const Constraint &constraint) const
Get the name of the static function used for the given region constraint.
void emitPatternConstraints(const ArrayRef< DagLeaf > constraints)
Unique all compatible type and attribute constraints from a pattern file and emit them at the top of ...
std::optional< StringRef > getAttrConstraintFn(const Constraint &constraint) const
Get the name of the static function used for the given attribute constraint.
std::optional< StringRef > getPropConstraintFn(const Constraint &constraint) const
Get the name of the static function used for the given property constraint.
StaticVerifierFunctionEmitter(raw_ostream &os, const llvm::RecordKeeper &records, StringRef tag="")
Create a constraint uniquer with a unique prefix derived from the record keeper with an optional tag.
void collectOpConstraints(ArrayRef< const llvm::Record * > opDefs)
Collect and unique all the constraints used by operations.
StringRef getTypeConstraintFn(const Constraint &constraint) const
Get the name of the static function used for the given type constraint.
void emitOpConstraints()
Collect and unique all compatible type, attribute, successor, and region constraints from the operati...
StringRef getSuccessorConstraintFn(const Constraint &constraint) const
Get the name of the static function used for the given successor constraint.
The OpAsmOpInterface, see OpAsmInterface.td for more details.
std::string buildErrorStreamingString(StringRef message, const FmtContext &ctx, ErrorStreamType errorStreamType=ErrorStreamType::InString)
Helper to generate a C++ streaming error message from a given message.
std::string escapeString(StringRef value)
Escape a string using C++ encoding. E.g. foo"bar -> foo\x22bar.
ErrorStreamType
This class represents how an error stream string being constructed will be consumed.
auto tgfmt(StringRef fmt, const FmtContext *ctx, Ts &&...vals) -> FmtObject< decltype(std::make_tuple(llvm::support::detail::FormatFunctor< Ts >(std::forward< Ts >(vals))...))>
Formats text by substituting placeholders in format string with replacement parameters.
Include the generated interface declarations.