@@ -19,6 +19,8 @@ namespace executorch {
1919namespace  runtime  {
2020namespace  deserialization  {
2121
22+ using  executorch::aten::ScalarType;
23+ using  executorch::runtime::TensorLayout;
2224//  Provides access to private Program methods.
2325class  TensorParser  final  {
2426 public: 
@@ -113,7 +115,8 @@ ET_NODISCARD Result<void*> getTensorDataPtr(
113115    const  executorch_flatbuffer::Tensor* s_tensor,
114116    const  Program* program,
115117    size_t  nbytes,
116-     HierarchicalAllocator* allocator) {
118+     HierarchicalAllocator* allocator,
119+     const  NamedDataMap* named_data_map) {
117120  auto  data_buffer_idx = s_tensor->data_buffer_idx ();
118121  const  executorch_flatbuffer::AllocationDetails* allocation_info =
119122      s_tensor->allocation_info ();
@@ -132,8 +135,76 @@ ET_NODISCARD Result<void*> getTensorDataPtr(
132135    }
133136    return  planned_ptr;
134137
135-     //  Constant
136-   } else  if  (data_buffer_idx > 0  && allocation_info == nullptr ) {
138+   }
139+   //  Constant, stored externally.
140+   else  if  (
141+       allocation_info == nullptr  && s_tensor->extra_tensor_info () != nullptr  &&
142+       s_tensor->extra_tensor_info ()->location () ==
143+           executorch_flatbuffer::TensorDataLocation::EXTERNAL) {
144+     //  Check that fqn is not null.
145+     ET_CHECK_OR_RETURN_ERROR (
146+         s_tensor->extra_tensor_info ()->fully_qualified_name () != nullptr ,
147+         InvalidExternalData,
148+         " Fully qualified name of external tensor is null"  );
149+     //  Look up tensor in named data map.
150+     Result<const  TensorLayout> tensor_layout_res = named_data_map->get_metadata (
151+         s_tensor->extra_tensor_info ()->fully_qualified_name ()->c_str ());
152+     if  (!tensor_layout_res.ok ()) {
153+       return  tensor_layout_res.error ();
154+     }
155+     const  TensorLayout& tensor_layout = tensor_layout_res.get ();
156+ 
157+     //  Compatibility checking.
158+     ET_CHECK_OR_RETURN_ERROR (
159+         static_cast <ScalarType>(s_tensor->scalar_type ()) ==
160+             tensor_layout.scalar_type (),
161+         InvalidExternalData,
162+         " Scalar type mismatch. Expected %hhd, got %hhd."  ,
163+         static_cast <int8_t >(s_tensor->scalar_type ()),
164+         static_cast <int8_t >(tensor_layout.scalar_type ()));
165+     ET_CHECK_OR_RETURN_ERROR (
166+         nbytes == tensor_layout.nbytes (),
167+         InvalidExternalData,
168+         " Nbytes mismatch. Expected %zu, got %zu."  ,
169+         nbytes,
170+         tensor_layout.nbytes ());
171+     int  dim = s_tensor->sizes ()->size ();
172+     ET_CHECK_OR_RETURN_ERROR (
173+         dim == tensor_layout.sizes ().size (),
174+         InvalidExternalData,
175+         " Dim mismatch. Expected %d, got %zu."  ,
176+         dim,
177+         tensor_layout.sizes ().size ());
178+     for  (int  i = 0 ; i < dim; i++) {
179+       ET_CHECK_OR_RETURN_ERROR (
180+           s_tensor->sizes ()->Get (i) == tensor_layout.sizes ()[i],
181+           InvalidExternalData,
182+           " Sizes mismatch. Expected %d, got %d for size at index %d."  ,
183+           s_tensor->sizes ()->Get (i),
184+           tensor_layout.sizes ()[i],
185+           i);
186+       ET_CHECK_OR_RETURN_ERROR (
187+           s_tensor->dim_order ()->Get (i) == tensor_layout.dim_order ()[i],
188+           InvalidExternalData,
189+           " Dim order mismatch. Expected %d, got %d for dim at index %d."  ,
190+           s_tensor->dim_order ()->Get (i),
191+           tensor_layout.dim_order ()[i],
192+           i);
193+     }
194+ 
195+     Result<FreeableBuffer> data_res = named_data_map->get_data (
196+         s_tensor->extra_tensor_info ()->fully_qualified_name ()->c_str ());
197+     if  (!data_res.ok ()) {
198+       return  data_res.error ();
199+     }
200+     //  The const_cast is 'ok' here because program and runtime should guarantee
201+     //  that this data is never modified. Temporary until we introduce the
202+     //  `get_and_persist_data` API from TODO(T214294528).
203+     return  const_cast <void *>(static_cast <const  void *>(data_res.get ().data ()));
204+   }
205+ 
206+   //  Constant, stored in PTE file.
207+   else  if  (data_buffer_idx > 0  && allocation_info == nullptr ) {
137208    auto  const_data =
138209        program->get_constant_buffer_data (data_buffer_idx, nbytes);
139210    if  (!const_data.ok ()) {
0 commit comments