// The list of results of the op. Default to 0 results.
dag results = (outs);
+ // How many regions this op has.
+ // TODO(b/133479568): Enhance to support advanced region usage cases
+ int numRegions = 0;
+
// Attribute getters can be added to the op by adding an Attr member
// with the name and type of the attribute. E.g., adding int attribute
// with name "value" and type "i32":
// requiring the raw MLIR trait here.
bool hasTrait(llvm::StringRef trait) const;
+ // Returns the number of regions.
+ int getNumRegions() const;
+
// Trait.
using const_trait_iterator = const OpTrait *;
const_trait_iterator trait_begin() const;
// The traits of the op.
SmallVector<OpTrait, 4> traits;
+ // The number of regions of this op.
+ int numRegions = 0;
+
// The number of native attributes stored in the leading positions of
// `attributes`.
int numNativeAttributes;
return false;
}
+int tblgen::Operator::getNumRegions() const { return numRegions; }
+
auto tblgen::Operator::trait_begin() const -> const_trait_iterator {
return traits.begin();
}
traits.reserve(traitListInit->size());
for (auto traitInit : *traitListInit)
traits.push_back(OpTrait::create(traitInit));
+
+ // Handle regions
+ numRegions = def.getValueAsInt("numRegions");
+ if (numRegions < 0)
+ PrintFatalError(def.getLoc(), "numRegions cannot be negative");
}
ArrayRef<llvm::SMLoc> tblgen::Operator::getLoc() const { return def.getLoc(); }
--- /dev/null
+// RUN: mlir-test-opt %s -split-input-file -verify | FileCheck %s
+
+func @correct_number_of_regions() {
+ // CHECK: test.two_region_op
+ "test.two_region_op"()(
+ {"work"() : () -> ()},
+ {"work"() : () -> ()}
+ ) : () -> ()
+ return
+}
+
+// -----
+
+func @missingk_regions() {
+ // expected-error@+1 {{op has incorrect number of regions: expected 2 but found 1}}
+ "test.two_region_op"()(
+ {"work"() : () -> ()}
+ ) : () -> ()
+ return
+}
+
+// -----
+
+func @extra_regions() {
+ // expected-error@+1 {{op has incorrect number of regions: expected 2 but found 3}}
+ "test.two_region_op"()(
+ {"work"() : () -> ()},
+ {"work"() : () -> ()},
+ {"work"() : () -> ()}
+ ) : () -> ()
+ return
+}
def : Pat<(OpG $input), (OpB $input, ConstantAttr<I32Attr, "20">:$attr)>;
def : Pat<(OpG (OpG $input)), (OpB $input, ConstantAttr<I32Attr, "34">:$attr)>;
+//===----------------------------------------------------------------------===//
+// Test op regions
+//===----------------------------------------------------------------------===//
+
+def TwoRegionOp : TEST_Op<"two_region_op", []> {
+ let numRegions = 2;
+}
+
#endif // TEST_OPS
}
}
}
+
+ // Create the correct number of regions
+ if (int numRegions = op.getNumRegions()) {
+ for (int i = 0; i < numRegions; ++i)
+ m.body() << " (void)" << builderOpState << "->addRegion();\n";
+ }
}
void OpEmitter::genBuilder() {
<< " " << builderOpState
<< "->addAttribute(pair.first, pair.second);\n";
+ // Create the correct number of regions
+ if (int numRegions = op.getNumRegions()) {
+ for (int i = 0; i < numRegions; ++i)
+ m.body() << " (void)" << builderOpState << "->addRegion();\n";
+ }
+
// 3. Deduced result types
bool useOperandType = op.hasTrait("SameOperandsAndResultType");
auto valueInit = def.getValueInit("verifier");
CodeInit *codeInit = dyn_cast<CodeInit>(valueInit);
bool hasCustomVerify = codeInit && !codeInit->getValue().empty();
- if (!hasCustomVerify && op.getNumArgs() == 0 && op.getNumResults() == 0 &&
- op.getNumPredOpTraits() == 0)
- return;
auto &method = opClass.newMethod("LogicalResult", "verify", /*params=*/"");
auto &body = method.body();
}
}
+ // Verify this op has the correct number of regions
+ body << formatv(
+ " if (this->getOperation()->getNumRegions() != {0}) \n return "
+ "emitOpError(\"has incorrect number of regions: expected {0} but found "
+ "\") << this->getOperation()->getNumRegions();\n",
+ op.getNumRegions());
+
if (hasCustomVerify)
body << codeInit->getValue() << "\n";
else