diff --git a/backends/native/runtime/graph/ScalarType.h b/backends/native/runtime/graph/ScalarType.h new file mode 100644 index 00000000000..303d2cb5a00 --- /dev/null +++ b/backends/native/runtime/graph/ScalarType.h @@ -0,0 +1,89 @@ +// Copyright (c) Meta Platforms, Inc. and affiliates. +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#pragma once + +#include +#include +#include + +namespace ptn { + +// X-macro table of scalar types: (CPP_TYPE, NAME, ID). +// +// The ids are the serialized ScalarType values, so a deserializer maps a +// serialized byte straight to this enum. They are not sequential: the gaps are +// ids reserved for element types this header does not carry. +// +// Half and BFloat16 have no 16-bit float type in this dependency-free header; +// they map to uint16_t as a raw storage stand-in, correct for size and layout. +#define PTN_FORALL_SCALAR_TYPES(_) \ + _(uint8_t, Byte, 0) \ + _(int8_t, Char, 1) \ + _(int16_t, Short, 2) \ + _(int32_t, Int, 3) \ + _(int64_t, Long, 4) \ + _(uint16_t, Half, 5) \ + _(float, Float, 6) \ + _(double, Double, 7) \ + _(bool, Bool, 11) \ + _(uint16_t, BFloat16, 15) \ + _(uint16_t, UInt16, 16) \ + _(uint32_t, UInt32, 17) \ + _(uint64_t, UInt64, 18) + +enum class ScalarType : int8_t { +#define PTN_DEFINE_ENUM(cpp_type, name, id) name = id, + PTN_FORALL_SCALAR_TYPES(PTN_DEFINE_ENUM) +#undef PTN_DEFINE_ENUM +}; + +#define PTN_DEFINE_CONSTANT(cpp_type, name, id) \ + inline constexpr ScalarType k##name = ScalarType::name; +PTN_FORALL_SCALAR_TYPES(PTN_DEFINE_CONSTANT) +#undef PTN_DEFINE_CONSTANT + +// Forward mapping only: a reverse C++-type -> ScalarType trait is omitted, +// since uint16_t would collide across Half / BFloat16 / UInt16. +template +struct ScalarTypeToCppType; +#define PTN_SPECIALIZE_S2C(cpp_type, name, id) \ + template <> \ + struct ScalarTypeToCppType { \ + using type = cpp_type; \ + }; +PTN_FORALL_SCALAR_TYPES(PTN_SPECIALIZE_S2C) +#undef PTN_SPECIALIZE_S2C + +template +using cpp_type_t = typename ScalarTypeToCppType::type; + +// Throws std::runtime_error on a value outside the table, e.g. a bad cast from +// an out-of-range serialized byte. +constexpr size_t element_size(ScalarType t) { + switch (t) { +#define PTN_CASE_ELEMSIZE(cpp_type, name, id) \ + case ScalarType::name: \ + return sizeof(cpp_type); + PTN_FORALL_SCALAR_TYPES(PTN_CASE_ELEMSIZE) +#undef PTN_CASE_ELEMSIZE + } + throw std::runtime_error("element_size: unrecognized ScalarType"); +} + +// Enumerator name, e.g. "Float". Throws on a value outside the table. +constexpr const char* scalar_type_name(ScalarType t) { + switch (t) { +#define PTN_CASE_NAME(cpp_type, name, id) \ + case ScalarType::name: \ + return #name; + PTN_FORALL_SCALAR_TYPES(PTN_CASE_NAME) +#undef PTN_CASE_NAME + } + throw std::runtime_error("scalar_type_name: unrecognized ScalarType"); +} + +} // namespace ptn diff --git a/backends/native/runtime/graph/TensorMeta.cpp b/backends/native/runtime/graph/TensorMeta.cpp new file mode 100644 index 00000000000..7cec572b08b --- /dev/null +++ b/backends/native/runtime/graph/TensorMeta.cpp @@ -0,0 +1,41 @@ +// Copyright (c) Meta Platforms, Inc. and affiliates. +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#include + +#include +#include +#include +#include + +namespace ptn { + +bool TensorMeta::is_contiguous() const { + if (dim_order_hint.empty()) { + return true; + } + // A length mismatch already makes this unequal. + return std::ranges::equal( + dim_order_hint, + std::views::iota(int32_t{0}, static_cast(sizes.size()))); +} + +int64_t TensorMeta::numel() const { + int64_t n = 1; + for (const int64_t dim_size : sizes) { + if (dim_size < 0) { + throw std::runtime_error("TensorMeta::numel: negative extent"); + } + // Signed overflow is UB, so the product must be checked before it happens. + if (dim_size != 0 && n > std::numeric_limits::max() / dim_size) { + throw std::runtime_error("TensorMeta::numel: element count overflows"); + } + n *= dim_size; + } + return n; +} + +} // namespace ptn diff --git a/backends/native/runtime/graph/TensorMeta.h b/backends/native/runtime/graph/TensorMeta.h new file mode 100644 index 00000000000..bf5b3288701 --- /dev/null +++ b/backends/native/runtime/graph/TensorMeta.h @@ -0,0 +1,51 @@ +// Copyright (c) Meta Platforms, Inc. and affiliates. +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#pragma once + +#include +#include +#include + +#include + +namespace ptn { + +// Logical tensor metadata: element type and shape. No storage, no quant scheme. +// +// sizes holds concrete extents. The wire format carries a per-dim range +// instead, but a runtime that plans and executes at fixed shapes cannot honor a +// dynamic dim, so deserialization rejects one rather than silently collapsing +// it to its upper bound. +// +// dim_order_hint is a permutation of dim indices, outermost first; empty means +// contiguous ([0, 1, ..., n-1]). It is a hint only for a tensor with no stored +// content — an activation — where an engine is free to pick its own physical +// layout. For a tensor whose bytes are serialized it instead describes the +// layout those bytes are actually in, and an engine that ignores it reads the +// weight wrong. +struct TensorMeta { + ScalarType dtype = ScalarType::Float; + std::vector sizes; + std::vector dim_order_hint; + + size_t ndim() const { + return sizes.size(); + } + + // True if dim_order_hint is empty or the identity permutation. + bool is_contiguous() const; + + // Throws std::runtime_error on a negative extent, or on a count that + // overflows int64_t. + int64_t numel() const; + + // Exact on dim_order_hint: an empty hint and a spelled-out identity + // permutation compare unequal though they mean the same layout. + bool operator==(const TensorMeta&) const = default; +}; + +} // namespace ptn diff --git a/backends/native/runtime/graph/targets.bzl b/backends/native/runtime/graph/targets.bzl index d468560227d..f145936dbbb 100644 --- a/backends/native/runtime/graph/targets.bzl +++ b/backends/native/runtime/graph/targets.bzl @@ -8,3 +8,38 @@ def define_common_targets(): ], visibility = ["//executorch/backends/native/..."], ) + + runtime.cxx_library( + name = "scalar_type", + exported_headers = [ + "ScalarType.h", + ], + visibility = ["//executorch/backends/native/..."], + ) + + runtime.cxx_library( + name = "tensor_meta", + srcs = ["TensorMeta.cpp"], + exported_headers = [ + "TensorMeta.h", + ], + exported_deps = [ + ":scalar_type", + ], + visibility = ["//executorch/backends/native/..."], + ) + + # utils/ has no BUCK of its own, so the IR printer's target lives here. Kept + # separate from the IR libraries so only a consumer that dumps the IR links + # the formatting code. + runtime.cxx_library( + name = "print", + srcs = ["utils/Print.cpp"], + exported_headers = [ + "utils/Print.h", + ], + exported_deps = [ + ":tensor_meta", + ], + visibility = ["//executorch/backends/native/..."], + ) diff --git a/backends/native/runtime/graph/utils/Print.cpp b/backends/native/runtime/graph/utils/Print.cpp new file mode 100644 index 00000000000..b1dee44d8e6 --- /dev/null +++ b/backends/native/runtime/graph/utils/Print.cpp @@ -0,0 +1,27 @@ +// Copyright (c) Meta Platforms, Inc. and affiliates. +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#include + +#include +#include + +namespace ptn { + +std::string to_string(const TensorMeta& meta) { + std::string s = scalar_type_name(meta.dtype); + s += "["; + for (size_t i = 0; i < meta.sizes.size(); ++i) { + if (i != 0) { + s += ","; + } + s += std::to_string(meta.sizes[i]); + } + s += "]"; + return s; +} + +} // namespace ptn diff --git a/backends/native/runtime/graph/utils/Print.h b/backends/native/runtime/graph/utils/Print.h new file mode 100644 index 00000000000..e9740618acd --- /dev/null +++ b/backends/native/runtime/graph/utils/Print.h @@ -0,0 +1,24 @@ +// Copyright (c) Meta Platforms, Inc. and affiliates. +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#pragma once + +#include + +#include + +namespace ptn { + +// Debug renderings of the in-memory IR. Free functions in their own target so +// nothing on an execution path links the formatting code; members would tie +// and these format choices to every consumer of the IR headers. The +// output is for humans -- nothing parses it back, and it is not versioned. + +// e.g. "Float[16,16]", "Float[1..8,16]" (bounded dynamic), "Float[0..?,16]" +// (unbounded). +std::string to_string(const TensorMeta& meta); + +} // namespace ptn