| 218 | InterpreterBuilder::~InterpreterBuilder() {} |
| 219 | |
| 220 | TfLiteStatus InterpreterBuilder::BuildLocalIndexToRegistrationMapping() { |
| 221 | TfLiteStatus status = kTfLiteOk; |
| 222 | // Reset state. |
| 223 | flatbuffer_op_index_to_registration_.clear(); |
| 224 | unresolved_custom_ops_.clear(); |
| 225 | |
| 226 | auto opcodes = model_->operator_codes(); |
| 227 | if (!opcodes) { |
| 228 | return status; |
| 229 | } |
| 230 | int num_custom_ops = 0; |
| 231 | for (const OperatorCode* opcode : *opcodes) { |
| 232 | if (opcode->builtin_code() == BuiltinOperator_CUSTOM) { |
| 233 | num_custom_ops++; |
| 234 | } |
| 235 | } |
| 236 | unresolved_custom_ops_.reserve(num_custom_ops); |
| 237 | for (const OperatorCode* opcode : *opcodes) { |
| 238 | const TfLiteRegistration* registration = nullptr; |
| 239 | status = GetRegistrationFromOpCode(opcode, op_resolver_, error_reporter_, |
| 240 | ®istration); |
| 241 | if (status != kTfLiteOk) { |
| 242 | if (opcode->builtin_code() != BuiltinOperator_CUSTOM) { |
| 243 | return status; |
| 244 | } |
| 245 | // If it's an unresolved custom op, allow it for now. It might be resolved |
| 246 | // by a delegate later. |
| 247 | if (!opcode->custom_code()) { |
| 248 | error_reporter_->Report( |
| 249 | "Operator with CUSTOM builtin_code has no custom_code.\n"); |
| 250 | return status; |
| 251 | } |
| 252 | const auto* op_name = opcode->custom_code()->c_str(); |
| 253 | TfLiteRegistration unresolved_op{nullptr, |
| 254 | nullptr, |
| 255 | nullptr, |
| 256 | /*invoke*/ &UnresolvedOpInvoke, |
| 257 | nullptr, |
| 258 | BuiltinOperator_CUSTOM, |
| 259 | op_name, |
| 260 | 1}; |
| 261 | unresolved_custom_ops_.push_back(unresolved_op); |
| 262 | registration = &unresolved_custom_ops_.back(); |
| 263 | has_flex_op_ |= IsFlexOp(op_name); |
| 264 | status = kTfLiteOk; |
| 265 | } |
| 266 | flatbuffer_op_index_to_registration_.push_back(registration); |
| 267 | } |
| 268 | return status; |
| 269 | } |
| 270 | |
| 271 | namespace { |
| 272 | template <class T> |