From 3ebeee91662f78b99bc175f3eb4a92a5398293eb Mon Sep 17 00:00:00 2001 From: Faith Ekstrand Date: Tue, 30 Jul 2024 17:34:38 -0500 Subject: [PATCH] compiler/rust/nir: Implement NIR types directly Reviewed-by: Christian Gmeiner Part-of: --- src/compiler/rust/nir.rs | 398 +++++++++++++-------------------------- 1 file changed, 127 insertions(+), 271 deletions(-) diff --git a/src/compiler/rust/nir.rs b/src/compiler/rust/nir.rs index bdd85655e62..a780f9036b0 100644 --- a/src/compiler/rust/nir.rs +++ b/src/compiler/rust/nir.rs @@ -91,28 +91,34 @@ impl<'a, T: 'a> Iterator for ExecListIter<'a, T> { } } -pub trait NirDef { - fn parent_instr(&self) -> &nir_instr; - fn components_read(&self) -> nir_component_mask_t; - fn all_uses_are_fsat(&self) -> bool; -} - -impl NirDef for nir_def { - fn parent_instr(&self) -> &nir_instr { +impl nir_def { + pub fn parent_instr(&self) -> &nir_instr { unsafe { NonNull::new(self.parent_instr).unwrap().as_ref() } } - fn components_read(&self) -> nir_component_mask_t { + pub fn components_read(&self) -> nir_component_mask_t { unsafe { nir_def_components_read(self as *const _) } } - fn all_uses_are_fsat(&self) -> bool { + pub fn all_uses_are_fsat(&self) -> bool { unsafe { nir_def_all_uses_are_fsat(self as *const _) } } } -pub trait AsConst: NirValue { - fn as_load_const(&self) -> Option<&nir_load_const_instr>; +pub trait AsDef { + fn as_def(&self) -> &nir_def; + + fn bit_size(&self) -> u8 { + self.as_def().bit_size + } + + fn num_components(&self) -> u8 { + self.as_def().num_components + } + + fn as_load_const(&self) -> Option<&nir_load_const_instr> { + self.as_def().parent_instr().as_load_const() + } fn is_const(&self) -> bool { self.as_load_const().is_some() @@ -169,69 +175,25 @@ pub trait AsConst: NirValue { } } -impl AsConst for nir_def { - fn as_load_const(&self) -> Option<&nir_load_const_instr> { - self.parent_instr().as_load_const() - } -} - -impl AsConst for nir_src { - fn as_load_const(&self) -> Option<&nir_load_const_instr> { - self.as_def().parent_instr().as_load_const() - } -} - -pub trait AsDef { - fn as_def(&self) -> &nir_def; -} - impl AsDef for nir_def { fn as_def(&self) -> &nir_def { self } } -pub trait NirValue { - fn bit_size(&self) -> u8; - fn num_components(&self) -> u8; -} - -impl NirValue for T { - fn bit_size(&self) -> u8 { - self.as_def().bit_size - } - - fn num_components(&self) -> u8 { - self.as_def().num_components - } -} - impl AsDef for nir_src { fn as_def(&self) -> &nir_def { - unsafe { &*self.ssa } + unsafe { NonNull::new(self.ssa).unwrap().as_ref() } } } -pub trait NirSrcsAsSlice { - fn srcs_as_slice(&self) -> &[S]; - - fn get_src(&self, idx: usize) -> &S { - &self.srcs_as_slice()[idx] - } -} - -pub trait NirAluInstr { - fn info(&self) -> &nir_op_info; - fn src_components(&self, src_idx: u8) -> u8; -} - -impl NirAluInstr for nir_alu_instr { - fn info(&self) -> &nir_op_info { +impl nir_alu_instr { + pub fn info(&self) -> &'static nir_op_info { let info_idx: usize = self.op.try_into().unwrap(); unsafe { &nir_op_infos[info_idx] } } - fn src_components(&self, src_idx: u8) -> u8 { + pub fn src_components(&self, src_idx: u8) -> u8 { assert!(src_idx < self.info().num_inputs); unsafe { nir_ssa_alu_instr_src_components(self as *const _, src_idx.into()) @@ -239,142 +201,119 @@ impl NirAluInstr for nir_alu_instr { .unwrap() } } -} -impl NirSrcsAsSlice for nir_alu_instr { - fn srcs_as_slice(&self) -> &[nir_alu_src] { + pub fn srcs_as_slice(&self) -> &[nir_alu_src] { unsafe { self.src .as_slice(self.info().num_inputs.try_into().unwrap()) } } -} -impl AsDef for nir_alu_src { - fn as_def(&self) -> &nir_def { - self.src.as_def() + pub fn get_src(&self, idx: usize) -> &nir_alu_src { + &self.srcs_as_slice()[idx] } } -pub trait NirAluInfo { - fn name(&self) -> &'static str; -} - -impl NirAluInfo for nir_op_info { - fn name(&self) -> &'static str { +impl nir_op_info { + pub fn name(&self) -> &'static str { unsafe { CStr::from_ptr(self.name).to_str().expect("Invalid UTF-8") } } } -pub trait NirAluSrc { - fn comp_as_int(&self, comp: u8) -> Option; - fn comp_as_uint(&self, comp: u8) -> Option; -} +impl nir_alu_src { + pub fn bit_size(&self) -> u8 { + self.src.bit_size() + } -impl NirAluSrc for nir_alu_src { - fn comp_as_int(&self, comp: u8) -> Option { + pub fn comp_as_int(&self, comp: u8) -> Option { self.src.comp_as_int(self.swizzle[usize::from(comp)]) } - fn comp_as_uint(&self, comp: u8) -> Option { + pub fn comp_as_uint(&self, comp: u8) -> Option { self.src.comp_as_uint(self.swizzle[usize::from(comp)]) } } -impl NirSrcsAsSlice for nir_tex_instr { - fn srcs_as_slice(&self) -> &[nir_tex_src] { +impl nir_tex_instr { + pub fn srcs_as_slice(&self) -> &[nir_tex_src] { unsafe { std::slice::from_raw_parts(self.src, self.num_srcs as usize) } } + + pub fn get_src(&self, idx: usize) -> &nir_tex_src { + &self.srcs_as_slice()[idx] + } } -pub trait NirIntrinsicInstr { - fn info(&self) -> &nir_intrinsic_info; - fn get_const_index(&self, name: u32) -> u32; - fn base(&self) -> i32; - fn range_base(&self) -> i32; - fn range(&self) -> i32; - fn write_mask(&self) -> u32; - fn stream_id(&self) -> u32; - fn component(&self) -> u32; - fn interp_mode(&self) -> u32; - fn reduction_op(&self) -> nir_op; - fn cluster_size(&self) -> u32; - fn image_dim(&self) -> glsl_sampler_dim; - fn image_array(&self) -> bool; - fn access(&self) -> gl_access_qualifier; - fn align(&self) -> u32; - fn align_mul(&self) -> u32; - fn align_offset(&self) -> u32; - fn execution_scope(&self) -> mesa_scope; - fn memory_scope(&self) -> mesa_scope; - fn memory_semantics(&self) -> nir_memory_semantics; - fn memory_modes(&self) -> nir_variable_mode; - fn flags(&self) -> u32; - fn atomic_op(&self) -> nir_atomic_op; -} - -impl NirIntrinsicInstr for nir_intrinsic_instr { - fn info(&self) -> &nir_intrinsic_info { +impl nir_intrinsic_instr { + pub fn info(&self) -> &'static nir_intrinsic_info { let info_idx: usize = self.intrinsic.try_into().unwrap(); unsafe { &nir_intrinsic_infos[info_idx] } } - fn get_const_index(&self, name: u32) -> u32 { + pub fn srcs_as_slice(&self) -> &[nir_src] { + unsafe { self.src.as_slice(self.info().num_srcs.try_into().unwrap()) } + } + + pub fn get_src(&self, idx: usize) -> &nir_src { + &self.srcs_as_slice()[idx] + } + + pub fn get_const_index(&self, name: u32) -> u32 { let name: usize = name.try_into().unwrap(); let idx = self.info().index_map[name]; assert!(idx > 0); self.const_index[usize::from(idx - 1)] as u32 } - fn base(&self) -> i32 { + pub fn base(&self) -> i32 { self.get_const_index(NIR_INTRINSIC_BASE) as i32 } - fn range_base(&self) -> i32 { + pub fn range_base(&self) -> i32 { self.get_const_index(NIR_INTRINSIC_RANGE_BASE) as i32 } - fn range(&self) -> i32 { + pub fn range(&self) -> i32 { self.get_const_index(NIR_INTRINSIC_RANGE) as i32 } - fn write_mask(&self) -> u32 { + pub fn write_mask(&self) -> u32 { self.get_const_index(NIR_INTRINSIC_WRITE_MASK) } - fn stream_id(&self) -> u32 { + pub fn stream_id(&self) -> u32 { self.get_const_index(NIR_INTRINSIC_STREAM_ID) } - fn component(&self) -> u32 { + pub fn component(&self) -> u32 { self.get_const_index(NIR_INTRINSIC_COMPONENT) } - fn interp_mode(&self) -> u32 { + pub fn interp_mode(&self) -> u32 { self.get_const_index(NIR_INTRINSIC_INTERP_MODE) } - fn reduction_op(&self) -> nir_op { + pub fn reduction_op(&self) -> nir_op { self.get_const_index(NIR_INTRINSIC_REDUCTION_OP) as nir_op } - fn cluster_size(&self) -> u32 { + pub fn cluster_size(&self) -> u32 { self.get_const_index(NIR_INTRINSIC_CLUSTER_SIZE) } - fn image_dim(&self) -> glsl_sampler_dim { + pub fn image_dim(&self) -> glsl_sampler_dim { self.get_const_index(NIR_INTRINSIC_IMAGE_DIM) as glsl_sampler_dim } - fn image_array(&self) -> bool { + pub fn image_array(&self) -> bool { self.get_const_index(NIR_INTRINSIC_IMAGE_ARRAY) != 0 } - fn access(&self) -> gl_access_qualifier { + pub fn access(&self) -> gl_access_qualifier { self.get_const_index(NIR_INTRINSIC_ACCESS) as gl_access_qualifier } - fn align(&self) -> u32 { + pub fn align(&self) -> u32 { let mul = self.align_mul(); let offset = self.align_offset(); assert!(offset < mul); @@ -385,116 +324,75 @@ impl NirIntrinsicInstr for nir_intrinsic_instr { } } - fn align_mul(&self) -> u32 { + pub fn align_mul(&self) -> u32 { self.get_const_index(NIR_INTRINSIC_ALIGN_MUL) } - fn align_offset(&self) -> u32 { + pub fn align_offset(&self) -> u32 { self.get_const_index(NIR_INTRINSIC_ALIGN_OFFSET) } - fn execution_scope(&self) -> mesa_scope { + pub fn execution_scope(&self) -> mesa_scope { self.get_const_index(NIR_INTRINSIC_EXECUTION_SCOPE) } - fn memory_scope(&self) -> mesa_scope { + pub fn memory_scope(&self) -> mesa_scope { self.get_const_index(NIR_INTRINSIC_MEMORY_SCOPE) } - fn memory_semantics(&self) -> nir_memory_semantics { + pub fn memory_semantics(&self) -> nir_memory_semantics { self.get_const_index(NIR_INTRINSIC_MEMORY_SEMANTICS) } - fn memory_modes(&self) -> nir_variable_mode { + pub fn memory_modes(&self) -> nir_variable_mode { self.get_const_index(NIR_INTRINSIC_MEMORY_MODES) } - fn flags(&self) -> u32 { + pub fn flags(&self) -> u32 { self.get_const_index(NIR_INTRINSIC_FLAGS) } - fn atomic_op(&self) -> nir_atomic_op { + pub fn atomic_op(&self) -> nir_atomic_op { self.get_const_index(NIR_INTRINSIC_ATOMIC_OP) as nir_atomic_op } } -impl NirSrcsAsSlice for nir_intrinsic_instr { - fn srcs_as_slice(&self) -> &[nir_src] { - unsafe { - let info = nir_intrinsic_infos[self.intrinsic as usize]; - self.src.as_slice(info.num_srcs as usize) - } - } -} - -pub trait NirIntrinsicInfo { - fn name(&self) -> &'static str; -} - -impl NirIntrinsicInfo for nir_intrinsic_info { - fn name(&self) -> &'static str { +impl nir_intrinsic_info { + pub fn name(&self) -> &'static str { unsafe { CStr::from_ptr(self.name).to_str().expect("Invalid UTF-8") } } } -pub trait NirLoadConstInstr { - fn values(&self) -> &[nir_const_value]; -} - -impl NirLoadConstInstr for nir_load_const_instr { - fn values(&self) -> &[nir_const_value] { +impl nir_load_const_instr { + pub fn values(&self) -> &[nir_const_value] { unsafe { self.value.as_slice(self.def.num_components as usize) } } } -pub trait NirPhiSrc { - fn pred(&self) -> &nir_block; -} - -impl NirPhiSrc for nir_phi_src { - fn pred(&self) -> &nir_block { +impl nir_phi_src { + pub fn pred(&self) -> &nir_block { unsafe { NonNull::new(self.pred).unwrap().as_ref() } } } -pub trait NirPhiInstr { - fn iter_srcs(&self) -> ExecListIter; -} - -impl NirPhiInstr for nir_phi_instr { - fn iter_srcs(&self) -> ExecListIter { +impl nir_phi_instr { + pub fn iter_srcs(&self) -> ExecListIter { ExecListIter::new(&self.srcs, offset_of!(nir_phi_src, node)) } } -pub trait NirJumpInstr { - fn target(&self) -> Option<&nir_block>; - fn else_target(&self) -> Option<&nir_block>; -} - -impl NirJumpInstr for nir_jump_instr { - fn target(&self) -> Option<&nir_block> { +impl nir_jump_instr { + pub fn target(&self) -> Option<&nir_block> { NonNull::new(self.target).map(|b| unsafe { b.as_ref() }) } - fn else_target(&self) -> Option<&nir_block> { + pub fn else_target(&self) -> Option<&nir_block> { NonNull::new(self.else_target).map(|b| unsafe { b.as_ref() }) } } -pub trait NirInstr { - fn as_alu(&self) -> Option<&nir_alu_instr>; - fn as_jump(&self) -> Option<&nir_jump_instr>; - fn as_tex(&self) -> Option<&nir_tex_instr>; - fn as_intrinsic(&self) -> Option<&nir_intrinsic_instr>; - fn as_load_const(&self) -> Option<&nir_load_const_instr>; - fn as_undef(&self) -> Option<&nir_undef_instr>; - fn as_phi(&self) -> Option<&nir_phi_instr>; - fn def(&self) -> Option<&nir_def>; -} - -impl NirInstr for nir_instr { - fn as_alu(&self) -> Option<&nir_alu_instr> { +impl nir_instr { + pub fn as_alu(&self) -> Option<&nir_alu_instr> { if self.type_ == nir_instr_type_alu { let p = self as *const nir_instr; Some(unsafe { &*(p as *const nir_alu_instr) }) @@ -503,7 +401,7 @@ impl NirInstr for nir_instr { } } - fn as_jump(&self) -> Option<&nir_jump_instr> { + pub fn as_jump(&self) -> Option<&nir_jump_instr> { if self.type_ == nir_instr_type_jump { let p = self as *const nir_instr; Some(unsafe { &*(p as *const nir_jump_instr) }) @@ -512,7 +410,7 @@ impl NirInstr for nir_instr { } } - fn as_tex(&self) -> Option<&nir_tex_instr> { + pub fn as_tex(&self) -> Option<&nir_tex_instr> { if self.type_ == nir_instr_type_tex { let p = self as *const nir_instr; Some(unsafe { &*(p as *const nir_tex_instr) }) @@ -521,7 +419,7 @@ impl NirInstr for nir_instr { } } - fn as_intrinsic(&self) -> Option<&nir_intrinsic_instr> { + pub fn as_intrinsic(&self) -> Option<&nir_intrinsic_instr> { if self.type_ == nir_instr_type_intrinsic { let p = self as *const nir_instr; Some(unsafe { &*(p as *const nir_intrinsic_instr) }) @@ -530,7 +428,7 @@ impl NirInstr for nir_instr { } } - fn as_load_const(&self) -> Option<&nir_load_const_instr> { + pub fn as_load_const(&self) -> Option<&nir_load_const_instr> { if self.type_ == nir_instr_type_load_const { let p = self as *const nir_instr; Some(unsafe { &*(p as *const nir_load_const_instr) }) @@ -539,7 +437,7 @@ impl NirInstr for nir_instr { } } - fn as_undef(&self) -> Option<&nir_undef_instr> { + pub fn as_undef(&self) -> Option<&nir_undef_instr> { if self.type_ == nir_instr_type_undef { let p = self as *const nir_instr; Some(unsafe { &*(p as *const nir_undef_instr) }) @@ -548,7 +446,7 @@ impl NirInstr for nir_instr { } } - fn as_phi(&self) -> Option<&nir_phi_instr> { + pub fn as_phi(&self) -> Option<&nir_phi_instr> { if self.type_ == nir_instr_type_phi { let p = self as *const nir_instr; Some(unsafe { &*(p as *const nir_phi_instr) }) @@ -557,7 +455,7 @@ impl NirInstr for nir_instr { } } - fn def(&self) -> Option<&nir_def> { + pub fn def(&self) -> Option<&nir_def> { unsafe { let def = nir_instr_def(self as *const _ as *mut _); NonNull::new(def).map(|d| d.as_ref()) @@ -565,98 +463,71 @@ impl NirInstr for nir_instr { } } -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>; - fn parent(&self) -> &nir_cf_node; -} - -impl NirBlock for nir_block { - fn iter_instr_list(&self) -> ExecListIter { +impl nir_block { + pub fn iter_instr_list(&self) -> ExecListIter { ExecListIter::new(&self.instr_list, offset_of!(nir_instr, node)) } - fn successors(&self) -> [Option<&nir_block>; 2] { + pub fn successors(&self) -> [Option<&nir_block>; 2] { [ NonNull::new(self.successors[0]).map(|b| unsafe { b.as_ref() }), NonNull::new(self.successors[1]).map(|b| unsafe { b.as_ref() }), ] } - fn following_if(&self) -> Option<&nir_if> { + pub fn following_if(&self) -> Option<&nir_if> { 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> { + pub 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() } } - fn parent(&self) -> &nir_cf_node { + pub fn parent(&self) -> &nir_cf_node { self.cf_node.parent().unwrap() } } -pub trait NirIf { - fn first_then_block(&self) -> &nir_block; - 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 { - fn first_then_block(&self) -> &nir_block { +impl nir_if { + pub fn first_then_block(&self) -> &nir_block { self.iter_then_list().next().unwrap().as_block().unwrap() } - fn first_else_block(&self) -> &nir_block { + + pub fn first_else_block(&self) -> &nir_block { self.iter_else_list().next().unwrap().as_block().unwrap() } - fn iter_then_list(&self) -> ExecListIter { + + pub fn iter_then_list(&self) -> ExecListIter { ExecListIter::new(&self.then_list, offset_of!(nir_cf_node, node)) } - fn iter_else_list(&self) -> ExecListIter { + + pub fn iter_else_list(&self) -> ExecListIter { ExecListIter::new(&self.else_list, offset_of!(nir_cf_node, node)) } - fn following_block(&self) -> &nir_block { + + pub fn following_block(&self) -> &nir_block { self.cf_node.next().unwrap().as_block().unwrap() } } -pub trait NirLoop { - fn iter_body(&self) -> ExecListIter; - fn first_block(&self) -> &nir_block; - fn following_block(&self) -> &nir_block; -} - -impl NirLoop for nir_loop { - fn iter_body(&self) -> ExecListIter { +impl nir_loop { + pub fn iter_body(&self) -> ExecListIter { ExecListIter::new(&self.body, offset_of!(nir_cf_node, node)) } - fn first_block(&self) -> &nir_block { + pub fn first_block(&self) -> &nir_block { self.iter_body().next().unwrap().as_block().unwrap() } - fn following_block(&self) -> &nir_block { + pub fn following_block(&self) -> &nir_block { self.cf_node.next().unwrap().as_block().unwrap() } } -pub trait NirCfNode { - fn as_block(&self) -> Option<&nir_block>; - 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>; - fn parent(&self) -> Option<&nir_cf_node>; -} - -impl NirCfNode for nir_cf_node { - fn as_block(&self) -> Option<&nir_block> { +impl nir_cf_node { + pub fn as_block(&self) -> Option<&nir_block> { if self.type_ == nir_cf_node_block { Some(unsafe { &*(self as *const nir_cf_node as *const nir_block) }) } else { @@ -664,7 +535,7 @@ impl NirCfNode for nir_cf_node { } } - fn as_if(&self) -> Option<&nir_if> { + pub fn as_if(&self) -> Option<&nir_if> { if self.type_ == nir_cf_node_if { Some(unsafe { &*(self as *const nir_cf_node as *const nir_if) }) } else { @@ -672,7 +543,7 @@ impl NirCfNode for nir_cf_node { } } - fn as_loop(&self) -> Option<&nir_loop> { + pub fn as_loop(&self) -> Option<&nir_loop> { if self.type_ == nir_cf_node_loop { Some(unsafe { &*(self as *const nir_cf_node as *const nir_loop) }) } else { @@ -680,64 +551,49 @@ impl NirCfNode for nir_cf_node { } } - fn next(&self) -> Option<&nir_cf_node> { + pub fn next(&self) -> Option<&nir_cf_node> { let mut iter: ExecListIter = ExecListIter::at(&self.node, offset_of!(nir_cf_node, node), false); iter.next() } - fn prev(&self) -> Option<&nir_cf_node> { + pub fn prev(&self) -> Option<&nir_cf_node> { let mut iter: ExecListIter = ExecListIter::at(&self.node, offset_of!(nir_cf_node, node), true); iter.next() } - fn parent(&self) -> Option<&nir_cf_node> { + pub fn parent(&self) -> Option<&nir_cf_node> { NonNull::new(self.parent).map(|b| unsafe { b.as_ref() }) } } -pub trait NirFunctionImpl { - fn iter_body(&self) -> ExecListIter; - fn end_block(&self) -> &nir_block; - fn function(&self) -> &nir_function; -} - -impl NirFunctionImpl for nir_function_impl { - fn iter_body(&self) -> ExecListIter { +impl nir_function_impl { + pub fn iter_body(&self) -> ExecListIter { ExecListIter::new(&self.body, offset_of!(nir_cf_node, node)) } - fn end_block(&self) -> &nir_block { + pub fn end_block(&self) -> &nir_block { unsafe { NonNull::new(self.end_block).unwrap().as_ref() } } - fn function(&self) -> &nir_function { + pub fn function(&self) -> &nir_function { unsafe { self.function.as_ref() }.unwrap() } } -pub trait NirFunction { - fn get_impl(&self) -> Option<&nir_function_impl>; -} - -impl NirFunction for nir_function { - fn get_impl(&self) -> Option<&nir_function_impl> { +impl nir_function { + pub fn get_impl(&self) -> Option<&nir_function_impl> { unsafe { self.impl_.as_ref() } } } -pub trait NirShader { - fn iter_functions(&self) -> ExecListIter; - fn iter_variables(&self) -> ExecListIter; -} - -impl NirShader for nir_shader { - fn iter_functions(&self) -> ExecListIter { +impl nir_shader { + pub fn iter_functions(&self) -> ExecListIter { ExecListIter::new(&self.functions, offset_of!(nir_function, node)) } - fn iter_variables(&self) -> ExecListIter { + pub fn iter_variables(&self) -> ExecListIter { ExecListIter::new(&self.variables, offset_of!(nir_variable, node)) } }