chromium/third_party/tflite/src/tensorflow/lite/core/c/common.h

/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
// WARNING: Users of TensorFlow Lite should not include this file directly, but
// should instead include "third_party/tensorflow/lite/c/common.h".
// Only the TensorFlow Lite implementation itself should include this file
// directly.

/// This file defines common C types and APIs for implementing operations,
/// delegates and other constructs in TensorFlow Lite. The actual operations and
/// delegates can be defined using C++, but the interface between the
/// interpreter and the operations are C.
///
/// Summary of abstractions:
/// * `TF_LITE_ENSURE` - self-sufficient error checking
/// * `TfLiteStatus` - status reporting
/// * `TfLiteIntArray` - stores tensor shapes (dims),
/// * `TfLiteContext` - allows an op to access the tensors
/// * `TfLiteTensor` - tensor (a multidimensional array)
/// * `TfLiteNode` - a single node or operation
/// * `TfLiteRegistration` - the implementation of a conceptual operation.
/// * `TfLiteDelegate` - allows delegation of nodes to alternative backends.
///
/// Some abstractions in this file are created and managed by Interpreter.
///
/// NOTE: The order of values in these structs are "semi-ABI stable". New values
/// should be added only to the end of structs and never reordered.
///
// clang-format off
// NOLINTBEGIN(whitespace/line_length)
/// \note Users of TensorFlow Lite should use
/// \code
/// #include "tensorflow/lite/c/common.h"
/// \endcode
/// to access the APIs documented on this page.
// NOLINTEND(whitespace/line_length)
// clang-format on

// IWYU pragma: private, include "third_party/tensorflow/lite/c/common.h"

#ifndef TENSORFLOW_LITE_CORE_C_COMMON_H_
#define TENSORFLOW_LITE_CORE_C_COMMON_H_

#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#include "tensorflow/lite/core/c/c_api_types.h"  // IWYU pragma: export

