• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright © 2022 Collabora, Ltd.
2 // SPDX-License-Identifier: MIT
3 
4 use nak_bindings::*;
5 
6 use std::ffi::{c_void, CStr};
7 use std::marker::PhantomData;
8 use std::ptr::NonNull;
9 use std::str;
10 
11 // from https://internals.rust-lang.org/t/discussion-on-offset-of/7440/2
12 macro_rules! offset_of {
13     ($Struct:path, $field:ident) => {{
14         // Using a separate function to minimize unhygienic hazards
15         // (e.g. unsafety of #[repr(packed)] field borrows).
16         // Uncomment `const` when `const fn`s can juggle pointers.
17 
18         // const
19         fn offset() -> usize {
20             let u = std::mem::MaybeUninit::<$Struct>::uninit();
21             // Use pattern-matching to avoid accidentally going through Deref.
22             let &$Struct { $field: ref f, .. } = unsafe { &*u.as_ptr() };
23             let o =
24                 (f as *const _ as usize).wrapping_sub(&u as *const _ as usize);
25             // Triple check that we are within `u` still.
26             assert!((0..=std::mem::size_of_val(&u)).contains(&o));
27             o
28         }
29         offset()
30     }};
31 }
32 
33 pub struct ExecListIter<'a, T> {
34     n: &'a exec_node,
35     offset: usize,
36     _marker: PhantomData<T>,
37 }
38 
39 impl<'a, T> ExecListIter<'a, T> {
new(l: &'a exec_list, offset: usize) -> Self40     fn new(l: &'a exec_list, offset: usize) -> Self {
41         Self {
42             n: &l.head_sentinel,
43             offset: offset,
44             _marker: PhantomData,
45         }
46     }
47 }
48 
49 impl<'a, T: 'a> Iterator for ExecListIter<'a, T> {
50     type Item = &'a T;
51 
next(&mut self) -> Option<Self::Item>52     fn next(&mut self) -> Option<Self::Item> {
53         self.n = unsafe { &*self.n.next };
54         if self.n.next.is_null() {
55             None
56         } else {
57             let t: *const c_void = (self.n as *const exec_node).cast();
58             Some(unsafe { &*(t.sub(self.offset).cast()) })
59         }
60     }
61 }
62 
63 pub trait NirDef {
parent_instr(&self) -> &nir_instr64     fn parent_instr(&self) -> &nir_instr;
components_read(&self) -> nir_component_mask_t65     fn components_read(&self) -> nir_component_mask_t;
all_uses_are_fsat(&self) -> bool66     fn all_uses_are_fsat(&self) -> bool;
67 }
68 
69 impl NirDef for nir_def {
parent_instr(&self) -> &nir_instr70     fn parent_instr(&self) -> &nir_instr {
71         unsafe { NonNull::new(self.parent_instr).unwrap().as_ref() }
72     }
73 
components_read(&self) -> nir_component_mask_t74     fn components_read(&self) -> nir_component_mask_t {
75         unsafe { nir_def_components_read(self as *const _) }
76     }
77 
all_uses_are_fsat(&self) -> bool78     fn all_uses_are_fsat(&self) -> bool {
79         unsafe { nir_def_all_uses_are_fsat(self as *const _) }
80     }
81 }
82 
83 pub trait AsConst: NirValue {
as_load_const(&self) -> Option<&nir_load_const_instr>84     fn as_load_const(&self) -> Option<&nir_load_const_instr>;
85 
is_const(&self) -> bool86     fn is_const(&self) -> bool {
87         self.as_load_const().is_some()
88     }
89 
comp_as_int(&self, comp: u8) -> Option<i64>90     fn comp_as_int(&self, comp: u8) -> Option<i64> {
91         if let Some(load) = self.as_load_const() {
92             assert!(comp < load.def.num_components);
93             Some(unsafe {
94                 let comp = usize::from(comp);
95                 match self.bit_size() {
96                     8 => load.values()[comp].i8_ as i64,
97                     16 => load.values()[comp].i16_ as i64,
98                     32 => load.values()[comp].i32_ as i64,
99                     64 => load.values()[comp].i64_,
100                     _ => panic!("Invalid bit size"),
101                 }
102             })
103         } else {
104             None
105         }
106     }
107 
comp_as_uint(&self, comp: u8) -> Option<u64>108     fn comp_as_uint(&self, comp: u8) -> Option<u64> {
109         if let Some(load) = self.as_load_const() {
110             assert!(comp < load.def.num_components);
111             Some(unsafe {
112                 let comp = usize::from(comp);
113                 match self.bit_size() {
114                     8 => load.values()[comp].u8_ as u64,
115                     16 => load.values()[comp].u16_ as u64,
116                     32 => load.values()[comp].u32_ as u64,
117                     64 => load.values()[comp].u64_,
118                     _ => panic!("Invalid bit size"),
119                 }
120             })
121         } else {
122             None
123         }
124     }
125 
as_int(&self) -> Option<i64>126     fn as_int(&self) -> Option<i64> {
127         assert!(self.num_components() == 1);
128         self.comp_as_int(0)
129     }
130 
as_uint(&self) -> Option<u64>131     fn as_uint(&self) -> Option<u64> {
132         assert!(self.num_components() == 1);
133         self.comp_as_uint(0)
134     }
135 
is_zero(&self) -> bool136     fn is_zero(&self) -> bool {
137         self.num_components() == 1 && self.as_uint() == Some(0)
138     }
139 }
140 
141 impl AsConst for nir_def {
as_load_const(&self) -> Option<&nir_load_const_instr>142     fn as_load_const(&self) -> Option<&nir_load_const_instr> {
143         self.parent_instr().as_load_const()
144     }
145 }
146 
147 impl AsConst for nir_src {
as_load_const(&self) -> Option<&nir_load_const_instr>148     fn as_load_const(&self) -> Option<&nir_load_const_instr> {
149         self.as_def().parent_instr().as_load_const()
150     }
151 }
152 
153 pub trait AsDef {
as_def(&self) -> &nir_def154     fn as_def(&self) -> &nir_def;
155 }
156 
157 impl AsDef for nir_def {
as_def(&self) -> &nir_def158     fn as_def(&self) -> &nir_def {
159         self
160     }
161 }
162 
163 pub trait NirValue {
bit_size(&self) -> u8164     fn bit_size(&self) -> u8;
num_components(&self) -> u8165     fn num_components(&self) -> u8;
166 }
167 
168 impl<T: AsDef> NirValue for T {
bit_size(&self) -> u8169     fn bit_size(&self) -> u8 {
170         self.as_def().bit_size
171     }
172 
num_components(&self) -> u8173     fn num_components(&self) -> u8 {
174         self.as_def().num_components
175     }
176 }
177 
178 impl AsDef for nir_src {
as_def(&self) -> &nir_def179     fn as_def(&self) -> &nir_def {
180         unsafe { &*self.ssa }
181     }
182 }
183 
184 pub trait NirSrcsAsSlice<S> {
srcs_as_slice(&self) -> &[S]185     fn srcs_as_slice(&self) -> &[S];
186 
get_src(&self, idx: usize) -> &S187     fn get_src(&self, idx: usize) -> &S {
188         &self.srcs_as_slice()[idx]
189     }
190 }
191 
192 pub trait NirAluInstr {
info(&self) -> &nir_op_info193     fn info(&self) -> &nir_op_info;
src_components(&self, src_idx: u8) -> u8194     fn src_components(&self, src_idx: u8) -> u8;
195 }
196 
197 impl NirAluInstr for nir_alu_instr {
info(&self) -> &nir_op_info198     fn info(&self) -> &nir_op_info {
199         let info_idx: usize = self.op.try_into().unwrap();
200         unsafe { &nir_op_infos[info_idx] }
201     }
202 
src_components(&self, src_idx: u8) -> u8203     fn src_components(&self, src_idx: u8) -> u8 {
204         assert!(src_idx < self.info().num_inputs);
205         unsafe {
206             nir_ssa_alu_instr_src_components(self as *const _, src_idx.into())
207                 .try_into()
208                 .unwrap()
209         }
210     }
211 }
212 
213 impl NirSrcsAsSlice<nir_alu_src> for nir_alu_instr {
srcs_as_slice(&self) -> &[nir_alu_src]214     fn srcs_as_slice(&self) -> &[nir_alu_src] {
215         unsafe {
216             self.src
217                 .as_slice(self.info().num_inputs.try_into().unwrap())
218         }
219     }
220 }
221 
222 impl AsDef for nir_alu_src {
as_def(&self) -> &nir_def223     fn as_def(&self) -> &nir_def {
224         self.src.as_def()
225     }
226 }
227 
228 pub trait NirAluInfo {
name(&self) -> &'static str229     fn name(&self) -> &'static str;
230 }
231 
232 impl NirAluInfo for nir_op_info {
name(&self) -> &'static str233     fn name(&self) -> &'static str {
234         unsafe { CStr::from_ptr(self.name).to_str().expect("Invalid UTF-8") }
235     }
236 }
237 
238 impl NirSrcsAsSlice<nir_tex_src> for nir_tex_instr {
srcs_as_slice(&self) -> &[nir_tex_src]239     fn srcs_as_slice(&self) -> &[nir_tex_src] {
240         unsafe { std::slice::from_raw_parts(self.src, self.num_srcs as usize) }
241     }
242 }
243 
244 pub trait NirIntrinsicInstr {
info(&self) -> &nir_intrinsic_info245     fn info(&self) -> &nir_intrinsic_info;
get_const_index(&self, name: u32) -> u32246     fn get_const_index(&self, name: u32) -> u32;
base(&self) -> i32247     fn base(&self) -> i32;
range_base(&self) -> i32248     fn range_base(&self) -> i32;
range(&self) -> i32249     fn range(&self) -> i32;
write_mask(&self) -> u32250     fn write_mask(&self) -> u32;
stream_id(&self) -> u32251     fn stream_id(&self) -> u32;
component(&self) -> u32252     fn component(&self) -> u32;
interp_mode(&self) -> u32253     fn interp_mode(&self) -> u32;
reduction_op(&self) -> nir_op254     fn reduction_op(&self) -> nir_op;
cluster_size(&self) -> u32255     fn cluster_size(&self) -> u32;
image_dim(&self) -> glsl_sampler_dim256     fn image_dim(&self) -> glsl_sampler_dim;
image_array(&self) -> bool257     fn image_array(&self) -> bool;
access(&self) -> gl_access_qualifier258     fn access(&self) -> gl_access_qualifier;
align(&self) -> u32259     fn align(&self) -> u32;
align_mul(&self) -> u32260     fn align_mul(&self) -> u32;
align_offset(&self) -> u32261     fn align_offset(&self) -> u32;
execution_scope(&self) -> mesa_scope262     fn execution_scope(&self) -> mesa_scope;
memory_scope(&self) -> mesa_scope263     fn memory_scope(&self) -> mesa_scope;
memory_semantics(&self) -> nir_memory_semantics264     fn memory_semantics(&self) -> nir_memory_semantics;
memory_modes(&self) -> nir_variable_mode265     fn memory_modes(&self) -> nir_variable_mode;
flags(&self) -> u32266     fn flags(&self) -> u32;
atomic_op(&self) -> nir_atomic_op267     fn atomic_op(&self) -> nir_atomic_op;
268 }
269 
270 impl NirIntrinsicInstr for nir_intrinsic_instr {
info(&self) -> &nir_intrinsic_info271     fn info(&self) -> &nir_intrinsic_info {
272         let info_idx: usize = self.intrinsic.try_into().unwrap();
273         unsafe { &nir_intrinsic_infos[info_idx] }
274     }
275 
get_const_index(&self, name: u32) -> u32276     fn get_const_index(&self, name: u32) -> u32 {
277         let name: usize = name.try_into().unwrap();
278         let idx = self.info().index_map[name];
279         assert!(idx > 0);
280         self.const_index[usize::from(idx - 1)] as u32
281     }
282 
base(&self) -> i32283     fn base(&self) -> i32 {
284         self.get_const_index(NIR_INTRINSIC_BASE) as i32
285     }
286 
range_base(&self) -> i32287     fn range_base(&self) -> i32 {
288         self.get_const_index(NIR_INTRINSIC_RANGE_BASE) as i32
289     }
290 
range(&self) -> i32291     fn range(&self) -> i32 {
292         self.get_const_index(NIR_INTRINSIC_RANGE) as i32
293     }
294 
write_mask(&self) -> u32295     fn write_mask(&self) -> u32 {
296         self.get_const_index(NIR_INTRINSIC_WRITE_MASK)
297     }
298 
stream_id(&self) -> u32299     fn stream_id(&self) -> u32 {
300         self.get_const_index(NIR_INTRINSIC_STREAM_ID)
301     }
302 
component(&self) -> u32303     fn component(&self) -> u32 {
304         self.get_const_index(NIR_INTRINSIC_COMPONENT)
305     }
306 
interp_mode(&self) -> u32307     fn interp_mode(&self) -> u32 {
308         self.get_const_index(NIR_INTRINSIC_INTERP_MODE)
309     }
310 
reduction_op(&self) -> nir_op311     fn reduction_op(&self) -> nir_op {
312         self.get_const_index(NIR_INTRINSIC_REDUCTION_OP) as nir_op
313     }
314 
cluster_size(&self) -> u32315     fn cluster_size(&self) -> u32 {
316         self.get_const_index(NIR_INTRINSIC_CLUSTER_SIZE)
317     }
318 
image_dim(&self) -> glsl_sampler_dim319     fn image_dim(&self) -> glsl_sampler_dim {
320         self.get_const_index(NIR_INTRINSIC_IMAGE_DIM) as glsl_sampler_dim
321     }
322 
image_array(&self) -> bool323     fn image_array(&self) -> bool {
324         self.get_const_index(NIR_INTRINSIC_IMAGE_ARRAY) != 0
325     }
326 
access(&self) -> gl_access_qualifier327     fn access(&self) -> gl_access_qualifier {
328         self.get_const_index(NIR_INTRINSIC_ACCESS) as gl_access_qualifier
329     }
330 
align(&self) -> u32331     fn align(&self) -> u32 {
332         let mul = self.align_mul();
333         let offset = self.align_offset();
334         assert!(offset < mul);
335         if offset > 0 {
336             1 << offset.trailing_zeros()
337         } else {
338             mul
339         }
340     }
341 
align_mul(&self) -> u32342     fn align_mul(&self) -> u32 {
343         self.get_const_index(NIR_INTRINSIC_ALIGN_MUL)
344     }
345 
align_offset(&self) -> u32346     fn align_offset(&self) -> u32 {
347         self.get_const_index(NIR_INTRINSIC_ALIGN_OFFSET)
348     }
349 
execution_scope(&self) -> mesa_scope350     fn execution_scope(&self) -> mesa_scope {
351         self.get_const_index(NIR_INTRINSIC_EXECUTION_SCOPE)
352     }
353 
memory_scope(&self) -> mesa_scope354     fn memory_scope(&self) -> mesa_scope {
355         self.get_const_index(NIR_INTRINSIC_MEMORY_SCOPE)
356     }
357 
memory_semantics(&self) -> nir_memory_semantics358     fn memory_semantics(&self) -> nir_memory_semantics {
359         self.get_const_index(NIR_INTRINSIC_MEMORY_SEMANTICS)
360     }
361 
memory_modes(&self) -> nir_variable_mode362     fn memory_modes(&self) -> nir_variable_mode {
363         self.get_const_index(NIR_INTRINSIC_MEMORY_MODES)
364     }
365 
flags(&self) -> u32366     fn flags(&self) -> u32 {
367         self.get_const_index(NIR_INTRINSIC_FLAGS)
368     }
369 
atomic_op(&self) -> nir_atomic_op370     fn atomic_op(&self) -> nir_atomic_op {
371         self.get_const_index(NIR_INTRINSIC_ATOMIC_OP) as nir_atomic_op
372     }
373 }
374 
375 impl NirSrcsAsSlice<nir_src> for nir_intrinsic_instr {
srcs_as_slice(&self) -> &[nir_src]376     fn srcs_as_slice(&self) -> &[nir_src] {
377         unsafe {
378             let info = nir_intrinsic_infos[self.intrinsic as usize];
379             self.src.as_slice(info.num_srcs as usize)
380         }
381     }
382 }
383 
384 pub trait NirIntrinsicInfo {
name(&self) -> &'static str385     fn name(&self) -> &'static str;
386 }
387 
388 impl NirIntrinsicInfo for nir_intrinsic_info {
name(&self) -> &'static str389     fn name(&self) -> &'static str {
390         unsafe { CStr::from_ptr(self.name).to_str().expect("Invalid UTF-8") }
391     }
392 }
393 
394 pub trait NirLoadConstInstr {
values(&self) -> &[nir_const_value]395     fn values(&self) -> &[nir_const_value];
396 }
397 
398 impl NirLoadConstInstr for nir_load_const_instr {
values(&self) -> &[nir_const_value]399     fn values(&self) -> &[nir_const_value] {
400         unsafe { self.value.as_slice(self.def.num_components as usize) }
401     }
402 }
403 
404 pub trait NirPhiSrc {
pred(&self) -> &nir_block405     fn pred(&self) -> &nir_block;
406 }
407 
408 impl NirPhiSrc for nir_phi_src {
pred(&self) -> &nir_block409     fn pred(&self) -> &nir_block {
410         unsafe { NonNull::new(self.pred).unwrap().as_ref() }
411     }
412 }
413 
414 pub trait NirPhiInstr {
iter_srcs(&self) -> ExecListIter<nir_phi_src>415     fn iter_srcs(&self) -> ExecListIter<nir_phi_src>;
416 }
417 
418 impl NirPhiInstr for nir_phi_instr {
iter_srcs(&self) -> ExecListIter<nir_phi_src>419     fn iter_srcs(&self) -> ExecListIter<nir_phi_src> {
420         ExecListIter::new(&self.srcs, offset_of!(nir_phi_src, node))
421     }
422 }
423 
424 pub trait NirInstr {
as_alu(&self) -> Option<&nir_alu_instr>425     fn as_alu(&self) -> Option<&nir_alu_instr>;
as_jump(&self) -> Option<&nir_jump_instr>426     fn as_jump(&self) -> Option<&nir_jump_instr>;
as_tex(&self) -> Option<&nir_tex_instr>427     fn as_tex(&self) -> Option<&nir_tex_instr>;
as_intrinsic(&self) -> Option<&nir_intrinsic_instr>428     fn as_intrinsic(&self) -> Option<&nir_intrinsic_instr>;
as_load_const(&self) -> Option<&nir_load_const_instr>429     fn as_load_const(&self) -> Option<&nir_load_const_instr>;
as_undef(&self) -> Option<&nir_undef_instr>430     fn as_undef(&self) -> Option<&nir_undef_instr>;
as_phi(&self) -> Option<&nir_phi_instr>431     fn as_phi(&self) -> Option<&nir_phi_instr>;
432 }
433 
434 impl NirInstr for nir_instr {
as_alu(&self) -> Option<&nir_alu_instr>435     fn as_alu(&self) -> Option<&nir_alu_instr> {
436         if self.type_ == nir_instr_type_alu {
437             let p = self as *const nir_instr;
438             Some(unsafe { &*(p as *const nir_alu_instr) })
439         } else {
440             None
441         }
442     }
443 
as_jump(&self) -> Option<&nir_jump_instr>444     fn as_jump(&self) -> Option<&nir_jump_instr> {
445         if self.type_ == nir_instr_type_jump {
446             let p = self as *const nir_instr;
447             Some(unsafe { &*(p as *const nir_jump_instr) })
448         } else {
449             None
450         }
451     }
452 
as_tex(&self) -> Option<&nir_tex_instr>453     fn as_tex(&self) -> Option<&nir_tex_instr> {
454         if self.type_ == nir_instr_type_tex {
455             let p = self as *const nir_instr;
456             Some(unsafe { &*(p as *const nir_tex_instr) })
457         } else {
458             None
459         }
460     }
461 
as_intrinsic(&self) -> Option<&nir_intrinsic_instr>462     fn as_intrinsic(&self) -> Option<&nir_intrinsic_instr> {
463         if self.type_ == nir_instr_type_intrinsic {
464             let p = self as *const nir_instr;
465             Some(unsafe { &*(p as *const nir_intrinsic_instr) })
466         } else {
467             None
468         }
469     }
470 
as_load_const(&self) -> Option<&nir_load_const_instr>471     fn as_load_const(&self) -> Option<&nir_load_const_instr> {
472         if self.type_ == nir_instr_type_load_const {
473             let p = self as *const nir_instr;
474             Some(unsafe { &*(p as *const nir_load_const_instr) })
475         } else {
476             None
477         }
478     }
479 
as_undef(&self) -> Option<&nir_undef_instr>480     fn as_undef(&self) -> Option<&nir_undef_instr> {
481         if self.type_ == nir_instr_type_undef {
482             let p = self as *const nir_instr;
483             Some(unsafe { &*(p as *const nir_undef_instr) })
484         } else {
485             None
486         }
487     }
488 
as_phi(&self) -> Option<&nir_phi_instr>489     fn as_phi(&self) -> Option<&nir_phi_instr> {
490         if self.type_ == nir_instr_type_phi {
491             let p = self as *const nir_instr;
492             Some(unsafe { &*(p as *const nir_phi_instr) })
493         } else {
494             None
495         }
496     }
497 }
498 
499 pub trait NirBlock {
iter_instr_list(&self) -> ExecListIter<nir_instr>500     fn iter_instr_list(&self) -> ExecListIter<nir_instr>;
successors(&self) -> [Option<&nir_block>; 2]501     fn successors(&self) -> [Option<&nir_block>; 2];
following_if(&self) -> Option<&nir_if>502     fn following_if(&self) -> Option<&nir_if>;
503 }
504 
505 impl NirBlock for nir_block {
iter_instr_list(&self) -> ExecListIter<nir_instr>506     fn iter_instr_list(&self) -> ExecListIter<nir_instr> {
507         ExecListIter::new(&self.instr_list, offset_of!(nir_instr, node))
508     }
509 
successors(&self) -> [Option<&nir_block>; 2]510     fn successors(&self) -> [Option<&nir_block>; 2] {
511         [
512             NonNull::new(self.successors[0]).map(|b| unsafe { b.as_ref() }),
513             NonNull::new(self.successors[1]).map(|b| unsafe { b.as_ref() }),
514         ]
515     }
516 
following_if(&self) -> Option<&nir_if>517     fn following_if(&self) -> Option<&nir_if> {
518         let self_ptr = self as *const _ as *mut _;
519         unsafe { nir_block_get_following_if(self_ptr).as_ref() }
520     }
521 }
522 
523 pub trait NirIf {
first_then_block(&self) -> &nir_block524     fn first_then_block(&self) -> &nir_block;
first_else_block(&self) -> &nir_block525     fn first_else_block(&self) -> &nir_block;
iter_then_list(&self) -> ExecListIter<nir_cf_node>526     fn iter_then_list(&self) -> ExecListIter<nir_cf_node>;
iter_else_list(&self) -> ExecListIter<nir_cf_node>527     fn iter_else_list(&self) -> ExecListIter<nir_cf_node>;
528 }
529 
530 impl NirIf for nir_if {
first_then_block(&self) -> &nir_block531     fn first_then_block(&self) -> &nir_block {
532         self.iter_then_list().next().unwrap().as_block().unwrap()
533     }
first_else_block(&self) -> &nir_block534     fn first_else_block(&self) -> &nir_block {
535         self.iter_else_list().next().unwrap().as_block().unwrap()
536     }
iter_then_list(&self) -> ExecListIter<nir_cf_node>537     fn iter_then_list(&self) -> ExecListIter<nir_cf_node> {
538         ExecListIter::new(&self.then_list, offset_of!(nir_cf_node, node))
539     }
iter_else_list(&self) -> ExecListIter<nir_cf_node>540     fn iter_else_list(&self) -> ExecListIter<nir_cf_node> {
541         ExecListIter::new(&self.else_list, offset_of!(nir_cf_node, node))
542     }
543 }
544 
545 pub trait NirLoop {
iter_body(&self) -> ExecListIter<nir_cf_node>546     fn iter_body(&self) -> ExecListIter<nir_cf_node>;
547 }
548 
549 impl NirLoop for nir_loop {
iter_body(&self) -> ExecListIter<nir_cf_node>550     fn iter_body(&self) -> ExecListIter<nir_cf_node> {
551         ExecListIter::new(&self.body, offset_of!(nir_cf_node, node))
552     }
553 }
554 
555 pub trait NirCfNode {
as_block(&self) -> Option<&nir_block>556     fn as_block(&self) -> Option<&nir_block>;
as_if(&self) -> Option<&nir_if>557     fn as_if(&self) -> Option<&nir_if>;
as_loop(&self) -> Option<&nir_loop>558     fn as_loop(&self) -> Option<&nir_loop>;
559 }
560 
561 impl NirCfNode for nir_cf_node {
as_block(&self) -> Option<&nir_block>562     fn as_block(&self) -> Option<&nir_block> {
563         if self.type_ == nir_cf_node_block {
564             Some(unsafe { &*(self as *const nir_cf_node as *const nir_block) })
565         } else {
566             None
567         }
568     }
569 
as_if(&self) -> Option<&nir_if>570     fn as_if(&self) -> Option<&nir_if> {
571         if self.type_ == nir_cf_node_if {
572             Some(unsafe { &*(self as *const nir_cf_node as *const nir_if) })
573         } else {
574             None
575         }
576     }
577 
as_loop(&self) -> Option<&nir_loop>578     fn as_loop(&self) -> Option<&nir_loop> {
579         if self.type_ == nir_cf_node_loop {
580             Some(unsafe { &*(self as *const nir_cf_node as *const nir_loop) })
581         } else {
582             None
583         }
584     }
585 }
586 
587 pub trait NirFunctionImpl {
iter_body(&self) -> ExecListIter<nir_cf_node>588     fn iter_body(&self) -> ExecListIter<nir_cf_node>;
end_block(&self) -> &nir_block589     fn end_block(&self) -> &nir_block;
function(&self) -> &nir_function590     fn function(&self) -> &nir_function;
591 }
592 
593 impl NirFunctionImpl for nir_function_impl {
iter_body(&self) -> ExecListIter<nir_cf_node>594     fn iter_body(&self) -> ExecListIter<nir_cf_node> {
595         ExecListIter::new(&self.body, offset_of!(nir_cf_node, node))
596     }
597 
end_block(&self) -> &nir_block598     fn end_block(&self) -> &nir_block {
599         unsafe { NonNull::new(self.end_block).unwrap().as_ref() }
600     }
601 
function(&self) -> &nir_function602     fn function(&self) -> &nir_function {
603         unsafe { self.function.as_ref() }.unwrap()
604     }
605 }
606 
607 pub trait NirFunction {
get_impl(&self) -> Option<&nir_function_impl>608     fn get_impl(&self) -> Option<&nir_function_impl>;
609 }
610 
611 impl NirFunction for nir_function {
get_impl(&self) -> Option<&nir_function_impl>612     fn get_impl(&self) -> Option<&nir_function_impl> {
613         unsafe { self.impl_.as_ref() }
614     }
615 }
616 
617 pub trait NirShader {
iter_functions(&self) -> ExecListIter<nir_function>618     fn iter_functions(&self) -> ExecListIter<nir_function>;
iter_variables(&self) -> ExecListIter<nir_variable>619     fn iter_variables(&self) -> ExecListIter<nir_variable>;
620 }
621 
622 impl NirShader for nir_shader {
iter_functions(&self) -> ExecListIter<nir_function>623     fn iter_functions(&self) -> ExecListIter<nir_function> {
624         ExecListIter::new(&self.functions, offset_of!(nir_function, node))
625     }
626 
iter_variables(&self) -> ExecListIter<nir_variable>627     fn iter_variables(&self) -> ExecListIter<nir_variable> {
628         ExecListIter::new(&self.variables, offset_of!(nir_variable, node))
629     }
630 }
631