Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions backends/native/runtime/graph/ScalarType.h
Original file line number Diff line number Diff line change
@@ -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 <cstddef>
#include <cstdint>
#include <stdexcept>

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 <ScalarType N>
struct ScalarTypeToCppType;
#define PTN_SPECIALIZE_S2C(cpp_type, name, id) \
template <> \
struct ScalarTypeToCppType<ScalarType::name> { \
using type = cpp_type; \
};
PTN_FORALL_SCALAR_TYPES(PTN_SPECIALIZE_S2C)
#undef PTN_SPECIALIZE_S2C

template <ScalarType N>
using cpp_type_t = typename ScalarTypeToCppType<N>::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
41 changes: 41 additions & 0 deletions backends/native/runtime/graph/TensorMeta.cpp
Original file line number Diff line number Diff line change
@@ -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 <executorch/backends/native/runtime/graph/TensorMeta.h>

#include <algorithm>
#include <limits>
#include <ranges>
#include <stdexcept>

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<int32_t>(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<int64_t>::max() / dim_size) {
throw std::runtime_error("TensorMeta::numel: element count overflows");
}
n *= dim_size;
}
return n;
}

} // namespace ptn
51 changes: 51 additions & 0 deletions backends/native/runtime/graph/TensorMeta.h
Original file line number Diff line number Diff line change
@@ -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 <cstddef>
#include <cstdint>
#include <vector>

#include <executorch/backends/native/runtime/graph/ScalarType.h>

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<int64_t> sizes;
std::vector<int32_t> 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
35 changes: 35 additions & 0 deletions backends/native/runtime/graph/targets.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -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/..."],
)
27 changes: 27 additions & 0 deletions backends/native/runtime/graph/utils/Print.cpp
Original file line number Diff line number Diff line change
@@ -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 <executorch/backends/native/runtime/graph/utils/Print.h>

#include <cstddef>
#include <string>

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
24 changes: 24 additions & 0 deletions backends/native/runtime/graph/utils/Print.h
Original file line number Diff line number Diff line change
@@ -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 <string>

#include <executorch/backends/native/runtime/graph/TensorMeta.h>

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
// <string> 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
Loading