#ifdef __cplusplus
extern "C" {
#endif  // __cplusplus

// clang-format off
// NOLINTBEGIN(whitespace/line_length)
/** \defgroup common lite/c/common.h
 *  @{
 */
// NOLINTEND(whitespace/line_length)
// clang-format on

/// The list of external context types known to TF Lite. This list exists solely
/// to avoid conflicts and to ensure ops can share the external contexts they
/// need. Access to the external contexts is controlled by one of the
/// corresponding support files.
TfLiteExternalContextType;

// Forward declare so dependent structs and methods can reference these types
// prior to the struct definitions.
struct TfLiteContext;
struct TfLiteDelegate;
struct TfLiteRegistration;
struct TfLiteOpaqueDelegateBuilder;

/// An external context is a collection of information unrelated to the TF Lite
/// framework, but useful to a subset of the ops. TF Lite knows very little
/// about the actual contexts, but it keeps a list of them, and is able to
/// refresh them if configurations like the number of recommended threads
/// change.
TfLiteExternalContext;

#define kTfLiteOptionalTensor

/// Fixed size list of integers. Used for dimensions and inputs/outputs tensor
/// indices
TfLiteIntArray;

/// Given the size (number of elements) in a TfLiteIntArray, calculate its size
/// in bytes.
size_t TfLiteIntArrayGetSizeInBytes(int size);

#ifndef TF_LITE_STATIC_MEMORY
/// Create a array of a given `size` (uninitialized entries).
/// This returns a pointer, that you must free using TfLiteIntArrayFree().
TfLiteIntArray* TfLiteIntArrayCreate(int size);
#endif

/// Check if two intarrays are equal. Returns 1 if they are equal, 0 otherwise.
int TfLiteIntArrayEqual(const TfLiteIntArray* a, const TfLiteIntArray* b);

/// Check if an intarray equals an array. Returns 1 if equals, 0 otherwise.
int TfLiteIntArrayEqualsArray(const TfLiteIntArray* a, int b_size,
                              const int b_data[]);

#ifndef TF_LITE_STATIC_MEMORY
/// Create a copy of an array passed as `src`.
/// You are expected to free memory with TfLiteIntArrayFree
TfLiteIntArray* TfLiteIntArrayCopy(const TfLiteIntArray* src);

/// Free memory of array `a`.
void TfLiteIntArrayFree(TfLiteIntArray* a);
#endif  // TF_LITE_STATIC_MEMORY

/// Fixed size list of floats. Used for per-channel quantization.
TfLiteFloatArray;

/// Given the size (number of elements) in a TfLiteFloatArray, calculate its
/// size in bytes.
int TfLiteFloatArrayGetSizeInBytes(int size);

#ifndef TF_LITE_STATIC_MEMORY
/// Create a array of a given `size` (uninitialized entries).
/// This returns a pointer, that you must free using TfLiteFloatArrayFree().
TfLiteFloatArray* TfLiteFloatArrayCreate(int size);

/// Create a copy of an array passed as `src`.
/// You are expected to free memory with TfLiteFloatArrayFree.
TfLiteFloatArray* TfLiteFloatArrayCopy(const TfLiteFloatArray* src);

/// Free memory of array `a`.
void TfLiteFloatArrayFree(TfLiteFloatArray* a);
#endif  // TF_LITE_STATIC_MEMORY

// Since we must not depend on any libraries, define a minimal subset of
// error macros while avoiding names that have pre-conceived meanings like
// assert and check.

// Try to make all reporting calls through TF_LITE_KERNEL_LOG rather than
// calling the context->ReportError function directly, so that message strings
// can be stripped out if the binary size needs to be severely optimized.
#ifndef TF_LITE_STRIP_ERROR_STRINGS
#define TF_LITE_KERNEL_LOG(context, ...)

#define TF_LITE_MAYBE_KERNEL_LOG(context, ...)
#else  // TF_LITE_STRIP_ERROR_STRINGS
#define ARGS_UNUSED
#define TF_LITE_KERNEL_LOG
#define TF_LITE_MAYBE_KERNEL_LOG
#endif  // TF_LITE_STRIP_ERROR_STRINGS

/// Check whether value is true, and if not return kTfLiteError from
/// the current function (and report the error string msg).
#define TF_LITE_ENSURE_MSG(context, value, ...)

/// Check whether the value `a` is true, and if not return kTfLiteError from
/// the current function, while also reporting the location of the error.
#define TF_LITE_ENSURE(context, a)

#define TF_LITE_ENSURE_STATUS(a)

/// Check whether the value `a == b` is true, and if not return kTfLiteError
/// from the current function, while also reporting the location of the error.
/// `a` and `b` may be evaluated more than once, so no side effects or
/// extremely expensive computations should be done.
///
/// NOTE: Use TF_LITE_ENSURE_TYPES_EQ if comparing TfLiteTypes.
#define TF_LITE_ENSURE_EQ(context, a, b)

#define TF_LITE_ENSURE_TYPES_EQ(context, a, b)

#define TF_LITE_ENSURE_NEAR(context, a, b, epsilon)

#define TF_LITE_ENSURE_OK(context, status)

/// Single-precision complex data type compatible with the C99 definition.
TfLiteComplex64;

/// Double-precision complex data type compatible with the C99 definition.
TfLiteComplex128;

/// Half precision data type compatible with the C99 definition.
TfLiteFloat16;

/// bfloat16 data type compatible with the Google Brain definition.
/// https://cloud.google.com/tpu/docs/bfloat16.
/// This provides 1 bit of sign, 8 bits of exponent, and 7 bits of mantissa.
TfLiteBFloat16;

/// Return the name of a given type, for error reporting purposes.
const char* TfLiteTypeGetName(TfLiteType type);

/// SupportedQuantizationTypes.
TfLiteQuantizationType;

/// Structure specifying the quantization used by the tensor, if-any.
TfLiteQuantization;

/// Parameters for asymmetric quantization across a dimension (i.e per output
/// channel quantization).
/// quantized_dimension specifies which dimension the scales and zero_points
/// correspond to.
/// For a particular value in quantized_dimension, quantized values can be
/// converted back to float using:
///     `real_value = scale * (quantized_value - zero_point)`
TfLiteAffineQuantization;

/// A union of pointers that points to memory for a given tensor.
///
/// Do not access these members directly, if possible, use
/// `GetTensorData<TYPE>(tensor)` instead, otherwise only access `.data`, as
/// other members are deprecated.
TfLitePtrUnion;

/// Memory allocation strategies.
///  * `kTfLiteMmapRo`: Read-only memory-mapped data, or data externally
///        allocated.
///  * `kTfLiteArenaRw`: Arena allocated with no guarantees about persistence,
///        and available during eval.
///  * `kTfLiteArenaRwPersistent`: Arena allocated but persistent across eval,
///  and only available during eval.
///  * `kTfLiteDynamic`: Allocated during eval, or for string tensors.
///  * `kTfLitePersistentRo`: Allocated and populated during prepare. This is
///        useful for tensors that can be computed during prepare and treated
///        as constant inputs for downstream ops (also in prepare).
///  * `kTfLiteCustom`: Custom memory allocation provided by the user. See
///        TfLiteCustomAllocation below.
///  * `kTfLiteVariantObject`: Allocation is an arbitrary type-erased C++
///  object.
///        Allocation and deallocation are done through `new` and `delete`.
TfLiteAllocationType;

/// Memory allocation strategies.
///
/// TfLiteAllocationType values have been overloaded to mean more than their
/// original intent. This enum should only be used to document the allocation
/// strategy used by a tensor for it data.
TfLiteAllocationStrategy;

/// Describes how stable a tensor attribute is with regards to an interpreter
/// runs.
TfLiteRunStability;

/// Describes the steps of a TFLite operation life cycle.
TfLiteRunStep;

/// The delegates should use zero or positive integers to represent handles.
/// -1 is reserved from unallocated status.
TfLiteBufferHandle;
enum {};

/// Storage format of each dimension in a sparse tensor.
TfLiteDimensionType;

/// Metadata to encode each dimension in a sparse tensor.
TfLiteDimensionMetadata;

/// Parameters used to encode a sparse tensor. For detailed explanation of each
/// field please refer to lite/schema/schema.fbs.
TfLiteSparsity;

/// Defines a custom memory allocation not owned by the runtime.
/// `data` should be aligned to kDefaultTensorAlignment defined in
/// lite/util.h. (Currently 64 bytes)
/// NOTE: See `Interpreter::SetCustomAllocationForTensor` for details on usage.
TfLiteCustomAllocation;

/// The flags used in `Interpreter::SetCustomAllocationForTensor`.
/// Note that this is a bitmask, so the values should be 1, 2, 4, 8, ...etc.
TfLiteCustomAllocationFlags;

enum {};

/// A tensor in the interpreter system which is a wrapper around a buffer of
/// data including a dimensionality (or NULL if not currently defined).
#ifndef TF_LITE_STATIC_MEMORY
TfLiteTensor;

/// A structure representing an instance of a node.
/// This structure only exhibits the inputs, outputs, user defined data and some
/// node properties (like statefulness), not other features like the type.
TfLiteNode;
#else   // defined(TF_LITE_STATIC_MEMORY)?
// NOTE: This flag is opt-in only at compile time.
//
// Specific reduced TfLiteTensor struct for TF Micro runtime. This struct
// contains only the minimum fields required to initialize and prepare a micro
// inference graph. The fields in this struct have been ordered from
// largest-to-smallest for optimal struct sizeof.
//
// This struct does not use:
// - allocation
// - buffer_handle
// - data_is_stale
// - delegate
// - dims_signature
// - name
// - sparsity
typedef struct TfLiteTensor {
  // TODO(b/155784997): Consider consolidating these quantization fields:
  // Quantization information. Replaces params field above.
  TfLiteQuantization quantization;

  // Quantization information.
  TfLiteQuantizationParams params;

  // A union of data pointers. The appropriate type should be used for a typed
  // tensor based on `type`.
  TfLitePtrUnion data;

  // A pointer to a structure representing the dimensionality interpretation
  // that the buffer should have. NOTE: the product of elements of `dims`
  // and the element datatype size should be equal to `bytes` below.
  TfLiteIntArray* dims;

  // The number of bytes required to store the data of this Tensor. I.e.
  // (bytes of each element) * dims[0] * ... * dims[n-1].  For example, if
  // type is kTfLiteFloat32 and dims = {3, 2} then
  // bytes = sizeof(float) * 3 * 2 = 4 * 3 * 2 = 24.
  size_t bytes;

  // The data type specification for data stored in `data`. This affects
  // what member of `data` union should be used.
  TfLiteType type;

  // How memory is mapped
  //  kTfLiteMmapRo: Memory mapped read only.
  //  i.e. weights
  //  kTfLiteArenaRw: Arena allocated read write memory
  //  (i.e. temporaries, outputs).
  TfLiteAllocationType allocation_type;

  // True if the tensor is a variable.
  bool is_variable;
} TfLiteTensor;

// Specific reduced TfLiteNode struct for TF Micro runtime. This struct contains
// only the minimum fields required to represent a node.
//
// This struct does not use:
// - delegate
// - intermediates
// - temporaries
typedef struct TfLiteNode {
  // Inputs to this node expressed as indices into the simulator's tensors.
  TfLiteIntArray* inputs;

  // Outputs to this node expressed as indices into the simulator's tensors.
  TfLiteIntArray* outputs;

  // intermediate tensors to this node expressed as indices into the simulator's
  // tensors.
  TfLiteIntArray* intermediates;

  // Opaque data provided by the node implementer through `Registration.init`.
  void* user_data;

  // Opaque data provided to the node if the node is a builtin. This is usually
  // a structure defined in builtin_op_data.h
  void* builtin_data;

  // Custom initial data. This is the opaque data provided in the flatbuffer.
  //
  // WARNING: This is an experimental interface that is subject to change.
  const void* custom_initial_data;
  int custom_initial_data_size;
} TfLiteNode;
#endif  // TF_LITE_STATIC_MEMORY

/// Light-weight tensor struct for TF Micro runtime. Provides the minimal amount
/// of information required for a kernel to run during TfLiteRegistration::Eval.
// TODO(b/160955687): Move this field into TF_LITE_STATIC_MEMORY when TFLM
// builds with this flag by default internally.
TfLiteEvalTensor;

#ifndef TF_LITE_STATIC_MEMORY
/// Free data memory of tensor `t`.
void TfLiteTensorDataFree(TfLiteTensor* t);

/// Free quantization data.
void TfLiteQuantizationFree(TfLiteQuantization* quantization);

/// Free sparsity parameters.
void TfLiteSparsityFree(TfLiteSparsity* sparsity);

/// Free memory of tensor `t`.
void TfLiteTensorFree(TfLiteTensor* t);

/// Set all of a tensor's fields (and free any previously allocated data).
void TfLiteTensorReset(TfLiteType type, const char* name, TfLiteIntArray* dims,
                       TfLiteQuantizationParams quantization, char* buffer,
                       size_t size, TfLiteAllocationType allocation_type,
                       const void* allocation, bool is_variable,
                       TfLiteTensor* tensor);

/// Copies the contents of `src` in `dst`.
/// Function does nothing if either `src` or `dst` is passed as nullptr and
/// return `kTfLiteOk`.
/// Returns `kTfLiteError` if `src` and `dst` doesn't have matching data size.
/// Note function copies contents, so it won't create new data pointer
/// or change allocation type.
/// All Tensor related properties will be copied from `src` to `dst` like
/// quantization, sparsity, ...
TfLiteStatus TfLiteTensorCopy(const TfLiteTensor* src, TfLiteTensor* dst);

/// Change the size of the memory block owned by `tensor` to `num_bytes`.
/// Tensors with allocation types other than `kTfLiteDynamic` will be ignored
/// and a `kTfLiteOk` will be returned. `tensor`'s internal data buffer will be
/// assigned a pointer which can safely be passed to free or realloc if
/// `num_bytes` is zero. If `preserve_data` is true, tensor data will be
/// unchanged in the range from the start of the region up to the minimum of the
/// old and new sizes. In the case of NULL tensor, or an error allocating new
/// memory, returns `kTfLiteError`.
TfLiteStatus TfLiteTensorResizeMaybeCopy(size_t num_bytes, TfLiteTensor* tensor,
                                         bool preserve_data);

/// Change the size of the memory block owned by `tensor` to `num_bytes`.
/// Tensors with allocation types other than `kTfLiteDynamic` will be ignored
/// and a `kTfLiteOk` will be returned. `tensor`'s internal data buffer will be
/// assigned a pointer which can safely be passed to free or realloc if
/// `num_bytes` is zero. Tensor data will be unchanged in the range from the
/// start of the region up to the minimum of the old and new sizes. In the case
/// of NULL tensor, or an error allocating new memory, returns `kTfLiteError`.
TfLiteStatus TfLiteTensorRealloc(size_t num_bytes, TfLiteTensor* tensor);
#endif  // TF_LITE_STATIC_MEMORY

/// WARNING: This is an experimental interface that is subject to change.
///
/// Currently, TfLiteDelegateParams has to be allocated in a way that it's
/// trivially destructable. It will be stored as `builtin_data` field in
/// `TfLiteNode` of the delegate node.
///
/// See also the `CreateDelegateParams` function in `interpreter.cc` details.
TfLiteDelegateParams;

/// WARNING: This is an experimental interface that is subject to change.
///
/// Currently, TfLiteOpaqueDelegateParams has to be allocated in a way that it's
/// trivially destructable. It will be stored as `builtin_data` field in
/// `TfLiteNode` of the delegate node.
///
/// See also the `CreateOpaqueDelegateParams` function in `subgraph.cc`
/// details.
TfLiteOpaqueDelegateParams;

/// `TfLiteContext` allows an op to access the tensors.
///
/// `TfLiteContext` is a struct that is created by the TF Lite runtime
/// and passed to the "methods" (C function pointers) in the
/// `TfLiteRegistration` struct that are used to define custom ops and custom
/// delegate kernels. It contains information and methods (C function pointers)
/// that can be called by the code implementing a custom op or a custom delegate
/// kernel. These methods provide access to the context in which that custom op
/// or custom delegate kernel occurs, such as access to the input and output
/// tensors for that op, as well as methods for allocating memory buffers
/// and intermediate tensors, etc.
///
/// See also `TfLiteOpaqueContext`, which is an more ABI-stable equivalent.
TfLiteContext;

/// `TfLiteOperator` is an external version of `TfLiteRegistration`
/// for C API which doesn't use internal types (such as `TfLiteContext`) but
/// only uses stable API types (such as `TfLiteOpaqueContext`). The purpose of
/// each field is the exactly the same as with `TfLiteRegistration`.
TfLiteOperator;

#ifndef DOXYGEN_SKIP
// For backwards compatibility.
// Deprecated. Use TfLiteOperator instead.
TfLiteRegistrationExternal;
#endif

/// The valid values of the `inplace_operator` field in `TfLiteRegistration`.
/// This allow an op to signal to the runtime that the same data pointer
/// may be passed as an input and output without impacting the result.
/// This does not mean that the memory can safely be reused, it is up to the
/// runtime to determine this, e.g. if another op consumes the same input or not
/// or if an input tensor has sufficient memory allocated to store the output
/// data.
///
/// Setting these flags authorizes the runtime to set the data pointers of an
/// input and output tensor to the same value. In such cases, the memory
/// required by the output must be less than or equal to that required by the
/// shared input, never greater. If kTfLiteInplaceOpDataUnmodified is set, then
/// the runtime can share the same input tensor with multiple operator's
/// outputs, provided that kTfLiteInplaceOpDataUnmodified is set for all of
/// them. Otherwise, if an input tensor is consumed by multiple operators, it
/// may only be shared with the operator which is the last to consume it.
///
/// Note that this is a bitmask, so the values should be 1, 2, 4, 8, ...etc.
TfLiteInPlaceOp;

/// The number of shareable inputs supported.
static const int kTfLiteMaxSharableOpInputs =;

/// `TfLiteRegistration` defines the implementation of an operation
/// (a built-in op, custom op, or custom delegate kernel).
///
/// It is a struct containing "methods" (C function pointers) that will be
/// invoked by the TF Lite runtime to evaluate instances of the operation.
///
/// See also `TfLiteOperator` which is a more ABI-stable equivalent.
TfLiteRegistration;

/// \private
/// Old version of `TfLiteRegistration` to maintain binary backward
/// compatibility.
/// The legacy registration type must be a POD struct type whose field types
/// must be a prefix of the field types in TfLiteRegistration, and offset of the
/// first field in TfLiteRegistration that is not present in the legacy
/// registration type must be greater than or equal to the size of the legacy
/// registration type.
///
/// WARNING: This structure is deprecated / not an official part of the
/// API. It should be only used for binary backward compatibility.
TfLiteRegistration_V3;

/// \private
/// Old version of `TfLiteRegistration` to maintain binary backward
/// compatibility.
/// The legacy registration type must be a POD struct type whose field types
/// must be a prefix of the field types in TfLiteRegistration, and offset of the
/// first field in TfLiteRegistration that is not present in the legacy
/// registration type must be greater than or equal to the size of the legacy
/// registration type.
///
/// WARNING: This structure is deprecated / not an official part of the
/// API. It should be only used for binary backward compatibility.
TfLiteRegistration_V2;

/// \private
/// Old version of `TfLiteRegistration` to maintain binary backward
/// compatibility.
/// The legacy registration type must be a POD struct type whose field types
/// must be a prefix of the field types in TfLiteRegistration, and offset of the
/// first field in TfLiteRegistration that is not present in the legacy
/// registration type must be greater than or equal to the size of the legacy
/// registration type.
///
/// WARNING: This structure is deprecated / not an official part of the
/// API. It should be only used for binary backward compatibility.
TfLiteRegistration_V1;

/// The flags used in `TfLiteDelegate`. Note that this is a bitmask, so the
/// values should be 1, 2, 4, 8, ...etc.
TfLiteDelegateFlags;

/// WARNING: This is an experimental interface that is subject to change.
TfLiteDelegate;

/// Build a `null` delegate, with all the fields properly set to their default
/// values.
TfLiteDelegate TfLiteDelegateCreate(void);

/// `TfLiteOpaqueDelegateBuilder` is used for constructing
/// `TfLiteOpaqueDelegate`, see `TfLiteOpaqueDelegateCreate` in c_api_opaque.h.
/// NOTE: This struct is not ABI stable.
///
/// For forward source compatibility `TfLiteOpaqueDelegateBuilder` objects
/// should be brace-initialized, so that all fields (including any that might be
/// added in the future) get zero-initialized.  The purpose of each field is
/// exactly the same as with `TfLiteDelegate`.
///
/// NOTE: This type is part of the TensorFlow Lite Extension APIs.
/// We reserve the right to make changes to this API in future releases,
/// potentially including non-backwards-compatible changes, on a different
/// schedule than for the other TensorFlow Lite APIs. See
/// https://www.tensorflow.org/guide/versions#separate_version_number_for_tensorflow_lite_extension_apis.
TfLiteOpaqueDelegateBuilder;

#ifndef TF_LITE_STATIC_MEMORY
// See c_api_opaque.h.
// This declaration in common.h is only for backwards compatibility.
// NOTE: This function is part of the TensorFlow Lite Extension APIs, see above.
TfLiteOpaqueDelegate* TfLiteOpaqueDelegateCreate(
    const TfLiteOpaqueDelegateBuilder* opaque_delegate_builder);

// See c_api_opaque.h.
// This declaration in common.h is only for backwards compatibility.
// NOTE: This function is part of the TensorFlow Lite Extension APIs, see above.
void TfLiteOpaqueDelegateDelete(TfLiteOpaqueDelegate* delegate);
#endif  // TF_LITE_STATIC_MEMORY

// See c_api_opaque.h.
// This declaration in common.h is only for backwards compatibility.
// NOTE: This function is part of the TensorFlow Lite Extension APIs, see above.
void* TfLiteOpaqueDelegateGetData(const TfLiteOpaqueDelegate* delegate);

/// Returns a tensor data allocation strategy.
TfLiteAllocationStrategy TfLiteTensorGetAllocationStrategy(
    const TfLiteTensor* t);

/// Returns how stable a tensor data buffer address is across runs.
TfLiteRunStability TfLiteTensorGetBufferAddressStability(const TfLiteTensor* t);

/// Returns how stable a tensor data values are across runs.
TfLiteRunStability TfLiteTensorGetDataStability(const TfLiteTensor* t);

/// Returns the operation step when the data of a tensor is populated.
///
/// Some operations can precompute their results before the evaluation step.
/// This makes the data available earlier for subsequent operations.
TfLiteRunStep TfLiteTensorGetDataKnownStep(const TfLiteTensor* t);

/// Returns the operation steop when the shape of a tensor is computed.
///
/// Some operations can precompute the shape of their results before the
/// evaluation step. This makes the shape available earlier for subsequent
/// operations.
TfLiteRunStep TfLiteTensorGetShapeKnownStep(const TfLiteTensor* t);

/** @} */
// Ends `\addtogroup`, it's important for the doc generator that this doesn't
// include the CC code below.

#ifdef __cplusplus
}  // extern "C"

