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
33 changes: 33 additions & 0 deletions backends/native/runtime/graph/Ids.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// 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 <utility>

namespace ptn {

// Index-arena handles: a NodeRef indexes the graph's node arena, a ValueRef
// its value arena. Plain int32_t aliases — they index, compare, and hash
// directly, at the cost of no NodeRef/ValueRef type distinction. kInvalid marks
// "no ref".
using NodeRef = int32_t;
using ValueRef = int32_t;
inline constexpr int32_t kInvalid = -1;

constexpr bool valid(int32_t ref) {
return ref >= 0;
}

// std::cmp_less compares the signed ref against the unsigned size without
// casting either side.
constexpr bool in_bounds(int32_t ref, size_t size) {
return valid(ref) && std::cmp_less(ref, size);
}

} // namespace ptn
38 changes: 38 additions & 0 deletions backends/native/runtime/graph/Value.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// 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/Value.h>

#include <stdexcept>

namespace ptn {

const TensorMeta& Value::tensor_meta() const {
const TensorMeta* m = std::get_if<TensorMeta>(&value_);
if (m == nullptr) {
throw std::runtime_error("Value::tensor_meta: value is not a Tensor");
}
return *m;
}

const Scalar& Value::scalar() const {
const Scalar* s = std::get_if<Scalar>(&value_);
if (s == nullptr) {
throw std::runtime_error("Value::scalar: value is not a Scalar");
}
return *s;
}

const std::vector<ValueRef>& Value::content_refs() const {
const std::vector<ValueRef>* refs =
std::get_if<std::vector<ValueRef>>(&value_);
if (refs == nullptr) {
throw std::runtime_error("Value::content_refs: value is not a List");
}
return *refs;
}

} // namespace ptn
99 changes: 99 additions & 0 deletions backends/native/runtime/graph/Value.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// 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 <any>
#include <cstdint>
#include <string>
#include <unordered_map>
#include <utility>
#include <variant>
#include <vector>

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

namespace ptn {

enum class ValueKind : int8_t {
None = 0,
Tensor = 1,
Scalar = 2,
List = 3,
};

// A single SSA value (dataflow edge) in a Graph: its contents plus def-use
// wiring, a storage alias and an open annotation map. The ref fields are plain
// handles; whether one is in range is a property of the owning arena, so
// nothing here validates them.
//
// The variant's alternatives are listed in ValueKind order, so kind() is its
// index. A Tensor carries metadata only, so a weight is an ordinary arena
// value like any other, with its bytes held outside the graph. A List holds
// ValueRefs to its elements, so nesting goes through the arena; nothing
// deserialized is a List, it exists for in-memory rewrites such as grouping a
// tuple.
class Value {
private:
std::variant<std::monostate, TensorMeta, Scalar, std::vector<ValueRef>>
value_;

public:
// SSA name, scoped to the enclosing Graph.
std::string name;
// Defining node; invalid => graph input.
NodeRef producer_ref = kInvalid;
// Def-use, built by inverting node inputs.
std::vector<NodeRef> consumer_refs;
// Shares storage with this value (a view); fresh if invalid.
ValueRef alias_ref = kInvalid;
// Open annotations for graph passes and engines, like node.meta in FX.
std::unordered_map<std::string, std::any> attrs;

Value() = default; // a None value with an empty name

explicit Value(std::string name) // a named None value
: name(std::move(name)) {}

Value(std::string name, TensorMeta meta)
: value_(std::move(meta)), name(std::move(name)) {}

// The empty dim_order_hint is what makes the tensor contiguous.
Value(std::string name, ScalarType dtype, std::vector<Dim> sizes)
: value_(TensorMeta{dtype, std::move(sizes), {}}),
name(std::move(name)) {}

Value(std::string name, Scalar value)
: value_(value), name(std::move(name)) {}

Value(std::string name, std::vector<ValueRef> elem_refs)
: value_(std::move(elem_refs)), name(std::move(name)) {}

ValueKind kind() const {
return static_cast<ValueKind>(value_.index());
}
bool is_tensor() const {
return std::holds_alternative<TensorMeta>(value_);
}
bool is_scalar() const {
return std::holds_alternative<Scalar>(value_);
}
bool is_list() const {
return std::holds_alternative<std::vector<ValueRef>>(value_);
}
bool is_none() const {
return std::holds_alternative<std::monostate>(value_);
}

// Typed payload accessors: throw std::runtime_error unless the kind matches.
const TensorMeta& tensor_meta() const;
const Scalar& scalar() const;
const std::vector<ValueRef>& content_refs() const;
};

} // namespace ptn
22 changes: 22 additions & 0 deletions backends/native/runtime/graph/targets.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,25 @@ def define_common_targets():
],
visibility = ["//executorch/backends/native/..."],
)

runtime.cxx_library(
name = "ids",
exported_headers = [
"Ids.h",
],
visibility = ["//executorch/backends/native/..."],
)

runtime.cxx_library(
name = "value",
srcs = ["Value.cpp"],
exported_headers = [
"Value.h",
],
exported_deps = [
":ids",
":scalar",
":tensor_meta",
],
visibility = ["//executorch/backends/native/..."],
)
Loading