rusticl: add LinkOptions struct with validation

Add a LinkOptions struct that parses and validates link options
according to the OpenCL 3.0 specification (Section 5.8.7). This
replaces the raw string search for "-create-library" in
create_link_closure().

LinkOptions::new() accepts a &CStr, handles the to_str() conversion
internally, and returns CL_INVALID_LINKER_OPTIONS for any unknown
option or invalid UTF-8.

Program::link() now validates options via LinkOptions::new() before
starting the link, and the api layer passes &CStr directly.

Signed-off-by: jiajia Qian <jiajia.qian@nxp.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/41980>
This commit is contained in:
jiajia Qian 2026-06-11 09:47:01 +08:00 committed by Marge Bot
parent d889250541
commit 5f0fee80b8
2 changed files with 48 additions and 13 deletions

View file

@ -477,18 +477,12 @@ pub fn link_program(
return Err(CL_INVALID_OPERATION);
}
let (res, code) = Program::link(
context,
devices,
input_programs,
c_string_to_string(options),
callback,
)?;
// SAFETY: options is a valid C String or NULL.
let options = unsafe { CStr::from_ptr_or_empty(&options) };
let (res, code) = Program::link(context, devices, input_programs, options, callback)?;
Ok((res.into_cl(), code))
//• CL_INVALID_LINKER_OPTIONS if the linker options specified by options are invalid.
//• CL_INVALID_OPERATION if the rules for devices containing compiled binaries or libraries as described in input_programs argument above are not followed.
}
#[cl_entrypoint(clSetProgramSpecializationConstant)]

View file

@ -425,6 +425,43 @@ impl CompileOptions {
}
}
/// Parsed and validated link options.
struct LinkOptions {
create_lib: bool,
}
impl LinkOptions {
/// Parses and validates link options according to the OpenCL 3.0 specification
/// (Section 5.8.7). Returns CL_INVALID_LINKER_OPTIONS if any option is invalid.
fn new(options: &CStr) -> CLResult<Self> {
let mut create_lib = false;
if options.is_empty() {
return Ok(Self { create_lib });
}
let options = options.to_str().map_err(|_| CL_INVALID_LINKER_OPTIONS)?;
for token in options.split_whitespace() {
match token {
"-create-library" => {
create_lib = true;
}
"-enable-link-options"
| "-cl-denorms-are-zero"
| "-cl-no-signed-zeros"
| "-cl-unsafe-math-optimizations"
| "-cl-finite-math-only"
| "-cl-fast-relaxed-math"
| "-cl-no-subgroup-ifp" => {}
_ => return Err(CL_INVALID_LINKER_OPTIONS),
}
}
Ok(Self { create_lib })
}
}
impl Program {
fn create_default_builds(
devs: &[&'static Device],
@ -847,9 +884,13 @@ impl Program {
context: Arc<Context>,
devices: Vec<&'static Device>,
input_programs: Vec<Arc<Self>>,
options: String,
options: &CStr,
callback: Option<ProgramCB>,
) -> CLResult<(Arc<Self>, cl_int)> {
// Validate options before starting the link.
// clLinkProgram must return CL_INVALID_LINKER_OPTIONS if options are invalid.
let options = LinkOptions::new(options)?;
// Link can begin, so we must return a valid program object.
let builds_by_device = devices
.iter()
@ -1120,12 +1161,12 @@ fn create_link_closure(
program: Arc<Program>,
devices: Vec<&'static Device>,
input_programs: Vec<Arc<Program>>,
options: String,
options: LinkOptions,
mut callback: Option<ProgramCB>,
) -> impl FnMut() + Send + Sync + 'static {
move || {
let mut locks: Vec<_> = input_programs.iter().map(|p| p.build_info()).collect();
let is_lib = options.contains("-create-library");
let is_lib = options.create_lib;
let mut build_info = program.build_info();