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);
163 split = rest.split(
"{{");
164 if (split.second.empty() &&
168 os <<
" << (\"" << split.first;
170 os <<
" << \"" << split.first;
188static ::llvm::LogicalResult {0}(
189 ::mlir::Operation *op, ::mlir::Type type, ::llvm::StringRef valueKind,
190 unsigned valueIndex) {
192 return op->emitOpError(valueKind) << " #" << valueIndex
193 << " must be {2}, but got " << type;
195 return ::mlir::success();
206static ::llvm::LogicalResult {0}(
207 ::mlir::Attribute attr, ::llvm::StringRef attrName, llvm::function_ref<::mlir::InFlightDiagnostic()> emitError) {{
209 return emitError() << "attribute '" << attrName
210 << "' failed to satisfy constraint: {2}";
211 return ::mlir::success();
213static ::llvm::LogicalResult {0}(
214 ::mlir::Operation *op, ::mlir::Attribute attr, ::llvm::StringRef attrName) {{
215 return {0}(attr, attrName, [op]() {{
216 return op->emitOpError();
225 static ::llvm::LogicalResult {0}(
226 {3} prop, ::llvm::StringRef propName, llvm::function_ref<::mlir::InFlightDiagnostic()> emitError) {{
228 return emitError() << "property '" << propName
229 << "' failed to satisfy constraint: {2}";
230 return ::mlir::success();
232 static ::llvm::LogicalResult {0}(
233 ::mlir::Operation *op, {3} prop, ::llvm::StringRef propName) {{
234 return {0}(prop, propName, [op]() {{
235 return op->emitOpError();
242static ::llvm::LogicalResult {0}(
243 ::mlir::Operation *op, ::mlir::Block *successor,
244 ::llvm::StringRef successorName, unsigned successorIndex) {
246 return op->emitOpError("successor #") << successorIndex << " ('"
247 << successorName << ")' failed to verify constraint: {2}";
249 return ::mlir::success();
256static ::llvm::LogicalResult {0}(
257 ::mlir::Operation *op, ::mlir::Region ®ion, ::llvm::StringRef regionName,
258 unsigned regionIndex) {
260 return op->emitOpError("region #") << regionIndex
261 << (regionName.empty() ? " " : " ('" + regionName + "') ")
262 << "failed to verify constraint: {2}";
264 return ::mlir::success();
276static ::llvm::LogicalResult {0}(
277 ::mlir::PatternRewriter &rewriter, ::mlir::Operation *op, {3},
278 ::llvm::StringRef failureStr) {
280 return rewriter.notifyMatchFailure(op, [&](::mlir::Diagnostic &diag) {
281 diag << failureStr << ": {2}";
284 return ::mlir::success();
288void StaticVerifierFunctionEmitter::emitConstraints(
289 const ConstraintMap &constraints, StringRef selfName,
294 for (
auto &it : constraints) {
295 os << formatv(codeTemplate, it.second,
296 tgfmt(it.first.getConditionTemplate(), &ctx),
300void StaticVerifierFunctionEmitter::emitTypeConstraints() {
305void StaticVerifierFunctionEmitter::emitAttrConstraints() {
312void StaticVerifierFunctionEmitter::emitPropConstraints() {
315 for (
auto &it : propConstraints) {
316 auto propConstraint = cast<PropConstraint>(it.first);
318 tgfmt(propConstraint.getConditionTemplate(), &ctx),
320 propConstraint.getInterfaceType());
324void StaticVerifierFunctionEmitter::emitSuccessorConstraints() {
329void StaticVerifierFunctionEmitter::emitRegionConstraints() {
337 for (
auto &it : typeConstraints) {
339 tgfmt(it.first.getConditionTemplate(), &ctx),
341 "::mlir::Type type");
344 for (
auto &it : attrConstraints) {
346 tgfmt(it.first.getConditionTemplate(), &ctx),
348 "::mlir::Attribute attr");
351 for (
auto &it : propConstraints) {
352 PropConstraint propConstraint = cast<PropConstraint>(it.first);
356 if (interfaceType.empty()) {
358 os <<
"template <typename T>";
363 Twine(interfaceType) +
" prop");
378 auto test =
tgfmt(attr.getConditionTemplate(),
381 return !StringRef(test).contains(
"<no-subst-found>");
394 return !StringRef(test).contains(
"<no-subst-found>") && test !=
"true" &&
398std::string StaticVerifierFunctionEmitter::getUniqueName(StringRef kind,
400 return (
"__mlir_ods_local_" + kind +
"_constraint_" + uniqueOutputLabel +
405void StaticVerifierFunctionEmitter::collectConstraint(ConstraintMap &map,
408 auto [it,
inserted] = map.try_emplace(constraint);
410 it->second = getUniqueName(kind, map.size());
417 if (value.hasPredicate())
418 collectConstraint(typeConstraints,
"type", value.constraint);
421 for (
const Record *def : opDefs) {
428 if (!namedAttr.attr.getPredicate().isNull() &&
429 !namedAttr.attr.isDerivedAttr() &&
431 collectConstraint(attrConstraints,
"attr", namedAttr.attr);
435 if (!namedProp.prop.getPredicate().isNull() &&
437 collectConstraint(propConstraints,
"prop", namedProp.prop);
442 if (!successor.constraint.getPredicate().isNull()) {
443 collectConstraint(successorConstraints,
"successor",
444 successor.constraint);
449 if (!region.constraint.getPredicate().isNull())
450 collectConstraint(regionConstraints,
"region", region.constraint);
454void StaticVerifierFunctionEmitter::collectPatternConstraints(
456 for (
auto &leaf : constraints) {
457 assert(leaf.isOperandMatcher() || leaf.isAttrMatcher() ||
458 leaf.isPropMatcher());
459 Constraint constraint = leaf.getAsConstraint();
460 if (leaf.isOperandMatcher())
461 collectConstraint(typeConstraints,
"type", constraint);
462 else if (leaf.isAttrMatcher())
463 collectConstraint(attrConstraints,
"attr", constraint);
464 else if (leaf.isPropMatcher())
465 collectConstraint(propConstraints,
"prop", constraint);
475 raw_string_ostream os(ret);
476 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.
auto tgfmt(StringRef fmt, const FmtContext *ctx, Ts &&...vals) -> FmtObject< decltype(std::make_tuple(llvm::support::detail::build_format_adapter(std::forward< Ts >(vals))...))>
Formats text by substituting placeholders in format string with replacement parameters.
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.
Include the generated interface declarations.