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