(
&mut self,
ty: Word,
ptr: SpirvValue,
indices: &[SpirvValue],
is_inbounds: bool,
)
| 120 | } |
| 121 | |
| 122 | pub fn gep_help( |
| 123 | &mut self, |
| 124 | ty: Word, |
| 125 | ptr: SpirvValue, |
| 126 | indices: &[SpirvValue], |
| 127 | is_inbounds: bool, |
| 128 | ) -> SpirvValue { |
| 129 | // The first index is an offset to the pointer, the rest are actual members. |
| 130 | // https://llvm.org/docs/GetElementPtr.html |
| 131 | // "An OpAccessChain instruction is the equivalent of an LLVM getelementptr instruction where the first index element is zero." |
| 132 | // https://github.com/gpuweb/gpuweb/issues/33 |
| 133 | let mut result_indices = Vec::with_capacity(indices.len() - 1); |
| 134 | let mut result_pointee_type = match self.lookup_type(ptr.ty) { |
| 135 | SpirvType::Pointer { pointee } => { |
| 136 | assert_ty_eq!(self, ty, pointee); |
| 137 | pointee |
| 138 | } |
| 139 | other_type => self.fatal(&format!( |
| 140 | "GEP first deref not implemented for type {other_type:?}" |
| 141 | )), |
| 142 | }; |
| 143 | for index in indices.iter().cloned().skip(1) { |
| 144 | result_indices.push(index.def(self)); |
| 145 | result_pointee_type = match self.lookup_type(result_pointee_type) { |
| 146 | SpirvType::Array { element, .. } | SpirvType::RuntimeArray { element } => element, |
| 147 | _ => self.fatal(&format!( |
| 148 | "GEP not implemented for type {}", |
| 149 | self.debug_type(result_pointee_type) |
| 150 | )), |
| 151 | }; |
| 152 | } |
| 153 | let result_type = SpirvType::Pointer { |
| 154 | pointee: result_pointee_type, |
| 155 | } |
| 156 | .def(self.span(), self); |
| 157 | |
| 158 | let ptr_id = ptr.def(self); |
| 159 | if let Some((original_ptr, mut original_indices)) = self.find_access_chain(ptr_id) { |
| 160 | // Transform the following: |
| 161 | // OpAccessChain original_ptr [a, b, c] |
| 162 | // OpPtrAccessChain ptr base [d, e, f] |
| 163 | // into |
| 164 | // OpAccessChain original_ptr [a, b, c + base, d, e, f] |
| 165 | // to remove the need for OpPtrAccessChain |
| 166 | let last = original_indices.last_mut().unwrap(); |
| 167 | *last = self |
| 168 | .add(last.with_type(indices[0].ty), indices[0]) |
| 169 | .def(self); |
| 170 | original_indices.append(&mut result_indices); |
| 171 | let zero = self.constant_int(indices[0].ty, 0); |
| 172 | self.emit_access_chain( |
| 173 | result_type, |
| 174 | original_ptr, |
| 175 | zero, |
| 176 | original_indices, |
| 177 | is_inbounds, |
| 178 | ) |
| 179 | } else { |
no test coverage detected