MCPcopy Create free account
hub / github.com/bytecodealliance/wasmtime / emit_compute_table_elem_addr

Method emit_compute_table_elem_addr

winch/codegen/src/codegen/mod.rs:1420–1484  ·  view source on GitHub ↗

Loads the address of the table element at a given index. Returns the address of the table element using the provided register as base.

(
        &mut self,
        index: Reg,
        base: Reg,
        table_data: &TableData,
    )

Source from the content-addressed store, hash-verified

1418 /// Loads the address of the table element at a given index. Returns the
1419 /// address of the table element using the provided register as base.
1420 pub fn emit_compute_table_elem_addr(
1421 &mut self,
1422 index: Reg,
1423 base: Reg,
1424 table_data: &TableData,
1425 ) -> Result<M::Address> {
1426 let bound = self.context.any_gpr(self.masm)?;
1427 let tmp = self.context.any_gpr(self.masm)?;
1428 let ptr_size: OperandSize = self.env.ptr_type().try_into()?;
1429
1430 if let Some(offset) = table_data.import_from {
1431 // If the table data declares a particular offset base,
1432 // load the address into a register to further use it as
1433 // the table address.
1434 self.masm
1435 .load_ptr(self.masm.address_at_vmctx(offset)?, writable!(base))?;
1436 } else {
1437 // Else, simply move the vmctx register into the addr register as
1438 // the base to calculate the table address.
1439 self.masm.mov(writable!(base), vmctx!(M).into(), ptr_size)?;
1440 };
1441
1442 // OOB check.
1443 let bound_addr = self
1444 .masm
1445 .address_at_reg(base, table_data.current_elems_offset)?;
1446 let bound_size = table_data.current_elements_size;
1447 self.masm.load(bound_addr, writable!(bound), bound_size)?;
1448 self.masm.cmp(index, bound.into(), bound_size)?;
1449 self.masm
1450 .trapif(IntCmpKind::GeU, TRAP_TABLE_OUT_OF_BOUNDS)?;
1451
1452 // Move the index into the scratch register to calculate the table
1453 // element address.
1454 // Moving the value of the index register to the scratch register
1455 // also avoids overwriting the context of the index register.
1456 self.masm.with_scratch::<IntScratch, _>(|masm, scratch| {
1457 masm.mov(scratch.writable(), index.into(), bound_size)?;
1458 masm.mul(
1459 scratch.writable(),
1460 scratch.inner(),
1461 RegImm::i32(table_data.element_size.bytes() as i32),
1462 table_data.element_size,
1463 )?;
1464 masm.load_ptr(
1465 masm.address_at_reg(base, table_data.offset)?,
1466 writable!(base),
1467 )?;
1468 // Copy the value of the table base into a temporary register
1469 // so that we can use it later in case of a misspeculation.
1470 masm.mov(writable!(tmp), base.into(), ptr_size)?;
1471 // Calculate the address of the table element.
1472 masm.add(writable!(base), base, scratch.inner().into(), ptr_size)
1473 })?;
1474 if self.env.table_access_spectre_mitigation() {
1475 // Perform a bounds check and override the value of the
1476 // table element address in case the index is out of bounds.
1477 self.masm.cmp(index, bound.into(), bound_size)?;

Callers 2

emit_table_getMethod · 0.80
emit_table_setMethod · 0.80

Calls 15

any_gprMethod · 0.80
free_regMethod · 0.80
try_intoMethod · 0.45
ptr_typeMethod · 0.45
load_ptrMethod · 0.45
address_at_vmctxMethod · 0.45
movMethod · 0.45
address_at_regMethod · 0.45
loadMethod · 0.45
cmpMethod · 0.45
trapifMethod · 0.45

Tested by

no test coverage detected