From d4b095b164d23d1be44b9f1f2a729d6b90b1acca Mon Sep 17 00:00:00 2001 From: Jacques Pienaar <jpienaar@google.com> Date: Tue, 16 Oct 2018 08:36:15 -0700 Subject: [PATCH] Make the op specification more declarative wrt properties. Also remove the builder generator as it isn't useful until there are output constraints. PiperOrigin-RevId: 217322623 --- mlir/tools/mlir-op-gen/mlir-op-gen.cpp | 103 +++++++------------------ 1 file changed, 30 insertions(+), 73 deletions(-) diff --git a/mlir/tools/mlir-op-gen/mlir-op-gen.cpp b/mlir/tools/mlir-op-gen/mlir-op-gen.cpp index 82bb9dfa8610..540e9f9e4db8 100644 --- a/mlir/tools/mlir-op-gen/mlir-op-gen.cpp +++ b/mlir/tools/mlir-op-gen/mlir-op-gen.cpp @@ -106,10 +106,7 @@ void OpEmitter::emit(const Record &def, raw_ostream &os) { // Query the returned type and operands types of the op. emitter.getAttributes(); - // Query the C++ class from which this op should derived. - StringRef baseClass = def.getValueAsString("baseClass"); - os << "\nclass " << def.getName() << " : public " << baseClass << "<" - << def.getName(); + os << "\nclass " << def.getName() << " : public Op<" << def.getName(); emitter.emitTraits(); os << "> {\npublic:\n"; @@ -125,7 +122,7 @@ void OpEmitter::emit(const Record &def, raw_ostream &os) { os << "private:\n friend class ::mlir::Operation;\n"; os << " explicit " << def.getName() - << "(const Operation* state) : " << baseClass << "(state) {}\n"; + << "(const Operation* state) : Op(state) {}\n"; os << "};\n"; } @@ -158,55 +155,18 @@ void OpEmitter::emitAttrGetters() { void OpEmitter::emitBuilder() { // If a custom builder is given then print that out instead. - auto builder = def.getValueAsString("builder"); + auto valueInit = def.getValueInit("builder"); + CodeInit *codeInit = dyn_cast<CodeInit>(valueInit); + if (!codeInit) + return; + + auto builder = codeInit->getValue(); if (!builder.empty()) { os << builder << '\n'; return; } - os << " static void build(Builder *builder, OperationState *result"; - const std::vector<Record *> &operandTypes = - def.getValueAsListOfDefs("operandTypes"); - - // Label the operands as simply arg_i. - for (int i = 0, e = operandTypes.size(); i != e; ++i) - os << ", SSAValue *arg_" << i; - - // Add a parameter for every attribute. - for (const auto &attr : attrs) { - os << ", " << attr.second->getValueAsString("PrimitiveType") << " " - << attr.second->getValueAsString("name"); - } - os << ") {\n"; - - // Build the OperationState. - - // Add the operands. - if (!operandTypes.empty()) { - os << " result->addOperands({"; - for (int i = 0, e = operandTypes.size(); i != e; ++i) { - if (i) - os << ", "; - os << "arg_" << i; - } - os << "});\n"; - } - - // Set the return type. - // TODO(jpienaar): Perform type propagation here. - if (isa<DefInit>(def.getValueInit("returnType"))) { - os << " result->types.push_back(" << def.getName() - << "::ReturnType(*builder));\n"; - } - - // Add any attributes. - for (const auto &attr : attrs) { - os << " result->addAttribute(\"" << attr.second->getValueAsString("name") - << "\", builder->get" << attr.second->getValueAsString("AttrType") << "(" - << attr.second->getValueAsString("name") << "));\n"; - } - - os << " }\n"; + // TODO(jpienaar): Redo generating builder. } void OpEmitter::emitParser() { @@ -232,12 +192,6 @@ void OpEmitter::emitPrinter() { } void OpEmitter::emitVerifier() { - auto valueInit = def.getValueInit("verifier"); - CodeInit *codeInit = dyn_cast<CodeInit>(valueInit); - if (!codeInit) - return; - - auto verifier = codeInit->getValue(); os << " bool verify() const {\n"; // Verify the attributes have the correct type. @@ -246,14 +200,16 @@ void OpEmitter::emitVerifier() { os << " if (!dyn_cast_or_null<" << attr.second->getValueAsString("AttrType") << ">(this->getAttr(\"" << name << "\"))) return emitOpError(\"requires " - << attr.second->getValueAsString("PrimitiveType") << " attribute '" - << name << "'\");\n"; + << attr.second->getValueAsString("PrimitiveType").trim() + << " attribute '" << name << "'\");\n"; } - if (verifier.empty()) + auto valueInit = def.getValueInit("verifier"); + CodeInit *codeInit = dyn_cast<CodeInit>(valueInit); + if (!codeInit || codeInit->getValue().empty()) os << " return false;\n"; else - os << " " << verifier << "\n"; + os << " " << codeInit->getValue() << "\n"; os << " }\n"; } @@ -287,24 +243,25 @@ void OpEmitter::emitTraits() { break; } - // Add op property traits. - if (def.getValueAsBit("isCommutative")) - os << ", OpTrait::IsCommutative"; - if (def.getValueAsBit("hasNoSideEffect")) - os << ", OpTrait::HasNoSideEffect"; + // Add op property traits. These match the propoerties specified in the table + // with the OperationProperty specified in OperationSupport.h. + for (Record *property : def.getValueAsListOfDefs("properties")) { + if (property->getName() == "Commutative") { + os << ", OpTrait::IsCommutative"; + } else if (property->getName() == "NoSideEffect") { + os << ", OpTrait::HasNoSideEffect"; + } + } // Add explicitly added traits. // TODO(jpienaar): Improve Trait specification to make adding them in the // tblgen file better. - const auto traitType = def.getRecords().getClass("Trait"); - for (const auto &val : def.getValues()) { - if (DefInit *defInit = dyn_cast<DefInit>(val.getValue())) { - auto attr = defInit->getDef(); - if (attr->isSubClassOf(traitType)) { - os << ", OpTrait::" << attr->getValueAsString("trait").trim(); - } - } - } + auto *recordVal = def.getValue("traits"); + if (!recordVal || !recordVal->getValue()) + return; + auto traitList = dyn_cast<ListInit>(recordVal->getValue())->getValues(); + for (Init *trait : traitList) + os << ", OpTrait::" << StringRef(trait->getAsUnquotedString()).trim(); } // Emits the opcode enum and op classes.