[SYCL][SYCLBIN] Implement kernel_bundle::ext_oneapi_get_content (#22061)
Adds the runtime-side serializer for the `sycl_ext_oneapi_syclbin`
extension. Users can now produce SYCLBIN bytes from any non-source
kernel_bundle by calling `ext_oneapi_get_content()` (the inverse of the
existing SYCLBIN load path).
### Implementation
**Writer.** New SYCLBIN::SYCLBINDesc / AbstractModuleDesc / ImageDesc
descriptor structs and SYCLBIN::write in the runtime SYCLBIN module.
Mirrors the llvm/lib/Object/SYCLBIN.cpp writer but operates on in-memory
image bytes rather than file paths, since kernel_bundles hold their
device images in memory. Output is wrapped in an OffloadBinary v2 entry
so it round-trips through the existing reader path.
**Two-pass metadata composition**. `SYCLBIN::serializeImages` walks a
bundle's live device images and emits one abstract module per image. For
each image the property registry is built in two passes:
1. *Raw forward* : copy the static `RTDeviceBinaryImage` property sets
verbatim (preserving producer order), minus the SYCLBIN-reserved sets.
2. *Runtime overlay*: a fixed OverrideTable of category-specific
overrides patches in state that lives on the runtime `device_image_impl`
rather than the static image: [SYCL/kernel names], [SYCL/kernel param
opt], and user-set specialization-constant values. This addresses the
original design flaw where the serializer ignored runtime overlays a
`kernel_bundle_impl` carries on top of the static image.
**Specialization constants.** SYCLBIN has no "user-set vs default"
concept. A value set via `set_specialization_constant` before
`ext_oneapi_get_content` is preserved through an optional
[SYCL/specialization constants set values] property carrying the
effective value blob (set descriptors hold their current value, unset
descriptors their default). On reload the reader restores the
per-descriptor `IsSet` state by comparing against the default-value
blob. Backward compatible via presence-check (`isAvailable()`):
compiler-produced SYCLBIN never carries it, old readers ignore it, new
readers fall back when absent (no version bump in SYCLBIN). The
descriptor set and default-value blob are left to the raw-forward pass
so their producer ordering (which the flat value blob is indexed
against) is never perturbed.
**Bundle plumbing.** `kernel_bundle_impl::ext_oneapi_get_content` always
re-serializes from the current `MUniqueDeviceImages`, so state-promoted
bundles (compile/link/build) emit the post-promotion images.
`ext_oneapi_source` bundles are rejected at compile time via
`std::enable_if` (with a runtime assert backstop for internal callers).
**Public API**: `kernel_bundle::ext_oneapi_get_content` for any
non-source state, plumbed through `kernel_bundle_plain`. New ABI symbol
registered in the Linux and Windows symbol dumps. Feature macro
SYCL_EXT_ONEAPI_SYCLBIN.
## Tests
* 19 unit tests across
sycl/unittests/SYCL2020/SYCLBINSerialize{,JIT,Multi,Overrides,SpecConst}.cpp:
compile_target round-trip, all three non-source bundle states, image
payload round-trip, magic/version headers, IR vs native image
classification, multi-image bundles (one abstract module per image),
empty bundles, mixed IR+native, kernel-name and eliminated-arg-mask
overlays, spec-constant descriptor/default/set-values round-trip
including the two-constant set-then-reset ordering case, device-global
property byte round-trip.
* 6 E2E tests under sycl/test-e2e/SYCLBIN/get_content_*: baseline
round-trip (compile → load → ext_oneapi_get_content → reload → run),
multi-target variant (gated on opencl-aot + opencl-cpu-rt), arch
round-trip, JIT→native, kernel-id round-trip, and
specialization-constant round-trip.