#include <utility>

// --- TFLITE VARIANT TENSORS ----
// Programming languges usually define "variant" as a type that can hold an
// unbounded set of types. See std::any
// (https://en.cppreference.com/w/cpp/utility/any) for a related standard
// library construct. In tensorflow, variant tensors have a data member which is
// an Object that is destructible and copy constructible.
//   Variant tensors are commonly used to represent non trivial data
// semantics that don't fit into simple primitives, such as lists of tensors and
// datasets. Additionally, they can facilitate containers for optimizing
// memory movement of tensor data.
//
// The following set of classes define the variant tensor member for tflite.
// They implement a type-erased container intended to be used behind the
// `data.data : void*` member of `TfLiteTensor`s. Runtime functions interact
// the variant member at the level of a `VariantData`, whereas kernels
// operate with the full knowledge of the un-erased type. The `VariantData`
// class provides abstract methods for destroying and copying `VariantData`.
// Invoking these methods will dispatch to the erased type opaquely.
//    The contents of any object of type derived from `AbstractVariant` can be
// written to `TfLiteTensor::data::data : void*` from kernels. If the runtime
// were to copy such a tensor through `TfLiteTensorCopy`, the destination data
// member will contain the result of invoking the erased type's copy
// constructor. Similar for the runtime releasing tensors from memory, the
// erased type's destructor will be invoked. There are a few caveats to consider
// to use these safely, which we discuss below.
//
// EXAMPLE: READING VARIANT TENSORS
//   ```
//   // retrieve input with `type == kTfLiteVariant`
//   TfLiteTensor* input = ...
//   // must first static cast to `VariantData`, more on this below.
//   VariantData* vd_input = static_cast<VariantData*>(t->data.data);
//   CustomType* typed_input =
//   static_cast<CustomType*>(vd_input);
//   // do custom work on `typed_input`...
//   ```
//
// EXAMPLE: WRITING VARIANT TENSORS
//   ```
//   TfLiteTensor* output = ...
//   // construct a new variant object behind the target tensor
//   TfLiteVariantRealloc<DerivedType, DerivedArgs...>(output, args...);
//   // again must static cast to `VariantData*` before writing to `void*`.
//   output->data.data = static_cast<VariantData*>(typed_output);
//   ```
//
// WHY STATIC CAST TO `VariantData*`
//    The Standard defines a `reinterpret_cast` from a derived type to its
// parents as undefined behavior when the parent is a non-standard layout.
// https://en.cppreference.com/w/cpp/language/reinterpret_cast (see bullet 5).
// Due to the `VariantData` having virtual members it is indeed non-standard
// layout, and any type derived from `VariantData` fails to be
// "transparently-replaceable". I.e. implicit cast from derived to base in this
// case may adjust the pointer and by definition `reinterpret_cast` will not
// the adjust the pointer.
//    Thus, dereferencing a pointer of type `VariantData` which addresses
// the first byte of an object of said derived type is UB unless it was first
// implicitly or statically casted to a `VariantData`. Writing the object of
// derived type directly to `void*` which is dereferenced as a `VariantData` is
// then UB, and so the intermediate cast through `VariantData` must be enforced.
//    A good example of this issue is ellucidate in the bottom code snippet
// here: https://en.cppreference.com/w/cpp/utility/launder.
class VariantData {};

// Concrete implementations extend `AbstractVariantData` with CRPT.
template <typename ErasedDerived>
class AbstractVariantData : public VariantData {};

// Analogous to `TfLiteTensorRealloc` for allocation of tensors whose
// data member points to an arbitrary C++ object. `VariantType` refers
// to the erased type of said object and `VariantArgs` refers to
// a list of argument types with which to construct a new `VariantType`.
// `VariantArgs` must match a constructor of `VariantType`.
template <class VariantType, class... VariantArgs>
TfLiteStatus TfLiteTensorVariantRealloc(TfLiteTensor* t,
                                        VariantArgs&&... args) {}

#endif  // __cplusplus
#endif  // TENSORFLOW_LITE_CORE_C_COMMON_H_