| 83 | } |
| 84 | |
| 85 | static void EmitOptionBuilders(const RecordKeeper &record_keeper, |
| 86 | const std::vector<Record *> &defs, |
| 87 | raw_ostream *ostream) { |
| 88 | raw_ostream &os = *ostream; |
| 89 | |
| 90 | const auto attr_type = record_keeper.getClass("Attr"); |
| 91 | for (const auto *def : defs) { |
| 92 | // TFLite ops without options are skipped over. |
| 93 | if (!def->getValueAsBit("hasOptions")) continue; |
| 94 | |
| 95 | StringRef op_name = def->getName().drop_front(4); // Strip 'TFL_' prefix |
| 96 | std::string option_name = GetOperatorOptionName(*def); |
| 97 | std::string tflite_option_name = |
| 98 | option_name == "BasicLSTMOptions" ? "LSTMOptions" : option_name; |
| 99 | |
| 100 | os << "flatbuffers::Offset<tflite::" << tflite_option_name << "> Create" |
| 101 | << option_name << "(mlir::TFL::" << op_name |
| 102 | << " op, flatbuffers::FlatBufferBuilder *fbb) {\n"; |
| 103 | |
| 104 | // Construct all the builder option needed. |
| 105 | SmallVector<std::string, 8> options; |
| 106 | // Add options due to attributes (not-derived). |
| 107 | auto *arg_values = def->getValueAsDag("arguments"); |
| 108 | for (unsigned i = 0, e = arg_values->getNumArgs(); i != e; ++i) { |
| 109 | auto arg = arg_values->getArg(i); |
| 110 | DefInit *arg_def = dyn_cast<DefInit>(arg); |
| 111 | if (!arg_def) continue; |
| 112 | if (arg_def->getDef()->isSubClassOf(attr_type)) { |
| 113 | // This binds the name of the attribute in the TD file with the name |
| 114 | // of the add function of the builder and also with the conversion |
| 115 | // function to convert from the internal representation to the format |
| 116 | // expected by the flatbuffer builder. While this constrains the |
| 117 | // naming of the ops/attributes in the TD file, this also removes the |
| 118 | // need for specifying indirection. This tool is specific to TFLite |
| 119 | // conversion generation and so the simplicity was chosen over the |
| 120 | // flexibility. |
| 121 | StringRef arg_name = arg_values->getArgNameStr(i); |
| 122 | os << formatv( |
| 123 | " auto {0} = Convert{1}ForOptionWriter(op.{0}(), fbb);\n", |
| 124 | arg_name, mlir::tblgen::Attribute(arg_def).getAttrDefName()); |
| 125 | options.push_back(arg_name.str()); |
| 126 | } |
| 127 | } |
| 128 | |
| 129 | // Add options due to derived attributes. |
| 130 | for (const auto &val : def->getValues()) { |
| 131 | if (auto *record = dyn_cast<RecordRecTy>(val.getType())) { |
| 132 | if (record->isSubClassOf(attr_type)) { |
| 133 | if (record->getClasses().size() != 1) { |
| 134 | PrintFatalError( |
| 135 | def->getLoc(), |
| 136 | "unsupported attribute modelling, only single class expected"); |
| 137 | } |
| 138 | os << formatv( |
| 139 | " auto {0} = Convert{1}ForOptionWriter(op.{0}(), fbb);\n", |
| 140 | val.getName(), record->getClasses()[0]->getName()); |
| 141 | options.push_back(std::string(val.getName())); |
| 142 | } |
no test coverage detected