diff options
| -rw-r--r-- | mlir/include/mlir/IR/op_base.td | 32 | ||||
| -rw-r--r-- | mlir/tools/mlir-op-gen/mlir-op-gen.cpp | 73 |
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() { |

