diff --git a/src/nouveau/compiler/nak/nir.rs b/src/nouveau/compiler/nak/nir.rs index 4ba27a5c54e..b38c4bfb88d 100644 --- a/src/nouveau/compiler/nak/nir.rs +++ b/src/nouveau/compiler/nak/nir.rs @@ -33,6 +33,7 @@ macro_rules! offset_of { pub struct ExecListIter<'a, T> { n: &'a exec_node, offset: usize, + rev: bool, _marker: PhantomData, } @@ -41,14 +42,26 @@ impl<'a, T> ExecListIter<'a, T> { Self { n: &l.head_sentinel, offset: offset, + rev: false, _marker: PhantomData, } } - fn at(n: &'a exec_node, offset: usize) -> Self { + #[allow(dead_code)] + fn new_rev(l: &'a exec_list, offset: usize) -> Self { + Self { + n: &l.tail_sentinel, + offset: offset, + rev: true, + _marker: PhantomData, + } + } + + fn at(n: &'a exec_node, offset: usize, rev: bool) -> Self { Self { n, offset: offset, + rev: rev, _marker: PhantomData, } } @@ -58,7 +71,12 @@ impl<'a, T: 'a> Iterator for ExecListIter<'a, T> { type Item = &'a T; fn next(&mut self) -> Option { - self.n = unsafe { &*self.n.next }; + if self.rev { + self.n = unsafe { &*self.n.prev }; + } else { + self.n = unsafe { &*self.n.next }; + } + if self.n.next.is_null() { None } else { @@ -546,6 +564,7 @@ pub trait NirBlock { fn iter_instr_list(&self) -> ExecListIter; fn successors(&self) -> [Option<&nir_block>; 2]; fn following_if(&self) -> Option<&nir_if>; + fn following_loop(&self) -> Option<&nir_loop>; } impl NirBlock for nir_block { @@ -564,6 +583,11 @@ impl NirBlock for nir_block { let self_ptr = self as *const _ as *mut _; unsafe { nir_block_get_following_if(self_ptr).as_ref() } } + + fn following_loop(&self) -> Option<&nir_loop> { + let self_ptr = self as *const _ as *mut _; + unsafe { nir_block_get_following_loop(self_ptr).as_ref() } + } } pub trait NirIf { @@ -571,6 +595,7 @@ pub trait NirIf { fn first_else_block(&self) -> &nir_block; fn iter_then_list(&self) -> ExecListIter; fn iter_else_list(&self) -> ExecListIter; + fn following_block(&self) -> &nir_block; } impl NirIf for nir_if { @@ -586,16 +611,24 @@ impl NirIf for nir_if { fn iter_else_list(&self) -> ExecListIter { ExecListIter::new(&self.else_list, offset_of!(nir_cf_node, node)) } + fn following_block(&self) -> &nir_block { + self.cf_node.next().unwrap().as_block().unwrap() + } } pub trait NirLoop { fn iter_body(&self) -> ExecListIter; + fn following_block(&self) -> &nir_block; } impl NirLoop for nir_loop { fn iter_body(&self) -> ExecListIter { ExecListIter::new(&self.body, offset_of!(nir_cf_node, node)) } + + fn following_block(&self) -> &nir_block { + self.cf_node.next().unwrap().as_block().unwrap() + } } pub trait NirCfNode { @@ -603,6 +636,7 @@ pub trait NirCfNode { fn as_if(&self) -> Option<&nir_if>; fn as_loop(&self) -> Option<&nir_loop>; fn next(&self) -> Option<&nir_cf_node>; + fn prev(&self) -> Option<&nir_cf_node>; } impl NirCfNode for nir_cf_node { @@ -632,7 +666,13 @@ impl NirCfNode for nir_cf_node { fn next(&self) -> Option<&nir_cf_node> { let mut iter: ExecListIter = - ExecListIter::at(&self.node, offset_of!(nir_cf_node, node)); + ExecListIter::at(&self.node, offset_of!(nir_cf_node, node), false); + iter.next() + } + + fn prev(&self) -> Option<&nir_cf_node> { + let mut iter: ExecListIter = + ExecListIter::at(&self.node, offset_of!(nir_cf_node, node), true); iter.next() } }