summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mlir/include/mlir/IR/op_base.td32
-rw-r--r--mlir/tools/mlir-op-gen/mlir-op-gen.cpp73
2 files changed, 76 insertions, 29 deletions
diff --git a/mlir/include/mlir/IR/op_base.td b/mlir/include/mlir/IR/op_base.td
index 8d60000f1fc..eb8a4cc8b4c 100644
--- a/mlir/include/mlir/IR/op_base.td
+++ b/mlir/include/mlir/IR/op_base.td
@@ -144,6 +144,15 @@ class Op<string mnemonic, list<OpProperty> props = []> {
// Define the hooks used for building, parsing, printing, verification.
// Custom builder.
+ // If a derived class/def does not override this, then a default builder
+ // is generated, with the following signature:
+ //
+ // static void build(Builder* builder, OperationState* result,
+ // Type resultType0, Type resultType1, ...,
+ // SSAValue* arg0, SSAValue* arg1, ...,
+ // Attribute attr0, Attribute attr1, ...);
+ //
+ // Where the attributes follow the same declaration order as in the op.
code builder = ?;
// Custom parser.
@@ -183,29 +192,10 @@ class Traits<list<string> Traits> {
}
class BinaryOp<string mnemonic, list<OpProperty> props> :
- Op<mnemonic, props>, Operands<[Tensor, Tensor]>, Results<[Tensor]> {
-
- // TODO(jpienaar): To autogen the builder the type of the result needs to be
- // determined from the operands. That would (beyond trivial cases) require
- // type propagation information.
- let builder = [{
- static void build(Builder *builder, OperationState *result, SSAValue *lhs,
- SSAValue *rhs) {
- return impl::buildBinaryOp(builder, result, lhs, rhs);
- }
- }];
-}
+ Op<mnemonic, props>, Operands<[Tensor, Tensor]>, Results<[Tensor]>;
class TernaryOp<string mnemonic, list<OpProperty> props> :
Op<mnemonic, props>, Operands<[Tensor, Tensor, Tensor]>;
class UnaryOp<string mnemonic, list<OpProperty> props> :
- Op<mnemonic, props>, Operands<[Tensor]>, Results<[Tensor]> {
- let builder = [{
- static void build(Builder *builder, OperationState *result,
- SSAValue *arg) {
- result->addOperands({arg});
- result->types.push_back(arg->getType());
- }
- }];
-}
+ Op<mnemonic, props>, Operands<[Tensor]>, Results<[Tensor]>;
diff --git a/mlir/tools/mlir-op-gen/mlir-op-gen.cpp b/mlir/tools/mlir-op-gen/mlir-op-gen.cpp
index bf9fbc5bed8..623abb2b050 100644
--- a/mlir/tools/mlir-op-gen/mlir-op-gen.cpp
+++ b/mlir/tools/mlir-op-gen/mlir-op-gen.cpp
@@ -68,6 +68,16 @@ static inline bool hasStringAttribute(const Record &record,
return isa<CodeInit>(valueInit) || isa<StringInit>(valueInit);
}
+// Returns `fieldName`'s value queried from `record` if `fieldName` is set as
+// an string in record; otherwise, returns `defaultVal`.
+static inline StringRef getAsStringOrDefault(const Record &record,
+ StringRef fieldName,
+ StringRef defaultVal) {
+ return hasStringAttribute(record, fieldName)
+ ? record.getValueAsString(fieldName)
+ : defaultVal;
+}
+
namespace {
// Simple RAII helper for defining ifdef-undef-endif scopes.
class IfDefScope {
@@ -209,17 +219,64 @@ void OpEmitter::emitAttrGetters() {
}
void OpEmitter::emitBuilder() {
- if (!hasStringAttribute(def, "builder"))
- return;
+ if (hasStringAttribute(def, "builder")) {
+ // If a custom builder is given then print that out instead.
+ auto builder = def.getValueAsString("builder");
+ if (!builder.empty()) {
+ os << builder << '\n';
+ return;
+ }
+ }
- // If a custom builder is given then print that out instead.
- auto builder = def.getValueAsString("builder");
- if (!builder.empty()) {
- os << builder << '\n';
- return;
+ // Otherwise, generate a default builder that requires all result type,
+ // operands, and attributes as parameters.
+
+ std::vector<Record *> returnTypes = def.getValueAsListOfDefs("returnTypes");
+ std::vector<Record *> operandTypes = def.getValueAsListOfDefs("operandTypes");
+
+ os << " static void build(Builder* builder, OperationState* result";
+
+ // Emit parameters for all return types
+ for (unsigned i = 0, e = returnTypes.size(); i != e; ++i)
+ os << ", Type returnType" << i;
+
+ // Emit parameters for all operands
+ for (unsigned i = 0, e = operandTypes.size(); i != e; ++i)
+ os << ", SSAValue* arg" << i;
+
+ // Emit parameters for all attributes
+ // TODO(antiagainst): Support default initializer for attributes
+ for (const auto &pair : attrs) {
+ const Record &attr = *pair.second;
+ os << ", " << getAsStringOrDefault(attr, "storageType", "Attribute").trim()
+ << ' ' << pair.first->getName();
+ }
+
+ os << ") {\n";
+
+ // Push all result types to the result
+ if (!returnTypes.empty()) {
+ os << " result->addTypes({returnType0";
+ for (unsigned i = 1, e = returnTypes.size(); i != e; ++i)
+ os << ", returnType" << i;
+ os << "});\n\n";
}
- // TODO(jpienaar): Redo generating builder.
+ // Push all operands to the result
+ if (!operandTypes.empty()) {
+ os << " result->addOperands({arg0";
+ for (unsigned i = 1, e = operandTypes.size(); i != e; ++i)
+ os << ", arg" << i;
+ os << "});\n";
+ }
+
+ // Push all attributes to the result
+ for (const auto &pair : attrs) {
+ StringRef name = pair.first->getName();
+ os << " result->addAttribute(\"" << name << "\", " << name << ");\n";
+ }
+
+ os << " }\n";
}
void OpEmitter::emitCanonicalizationPatterns() {
OpenPOWER on IntegriCloud