(&mut self, table_index: TableIndex)
| 569 | } |
| 570 | |
| 571 | pub fn emit_table_get(&mut self, table_index: TableIndex) -> Result<()> { |
| 572 | let table = self.env.table(table_index); |
| 573 | let heap_type = table.ref_type.heap_type; |
| 574 | ensure!( |
| 575 | heap_type == WasmHeapType::Func, |
| 576 | CodeGenError::unsupported_wasm_type() |
| 577 | ); |
| 578 | ensure!( |
| 579 | self.tunables.table_lazy_init, |
| 580 | CodeGenError::unsupported_table_eager_init() |
| 581 | ); |
| 582 | let table_data = self.env.resolve_table_data(table_index); |
| 583 | let ptr_type = self.env.ptr_type(); |
| 584 | let builtin = self.env.builtins.table_get_lazy_init_func_ref::<M::ABI>()?; |
| 585 | |
| 586 | // Request the builtin's result register and use it to hold the table |
| 587 | // element value. We preemptively spill and request this register to |
| 588 | // avoid conflict at the control flow merge below. Requesting the result |
| 589 | // register is safe since we know ahead-of-time the builtin's signature. |
| 590 | self.context.spill(self.masm)?; |
| 591 | let elem_value: Reg = self.context.reg( |
| 592 | builtin.sig().results.unwrap_singleton().unwrap_reg(), |
| 593 | self.masm, |
| 594 | )?; |
| 595 | |
| 596 | let index = self.context.pop_to_reg(self.masm, None)?; |
| 597 | let base = self.context.any_gpr(self.masm)?; |
| 598 | |
| 599 | let elem_addr = self.emit_compute_table_elem_addr(index.into(), base, &table_data)?; |
| 600 | self.masm.load_ptr(elem_addr, writable!(elem_value))?; |
| 601 | // Free the register used as base, once we have loaded the element |
| 602 | // address into the element value register. |
| 603 | self.context.free_reg(base); |
| 604 | |
| 605 | let (defined, cont) = (self.masm.get_label()?, self.masm.get_label()?); |
| 606 | |
| 607 | // Push the built-in arguments to the stack. |
| 608 | self.context |
| 609 | .stack |
| 610 | .extend([table_index.as_u32().try_into().unwrap(), index.into()]); |
| 611 | |
| 612 | self.masm.branch( |
| 613 | IntCmpKind::Ne, |
| 614 | elem_value, |
| 615 | elem_value.into(), |
| 616 | defined, |
| 617 | ptr_type.try_into()?, |
| 618 | )?; |
| 619 | // Free the element value register. |
| 620 | // This is safe since the FnCall::emit call below, will ensure |
| 621 | // that the result register is placed on the value stack. |
| 622 | self.context.free_reg(elem_value); |
| 623 | FnCall::emit::<M>( |
| 624 | &mut self.env, |
| 625 | self.masm, |
| 626 | &mut self.context, |
| 627 | Callee::Builtin(builtin.clone()), |
| 628 | )?; |
no test coverage detected