Emit a WebAssembly load.
(
&mut self,
arg: &MemArg,
target_type: WasmValType,
kind: LoadKind,
)
| 1329 | |
| 1330 | /// Emit a WebAssembly load. |
| 1331 | pub fn emit_wasm_load( |
| 1332 | &mut self, |
| 1333 | arg: &MemArg, |
| 1334 | target_type: WasmValType, |
| 1335 | kind: LoadKind, |
| 1336 | ) -> Result<()> { |
| 1337 | let emit_load = |this: &mut Self, dst, addr, kind| -> Result<()> { |
| 1338 | let src = this.masm.address_at_reg(addr, 0)?; |
| 1339 | this.masm.wasm_load(src, writable!(dst), kind)?; |
| 1340 | this.context |
| 1341 | .stack |
| 1342 | .push(TypedReg::new(target_type, dst).into()); |
| 1343 | this.context.free_reg(addr); |
| 1344 | Ok(()) |
| 1345 | }; |
| 1346 | |
| 1347 | let memory_index = MemoryIndex::from_u32(arg.memory); |
| 1348 | let heap = self.env.resolve_heap(memory_index); |
| 1349 | |
| 1350 | // Ensure that the destination register is not allocated if |
| 1351 | // `emit_compute_heap_address` does not return an address. |
| 1352 | match kind { |
| 1353 | LoadKind::VectorLane(_) => { |
| 1354 | // Destination vector register is at the top of the stack and |
| 1355 | // `emit_compute_heap_address` expects an integer register |
| 1356 | // containing the address to load to be at the top of the stack. |
| 1357 | let dst = self.context.pop_to_reg(self.masm, None)?; |
| 1358 | let addr = |
| 1359 | self.emit_compute_heap_address(&heap, &arg, kind.derive_operand_size())?; |
| 1360 | if let Some(addr) = addr { |
| 1361 | emit_load(self, dst.reg, addr, kind)?; |
| 1362 | } else { |
| 1363 | self.context.free_reg(dst); |
| 1364 | } |
| 1365 | } |
| 1366 | _ => { |
| 1367 | let maybe_addr = match kind { |
| 1368 | LoadKind::Atomic(_, _) => self.emit_compute_heap_address_align_checked( |
| 1369 | &heap, |
| 1370 | &arg, |
| 1371 | kind.derive_operand_size(), |
| 1372 | )?, |
| 1373 | _ => self.emit_compute_heap_address(&heap, &arg, kind.derive_operand_size())?, |
| 1374 | }; |
| 1375 | |
| 1376 | if let Some(addr) = maybe_addr { |
| 1377 | let dst = match target_type { |
| 1378 | WasmValType::I32 | WasmValType::I64 => self.context.any_gpr(self.masm)?, |
| 1379 | WasmValType::F32 | WasmValType::F64 => self.context.any_fpr(self.masm)?, |
| 1380 | WasmValType::V128 => self.context.reg_for_type(target_type, self.masm)?, |
| 1381 | _ => bail!(CodeGenError::unsupported_wasm_type()), |
| 1382 | }; |
| 1383 | |
| 1384 | emit_load(self, dst, addr, kind)?; |
| 1385 | } |
| 1386 | } |
| 1387 | } |
| 1388 |
no test coverage detected