@@ -109,62 +109,49 @@ class UrOffloadEntry {
109109 NativeType MNative;
110110};
111111
112- // / Generic array of UR entries.
113- template <typename T> class UrArray {
112+ namespace internal {
113+ // Content from this namespace shouldn't be used anywhere outside of this file
114+
115+ // / "native" data structures used by SYCL RT do not hold the data, but only
116+ // / point to it. The data itself is embedded into the binary data sections in
117+ // / real applications.
118+ // / In unit-tests we mock those data structures and therefore we need to ensure
119+ // / that the lifetime of the underlying data is correct and we won't perform
120+ // / any illegal memory accesses in unit-tests.
121+ template <typename T> class LifetimeExtender {
114122public:
115- explicit UrArray (std::vector<T> Entries) : MMockEntries(std::move(Entries)) {
116- updateEntries ();
117- }
118-
119- UrArray (std::initializer_list<T> Entries) : MMockEntries( std::move(Entries)) {
120- updateEntries ( );
123+ explicit LifetimeExtender (std::vector<T> Entries)
124+ : MMockEntries(std::move(Entries)) {
125+ MEntries. clear ();
126+ std::transform (MMockEntries. begin (), MMockEntries. end (),
127+ std::back_inserter (MEntries),
128+ []( const T &Entry) { return Entry. convertToNativeType (); } );
121129 }
122130
123- UrArray () = default ;
124-
125- void push_back (const T &Entry) {
126- MMockEntries.push_back (Entry);
127- MEntriesNeedUpdate = true ;
128- }
131+ LifetimeExtender () = default ;
129132
130133 typename T::NativeType *begin () {
131- if (MEntriesNeedUpdate) {
132- updateEntries ();
133- }
134-
135134 if (MEntries.empty ())
136135 return nullptr ;
137136
138137 return &*MEntries.begin ();
139138 }
140139 typename T::NativeType *end () {
141- if (MEntriesNeedUpdate) {
142- updateEntries ();
143- }
144-
145140 if (MEntries.empty ())
146141 return nullptr ;
147142
148143 return &*MEntries.rbegin () + 1 ;
149144 }
150145
151146private:
152- void updateEntries () {
153- MEntries.clear ();
154- std::transform (MMockEntries.begin (), MMockEntries.end (),
155- std::back_inserter (MEntries),
156- [](const T &Entry) { return Entry.convertToNativeType (); });
157- }
158147 std::vector<T> MMockEntries;
159148 std::vector<typename T::NativeType> MEntries;
160- bool MEntriesNeedUpdate = false ;
161149};
162150
163151#ifdef __cpp_deduction_guides
164- template <typename T> UrArray (std::vector<T>) -> UrArray<T>;
165-
166- template <typename T> UrArray (std::initializer_list<T>) -> UrArray<T>;
152+ template <typename T> LifetimeExtender (std::vector<T>) -> LifetimeExtender<T>;
167153#endif // __cpp_deduction_guides
154+ } // namespace internal
168155
169156// / Convenience wrapper for sycl_device_binary_property_set.
170157class UrPropertySet {
@@ -187,19 +174,23 @@ class UrPropertySet {
187174 // Value must be an all-zero 32-bit mask, which would mean that no fallback
188175 // libraries are needed to be loaded.
189176 UrProperty DeviceLibReqMask (" " , Data, SYCL_PROPERTY_TYPE_UINT32);
190- insert (__SYCL_PROPERTY_SET_DEVICELIB_REQ_MASK, UrArray{DeviceLibReqMask});
177+ insert (__SYCL_PROPERTY_SET_DEVICELIB_REQ_MASK, std::move (DeviceLibReqMask));
178+ }
179+
180+ // / Adds a new property to the set.
181+ // /
182+ // / \param Name is a property name. See ur.hpp for list of known names.
183+ // / \param Prop is a property value.
184+ void insert (const std::string &Name, UrProperty &&Props) {
185+ insert (Name, internal::LifetimeExtender{std::vector{std::move (Props)}});
191186 }
192187
193188 // / Adds a new array of properties to the set.
194189 // /
195190 // / \param Name is a property array name. See ur.hpp for list of known names.
196191 // / \param Props is an array of property values.
197- void insert (const std::string &Name, UrArray<UrProperty> Props) {
198- MNames.push_back (Name);
199- MMockProperties.push_back (std::move (Props));
200- MProperties.push_back (_sycl_device_binary_property_set_struct{
201- MNames.back ().data (), MMockProperties.back ().begin (),
202- MMockProperties.back ().end ()});
192+ void insert (const std::string &Name, std::vector<UrProperty> &&Props) {
193+ insert (Name, internal::LifetimeExtender{std::move (Props)});
203194 }
204195
205196 _sycl_device_binary_property_set_struct *begin () {
@@ -215,36 +206,65 @@ class UrPropertySet {
215206 }
216207
217208private:
209+ // / Adds a new array of properties to the set.
210+ // /
211+ // / \param Name is a property array name. See ur.hpp for list of known names.
212+ // / \param Props is an array of property values.
213+ void insert (const std::string &Name,
214+ internal::LifetimeExtender<UrProperty> Props) {
215+ MNames.push_back (Name);
216+ MMockProperties.push_back (std::move (Props));
217+ MProperties.push_back (_sycl_device_binary_property_set_struct{
218+ MNames.back ().data (), MMockProperties.back ().begin (),
219+ MMockProperties.back ().end ()});
220+ }
221+
218222 std::vector<std::string> MNames;
219- std::vector<UrArray <UrProperty>> MMockProperties;
223+ std::vector<internal::LifetimeExtender <UrProperty>> MMockProperties;
220224 std::vector<_sycl_device_binary_property_set_struct> MProperties;
221225};
222226
223227// / Convenience wrapper around UR internal structures, that manages UR binary
224228// / image data lifecycle.
225229class UrImage {
226- public :
230+ private :
227231 // / Constructs an arbitrary device image.
228232 UrImage (uint16_t Version, uint8_t Kind, uint8_t Format,
229233 const std::string &DeviceTargetSpec,
230234 const std::string &CompileOptions, const std::string &LinkOptions,
231- std::vector<char > Manifest, std::vector<unsigned char > Binary,
232- UrArray<UrOffloadEntry> OffloadEntries, UrPropertySet PropertySet)
235+ std::vector<char > &&Manifest, std::vector<unsigned char > &&Binary,
236+ internal::LifetimeExtender<UrOffloadEntry> OffloadEntries,
237+ UrPropertySet PropertySet)
233238 : MVersion(Version), MKind(Kind), MFormat(Format),
234239 MDeviceTargetSpec (DeviceTargetSpec), MCompileOptions(CompileOptions),
235240 MLinkOptions(LinkOptions), MManifest(std::move(Manifest)),
236241 MBinary(std::move(Binary)), MOffloadEntries(std::move(OffloadEntries)),
237242 MPropertySet(std::move(PropertySet)) {}
238243
244+ public:
245+ // / Constructs an arbitrary device image.
246+ UrImage (uint16_t Version, uint8_t Kind, uint8_t Format,
247+ const std::string &DeviceTargetSpec,
248+ const std::string &CompileOptions, const std::string &LinkOptions,
249+ std::vector<char > &&Manifest, std::vector<unsigned char > &&Binary,
250+ std::vector<UrOffloadEntry> &&OffloadEntries,
251+ UrPropertySet PropertySet)
252+ : UrImage(Version, Kind, Format, DeviceTargetSpec, CompileOptions,
253+ LinkOptions, std::move(Manifest), std::move(Binary),
254+ internal::LifetimeExtender(std::move(OffloadEntries)),
255+ std::move(PropertySet)) {}
256+
239257 // / Constructs a SYCL device image of the latest version.
240258 UrImage (uint8_t Format, const std::string &DeviceTargetSpec,
241259 const std::string &CompileOptions, const std::string &LinkOptions,
242- std::vector<unsigned char > Binary,
243- UrArray<UrOffloadEntry> OffloadEntries, UrPropertySet PropertySet)
260+ std::vector<unsigned char > &&Binary,
261+ std::vector<UrOffloadEntry> &&OffloadEntries,
262+ UrPropertySet PropertySet)
244263 : UrImage(SYCL_DEVICE_BINARY_VERSION,
245264 SYCL_DEVICE_BINARY_OFFLOAD_KIND_SYCL, Format, DeviceTargetSpec,
246265 CompileOptions, LinkOptions, {}, std::move(Binary),
247- std::move(OffloadEntries), std::move(PropertySet)) {}
266+ internal::LifetimeExtender(std::move(OffloadEntries)),
267+ std::move(PropertySet)) {}
248268
249269 sycl_device_binary_struct convertToNativeType () {
250270 return sycl_device_binary_struct{
@@ -275,7 +295,7 @@ class UrImage {
275295 std::string MLinkOptions;
276296 std::vector<char > MManifest;
277297 std::vector<unsigned char > MBinary;
278- UrArray <UrOffloadEntry> MOffloadEntries;
298+ internal::LifetimeExtender <UrOffloadEntry> MOffloadEntries;
279299 UrPropertySet MPropertySet;
280300};
281301
@@ -392,7 +412,7 @@ inline UrProperty makeSpecConstant(std::vector<char> &ValData,
392412// / Utility function to mark kernel as the one using assert
393413inline void setKernelUsesAssert (const std::vector<std::string> &Names,
394414 UrPropertySet &Set) {
395- UrArray <UrProperty> Value;
415+ std::vector <UrProperty> Value;
396416 for (const std::string &N : Names)
397417 Value.push_back ({N, {0 , 0 , 0 , 0 }, SYCL_PROPERTY_TYPE_UINT32});
398418 Set.insert (__SYCL_PROPERTY_SET_SYCL_ASSERT_USED, std::move (Value));
@@ -401,16 +421,14 @@ inline void setKernelUsesAssert(const std::vector<std::string> &Names,
401421// / Utility function to add specialization constants to property set.
402422// /
403423// / This function overrides the default spec constant values.
404- inline void addSpecConstants (UrArray <UrProperty> SpecConstants,
424+ inline void addSpecConstants (std::vector <UrProperty> && SpecConstants,
405425 std::vector<char > ValData, UrPropertySet &Props) {
406426 Props.insert (__SYCL_PROPERTY_SET_SPEC_CONST_MAP, std::move (SpecConstants));
407427
408428 UrProperty Prop{" all" , std::move (ValData), SYCL_PROPERTY_TYPE_BYTE_ARRAY};
409429
410- UrArray<UrProperty> DefaultValues{std::move (Prop)};
411-
412430 Props.insert (__SYCL_PROPERTY_SET_SPEC_CONST_DEFAULT_VALUES_MAP,
413- std::move (DefaultValues ));
431+ std::move (Prop ));
414432}
415433
416434// / Utility function to add ESIMD kernel flag to property set.
@@ -419,15 +437,13 @@ inline void addESIMDFlag(UrPropertySet &Props) {
419437 ValData[0 ] = 1 ;
420438 UrProperty Prop{" isEsimdImage" , ValData, SYCL_PROPERTY_TYPE_UINT32};
421439
422- UrArray<UrProperty> Value{std::move (Prop)};
423-
424- Props.insert (__SYCL_PROPERTY_SET_SYCL_MISC_PROP, std::move (Value));
440+ Props.insert (__SYCL_PROPERTY_SET_SYCL_MISC_PROP, std::move (Prop));
425441}
426442
427443// / Utility function to generate offload entries for kernels without arguments.
428- inline UrArray <UrOffloadEntry>
444+ inline std::vector <UrOffloadEntry>
429445makeEmptyKernels (std::initializer_list<std::string> KernelNames) {
430- UrArray <UrOffloadEntry> Entries;
446+ std::vector <UrOffloadEntry> Entries;
431447
432448 for (const auto &Name : KernelNames) {
433449 UrOffloadEntry E{Name, {}, 0 };
@@ -531,7 +547,7 @@ inline void
531547addDeviceRequirementsProps (UrPropertySet &Props,
532548 const std::vector<sycl::aspect> &Aspects,
533549 const std::vector<int > &ReqdWGSize = {}) {
534- UrArray <UrProperty> Value{makeAspectsProp (Aspects)};
550+ std::vector <UrProperty> Value{makeAspectsProp (Aspects)};
535551 if (!ReqdWGSize.empty ())
536552 Value.push_back (makeReqdWGSizeProp (ReqdWGSize));
537553 Props.insert (__SYCL_PROPERTY_SET_SYCL_DEVICE_REQUIREMENTS, std::move (Value));
@@ -550,7 +566,7 @@ generateDefaultImage(std::initializer_list<std::string> KernelNames) {
550566 std::vector<unsigned char > Bin (Combined.begin (), Combined.end ());
551567 Bin.push_back (0 );
552568
553- UrArray <UrOffloadEntry> Entries = makeEmptyKernels (KernelNames);
569+ std::vector <UrOffloadEntry> Entries = makeEmptyKernels (KernelNames);
554570
555571 UrImage Img{SYCL_DEVICE_BINARY_TYPE_SPIRV, // Format
556572 __SYCL_DEVICE_BINARY_TARGET_SPIRV64, // DeviceTargetSpec
0 commit comments