mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-01 14:00:16 +01:00
rusticl/api: Use iterators in create_program_with_source
This replaces several instances of unsafe pointer arithmetic and dereferencing with a single unsafe creation of a slice, which we then use normal iterators on. The spec mandates that a null pointer is to be interpreted as if a slice filled with zeros had been given. That case is represented by an infinite iterator returning only zero. Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18978>
This commit is contained in:
parent
1e9e561811
commit
4de48a5dd5
1 changed files with 27 additions and 5 deletions
|
|
@ -10,6 +10,7 @@ use rusticl_opencl_gen::*;
|
|||
|
||||
use std::ffi::CStr;
|
||||
use std::ffi::CString;
|
||||
use std::iter;
|
||||
use std::os::raw::c_char;
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
|
|
@ -113,16 +114,37 @@ pub fn create_program_with_source(
|
|||
return Err(CL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
// "lengths argument is an array with the number of chars in each string
|
||||
// (the string length). If an element in lengths is zero, its accompanying
|
||||
// string is null-terminated. If lengths is NULL, all strings in the
|
||||
// strings argument are considered null-terminated."
|
||||
//
|
||||
// Take either an iterator over the given slice or - if the `lengths`
|
||||
// pointer is NULL - an iterator that always returns zero (infinite, but
|
||||
// later bounded by being zipped with the finite `srcs`).
|
||||
//
|
||||
// Looping over different iterators is no problem as long as they return
|
||||
// the same item type. However, since we can only decide which to use at
|
||||
// runtime, we need to use dynamic dispatch. The compiler also needs to
|
||||
// know how much space to reserve on the stack, but different
|
||||
// implementations of the `Iterator` trait will need different amounts of
|
||||
// memory. This is resolved by putting the actual iterator on the heap
|
||||
// with `Box` and only a reference to it on the stack.
|
||||
let lengths: Box<dyn Iterator<Item = &usize>> = if lengths.is_null() {
|
||||
Box::new(iter::repeat(&0))
|
||||
} else {
|
||||
Box::new(unsafe { slice::from_raw_parts(lengths, count as usize) }.iter())
|
||||
};
|
||||
|
||||
let mut source = String::new();
|
||||
// we don't want encoding or any other problems with the source to prevent compilations, so
|
||||
// just use CString::from_vec_unchecked and to_string_lossy
|
||||
for i in 0..count as usize {
|
||||
for (&string_ptr, len) in iter::zip(srcs, lengths) {
|
||||
unsafe {
|
||||
if lengths.is_null() || *lengths.add(i) == 0 {
|
||||
source.push_str(&CStr::from_ptr(*strings.add(i)).to_string_lossy());
|
||||
if *len == 0 {
|
||||
source.push_str(&CStr::from_ptr(string_ptr).to_string_lossy());
|
||||
} else {
|
||||
let l = *lengths.add(i);
|
||||
let arr = slice::from_raw_parts(*strings.add(i).cast(), l);
|
||||
let arr = slice::from_raw_parts(string_ptr.cast(), *len);
|
||||
source.push_str(&CString::from_vec_unchecked(arr.to_vec()).to_string_lossy());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue