Load the requested heap address into the specified destination register. This function doesn't perform any bounds checks and assumes the caller performed the right checks.
(
masm: &mut M,
heap: &HeapData,
index: Index,
offset: ImmOffset,
dst: Reg,
ptr_size: OperandSize,
)
| 191 | /// This function doesn't perform any bounds checks and assumes the caller |
| 192 | /// performed the right checks. |
| 193 | pub(crate) fn load_heap_addr_unchecked<M>( |
| 194 | masm: &mut M, |
| 195 | heap: &HeapData, |
| 196 | index: Index, |
| 197 | offset: ImmOffset, |
| 198 | dst: Reg, |
| 199 | ptr_size: OperandSize, |
| 200 | ) -> Result<()> |
| 201 | where |
| 202 | M: MacroAssembler, |
| 203 | { |
| 204 | masm.with_scratch::<IntScratch, _>(|masm, scratch| { |
| 205 | let base = if let Some(offset) = heap.import_from { |
| 206 | // If the WebAssembly memory is imported, load the address into |
| 207 | // the scratch register. |
| 208 | masm.load_ptr(masm.address_at_vmctx(offset)?, scratch.writable())?; |
| 209 | scratch.inner() |
| 210 | } else { |
| 211 | // Else if the WebAssembly memory is defined in the current module, |
| 212 | // simply use the `VMContext` as the base for subsequent operations. |
| 213 | vmctx!(M) |
| 214 | }; |
| 215 | |
| 216 | // Load the base of the memory into the `addr` register. |
| 217 | masm.load_ptr(masm.address_at_reg(base, heap.offset)?, writable!(dst)) |
| 218 | })?; |
| 219 | |
| 220 | // Start by adding the index to the heap base addr. |
| 221 | let index_typed = index.as_typed_reg(); |
| 222 | let heap_size: OperandSize = heap.index_type().try_into()?; |
| 223 | |
| 224 | // Emit a zero-extend add when dealing with 32-bit heaps to ensure |
| 225 | // that the high bits of the 64-bit values are zeroed. |
| 226 | if ptr_size == OperandSize::S64 && heap_size == OperandSize::S32 { |
| 227 | masm.add_uextend( |
| 228 | writable!(dst), |
| 229 | dst, |
| 230 | index_typed.reg, |
| 231 | OperandSize::S32, |
| 232 | ptr_size, |
| 233 | )?; |
| 234 | } else { |
| 235 | assert!(index_typed.ty == WasmValType::I64); |
| 236 | masm.add(writable!(dst), dst, index_typed.reg.into(), ptr_size)?; |
| 237 | } |
| 238 | |
| 239 | if offset.as_u32() > 0 { |
| 240 | masm.add( |
| 241 | writable!(dst), |
| 242 | dst, |
| 243 | RegImm::i64(offset.as_u32() as i64), |
| 244 | ptr_size, |
| 245 | )?; |
| 246 | } |
| 247 | Ok(()) |
| 248 | } |
no test coverage detected