diff --git a/backends/webgpu/runtime/ops/slice/Slice.cpp b/backends/webgpu/runtime/ops/slice/Slice.cpp index 261020e05d5..4fbbfccc5fe 100644 --- a/backends/webgpu/runtime/ops/slice/Slice.cpp +++ b/backends/webgpu/runtime/ops/slice/Slice.cpp @@ -14,6 +14,7 @@ #include +#include #include #include #include @@ -30,7 +31,10 @@ 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)) { @@ -38,6 +42,20 @@ read_scalar(WebGPUGraph& graph, int id, int64_t dflt, const char* what) { 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(d); + if (static_cast(v) != d) { + throw std::runtime_error(std::string("slice: non-integral ") + what); + } + return v; + } case WebGPUGraph::ValueType::Null: return dflt; default: @@ -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: @@ -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(d); + if (static_cast(v) != d) { + throw std::runtime_error("slice: non-integral start/end index"); + } + return v; + } case WebGPUGraph::ValueType::Null: return dflt; default: diff --git a/backends/webgpu/runtime/ops/view_copy/ViewCopy.cpp b/backends/webgpu/runtime/ops/view_copy/ViewCopy.cpp index eb274481893..7b3b44eb86f 100644 --- a/backends/webgpu/runtime/ops/view_copy/ViewCopy.cpp +++ b/backends/webgpu/runtime/ops/view_copy/ViewCopy.cpp @@ -103,6 +103,9 @@ void clone_impl(WebGPUGraph& graph, const std::vector& 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