| 583 | } |
| 584 | |
| 585 | Optional<BufferOffset<tflite::Tensor>> Translator::BuildTensor( |
| 586 | Value value, const std::string& name, unsigned buffer_idx) { |
| 587 | auto type = value.getType().cast<TensorType>(); |
| 588 | |
| 589 | // TFLite requires tensor shape only for the inputs and constants. |
| 590 | // However, we output all known shapes for better round-tripping |
| 591 | auto check_shape = |
| 592 | [&](llvm::ArrayRef<int64_t> shape_ref) -> mlir::LogicalResult { |
| 593 | auto is_out_of_range = [](int64_t dim) { |
| 594 | return dim > std::numeric_limits<int32_t>::max(); |
| 595 | }; |
| 596 | |
| 597 | if (std::any_of(shape_ref.begin(), shape_ref.end(), is_out_of_range)) |
| 598 | return mlir::emitError( |
| 599 | value.getLoc(), |
| 600 | "result shape dimensions out of 32 bit int type range"); |
| 601 | |
| 602 | return mlir::success(); |
| 603 | }; |
| 604 | |
| 605 | std::vector<int32_t> shape; |
| 606 | std::vector<int32_t> shape_signature; |
| 607 | if (type.hasStaticShape()) { |
| 608 | llvm::ArrayRef<int64_t> shape_ref = type.getShape(); |
| 609 | if (mlir::failed(check_shape(shape_ref))) return llvm::None; |
| 610 | |
| 611 | shape = std::vector<int32_t>(shape_ref.begin(), shape_ref.end()); |
| 612 | } else if (auto* inst = value.getDefiningOp()) { |
| 613 | if (IsConst(inst)) { |
| 614 | // Const op can have a result of dynamic shaped type (e.g. due to constant |
| 615 | // folding), but we can still derive the shape of a constant tensor for |
| 616 | // its attribute type. |
| 617 | mlir::Attribute tensor_attr = inst->getAttr("value"); |
| 618 | llvm::ArrayRef<int64_t> shape_ref = |
| 619 | tensor_attr.getType().cast<TensorType>().getShape(); |
| 620 | if (mlir::failed(check_shape(shape_ref))) return llvm::None; |
| 621 | |
| 622 | shape = std::vector<int32_t>(shape_ref.begin(), shape_ref.end()); |
| 623 | } |
| 624 | } else if (type.hasRank()) { |
| 625 | llvm::ArrayRef<int64_t> shape_ref = type.getShape(); |
| 626 | if (mlir::failed(check_shape(shape_ref))) return llvm::None; |
| 627 | |
| 628 | shape.reserve(shape_ref.size()); |
| 629 | for (auto& dim : shape_ref) { |
| 630 | shape.push_back(dim == -1 ? 1 : dim); |
| 631 | } |
| 632 | shape_signature = std::vector<int32_t>(shape_ref.begin(), shape_ref.end()); |
| 633 | } |
| 634 | |
| 635 | if (auto* inst = value.getDefiningOp()) { |
| 636 | if (auto cst = dyn_cast<tfl::SparseConstOp>(inst)) { |
| 637 | // CreateSparsityParameters(cst.s_param()); |
| 638 | } else if (auto cst = dyn_cast<tfl::SparseQConstOp>(inst)) { |
| 639 | // CreateSparsityParameters(cst.s_param()); |
| 640 | } |
| 641 | } |
| 642 |
nothing calls this directly
no test coverage detected