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
37 changes: 35 additions & 2 deletions backends/webgpu/runtime/ops/slice/Slice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include <webgpu/webgpu.h>

#include <cmath>
#include <cstdint>
#include <stdexcept>
#include <string>
Expand All @@ -30,14 +31,31 @@ struct SliceParams {
uint32_t _pad;
};

// Read scalar arg: Int->value (INT64_MAX->default), Null->default, else throw.
// Read scalar arg: Int->value (INT64_MAX->default), Double->truncated int if
// integral (the edge dialect may serialize an integer index as a float, e.g.
// a 0 start; a fractional Double throws, it is not a valid index),
// Null->default, else throw.
int64_t
read_scalar(WebGPUGraph& graph, int id, int64_t dflt, const char* what) {
switch (graph.get_value_type(id)) {
case WebGPUGraph::ValueType::Int: {
const int64_t v = graph.get_int(id);
return v == INT64_MAX ? dflt : v;
}
case WebGPUGraph::ValueType::Double: {
const double d = graph.get_double(id);
// Casting a NaN or out-of-int64-range double is undefined behavior;
// reject before the cast, not after.
if (std::isnan(d) || d < -9223372036854775808.0 ||
d >= 9223372036854775808.0) {
throw std::runtime_error(std::string("slice: non-integral ") + what);
}
const int64_t v = static_cast<int64_t>(d);
if (static_cast<double>(v) != d) {
throw std::runtime_error(std::string("slice: non-integral ") + what);
}
return v;
}
case WebGPUGraph::ValueType::Null:
return dflt;
default:
Expand All @@ -46,7 +64,8 @@ read_scalar(WebGPUGraph& graph, int id, int64_t dflt, const char* what) {
}
}

// Read a slice index (start/end) that MAY be a dynamic SymInt; else Int/Null.
// Read a slice index (start/end) that MAY be a dynamic SymInt; else Int/Double
// (truncated int if integral, mirrors read_scalar)/Null.
int64_t read_index(WebGPUGraph& graph, int id, int64_t dflt) {
switch (graph.get_value_type(id)) {
case WebGPUGraph::ValueType::SymInt:
Expand All @@ -55,6 +74,20 @@ int64_t read_index(WebGPUGraph& graph, int id, int64_t dflt) {
const int64_t v = graph.get_int(id);
return v == INT64_MAX ? dflt : v;
}
case WebGPUGraph::ValueType::Double: {
const double d = graph.get_double(id);
// Casting a NaN or out-of-int64-range double is undefined behavior;
// reject before the cast, not after.
if (std::isnan(d) || d < -9223372036854775808.0 ||
d >= 9223372036854775808.0) {
throw std::runtime_error("slice: non-integral start/end index");
}
const int64_t v = static_cast<int64_t>(d);
if (static_cast<double>(v) != d) {
throw std::runtime_error("slice: non-integral start/end index");
}
return v;
}
case WebGPUGraph::ValueType::Null:
return dflt;
default:
Expand Down
3 changes: 3 additions & 0 deletions backends/webgpu/runtime/ops/view_copy/ViewCopy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ void clone_impl(WebGPUGraph& graph, const std::vector<int>& args) {
WEBGPU_REGISTER_OPERATORS {
WEBGPU_REGISTER_OP(aten.view_copy.default, view_copy_impl);
WEBGPU_REGISTER_OP(aten.clone.default, clone_impl);
WEBGPU_REGISTER_OP(aten.alias_copy.default, clone_impl);
// _clone_dim_order ignores dim_order (AOT pass elides via shape+dtype).
WEBGPU_REGISTER_OP(dim_order_ops._clone_dim_order.default, clone_impl);
}

} // namespace executorch::backends::webgpu
Loading