17#include "llvm/Support/FormatVariadic.h"
18#include "llvm/Support/Path.h"
19#include "llvm/TableGen/CodeGenHelpers.h"
20#include "llvm/TableGen/Record.h"
31 StringRef inputFilename = records.getInputFilename();
34 StringRef nameRef = sys::path::filename(inputFilename);
35 nameRef.consume_back(
".td");
38 std::string uniqueName(tag);
39 for (
char c : nameRef) {
40 if (isAlnum(c) || c ==
'_')
41 uniqueName.push_back(c);
43 uniqueName.append(utohexstr((
unsigned char)c));
49 raw_ostream &os,
const RecordKeeper &records, StringRef tag)
53 emitTypeConstraints();
54 emitAttrConstraints();
55 emitPropConstraints();
56 emitSuccessorConstraints();
57 emitRegionConstraints();
62 collectPatternConstraints(constraints);
72 const auto *it = typeConstraints.find(constraint);
73 assert(it != typeConstraints.end() &&
"expected to find a type constraint");
81 const auto *it = attrConstraints.find(constraint);
82 return it == attrConstraints.end() ? std::optional<StringRef>()
83 : StringRef(it->second);
90 const auto *it = propConstraints.find(constraint);
91 return it == propConstraints.end() ? std::optional<StringRef>()
92 : StringRef(it->second);
97 const auto *it = successorConstraints.find(constraint);
98 assert(it != successorConstraints.end() &&
99 "expected to find a sucessor constraint");
105 const auto *it = regionConstraints.find(constraint);
106 assert(it != regionConstraints.end() &&
107 "expected to find a region constraint");
125static ::llvm::LogicalResult {0}(
126 ::mlir::Operation *op, ::mlir::Type type, ::llvm::StringRef valueKind,
127 unsigned valueIndex) {
129 return op->emitOpError(valueKind) << " #" << valueIndex
130 << " must be {2}, but got " << type;
132 return ::mlir::success();
143static ::llvm::LogicalResult {0}(
144 ::mlir::Attribute attr, ::llvm::StringRef attrName, llvm::function_ref<::mlir::InFlightDiagnostic()> emitError) {{
146 return emitError() << "attribute '" << attrName
147 << "' failed to satisfy constraint: {2}";
148 return ::mlir::success();
150static ::llvm::LogicalResult {0}(
151 ::mlir::Operation *op, ::mlir::Attribute attr, ::llvm::StringRef attrName) {{
152 return {0}(attr, attrName, [op]() {{
153 return op->emitOpError();
162 static ::llvm::LogicalResult {0}(
163 {3} prop, ::llvm::StringRef propName, llvm::function_ref<::mlir::InFlightDiagnostic()> emitError) {{
165 return emitError() << "property '" << propName
166 << "' failed to satisfy constraint: {2}";
167 return ::mlir::success();
169 static ::llvm::LogicalResult {0}(
170 ::mlir::Operation *op, {3} prop, ::llvm::StringRef propName) {{
171 return {0}(prop, propName, [op]() {{
172 return op->emitOpError();
179static ::llvm::LogicalResult {0}(
180 ::mlir::Operation *op, ::mlir::Block *successor,
181 ::llvm::StringRef successorName, unsigned successorIndex) {
183 return op->emitOpError("successor #") << successorIndex << " ('"
184 << successorName << ")' failed to verify constraint: {2}";
186 return ::mlir::success();
193static ::llvm::LogicalResult {0}(
194 ::mlir::Operation *op, ::mlir::Region ®ion, ::llvm::StringRef regionName,
195 unsigned regionIndex) {
197 return op->emitOpError("region #") << regionIndex
198 << (regionName.empty() ? " " : " ('" + regionName + "') ")
199 << "failed to verify constraint: {2}";
201 return ::mlir::success();
213static ::llvm::LogicalResult {0}(
214 ::mlir::PatternRewriter &rewriter, ::mlir::Operation *op, {3},
215 ::llvm::StringRef failureStr) {
217 return rewriter.notifyMatchFailure(op, [&](::mlir::Diagnostic &diag) {
218 diag << failureStr << ": {2}";
221 return ::mlir::success();
225void StaticVerifierFunctionEmitter::emitConstraints(
226 const ConstraintMap &constraints, StringRef selfName,
227 const char *
const codeTemplate) {
230 for (
auto &it : constraints) {
231 os << formatv(codeTemplate, it.second,
232 tgfmt(it.first.getConditionTemplate(), &ctx),
237void StaticVerifierFunctionEmitter::emitTypeConstraints() {
241void StaticVerifierFunctionEmitter::emitAttrConstraints() {
247void StaticVerifierFunctionEmitter::emitPropConstraints() {
250 for (
auto &it : propConstraints) {
251 auto propConstraint = cast<PropConstraint>(it.first);
253 tgfmt(propConstraint.getConditionTemplate(), &ctx),
255 propConstraint.getInterfaceType());
259void StaticVerifierFunctionEmitter::emitSuccessorConstraints() {
263void StaticVerifierFunctionEmitter::emitRegionConstraints() {
270 for (
auto &it : typeConstraints) {
272 tgfmt(it.first.getConditionTemplate(), &ctx),
273 escapeString(it.first.getSummary()),
"::mlir::Type type");
276 for (
auto &it : attrConstraints) {
278 tgfmt(it.first.getConditionTemplate(), &ctx),
280 "::mlir::Attribute attr");
283 for (
auto &it : propConstraints) {
284 PropConstraint propConstraint = cast<PropConstraint>(it.first);
288 if (interfaceType.empty()) {
290 os <<
"template <typename T>";
295 Twine(interfaceType) +
" prop");
310 auto test =
tgfmt(attr.getConditionTemplate(),
313 return !StringRef(test).contains(
"<no-subst-found>");
326 return !StringRef(test).contains(
"<no-subst-found>") && test !=
"true" &&
330std::string StaticVerifierFunctionEmitter::getUniqueName(StringRef kind,
332 return (
"__mlir_ods_local_" + kind +
"_constraint_" + uniqueOutputLabel +
337void StaticVerifierFunctionEmitter::collectConstraint(ConstraintMap &map,
340 auto [it,
inserted] = map.try_emplace(constraint);
342 it->second = getUniqueName(kind, map.size());
349 if (value.hasPredicate())
350 collectConstraint(typeConstraints,
"type", value.constraint);
353 for (
const Record *def : opDefs) {
360 if (!namedAttr.attr.getPredicate().isNull() &&
361 !namedAttr.attr.isDerivedAttr() &&
363 collectConstraint(attrConstraints,
"attr", namedAttr.attr);
367 if (!namedProp.prop.getPredicate().isNull() &&
369 collectConstraint(propConstraints,
"prop", namedProp.prop);
374 if (!successor.constraint.getPredicate().isNull()) {
375 collectConstraint(successorConstraints,
"successor",
376 successor.constraint);
381 if (!region.constraint.getPredicate().isNull())
382 collectConstraint(regionConstraints,
"region", region.constraint);
386void StaticVerifierFunctionEmitter::collectPatternConstraints(
388 for (
auto &leaf : constraints) {
389 assert(leaf.isOperandMatcher() || leaf.isAttrMatcher() ||
390 leaf.isPropMatcher());
391 Constraint constraint = leaf.getAsConstraint();
392 if (leaf.isOperandMatcher())
393 collectConstraint(typeConstraints,
"type", constraint);
394 else if (leaf.isAttrMatcher())
395 collectConstraint(attrConstraints,
"attr", constraint);
396 else if (leaf.isPropMatcher())
397 collectConstraint(propConstraints,
"prop", constraint);
407 raw_string_ostream os(ret);
408 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.
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.
Include the generated interface declarations.