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

Method emit_table_grow

winch/codegen/src/codegen/mod.rs:697–770  ·  view source on GitHub ↗

Emit the `table.grow` operation.

(&mut self, table_index: TableIndex)

Source from the content-addressed store, hash-verified

695
696 /// Emit the `table.grow` operation.
697 pub fn emit_table_grow(&mut self, table_index: TableIndex) -> Result<()> {
698 let ptr_type = self.env.ptr_type();
699 let idx_type = self.env.table(table_index).idx_type;
700
701 // Duplicate the `delta` argument on the stack since we'll need it at
702 // the end if growth succeeds.
703 let delta = self.context.pop_to_reg(self.masm, None)?;
704 let tmp = self.context.any_gpr(self.masm)?;
705 self.masm
706 .mov(writable!(tmp), delta.reg.into(), delta.ty.try_into()?)?;
707 self.context.stack.push(TypedReg::new(delta.ty, tmp).into());
708 self.context.stack.push(delta.into());
709
710 // Invoke the `table.grow` builtin on the host which will return whether
711 // the growth succeeded, and if so where it's located.
712 let at = self.context.stack.ensure_index_at(1)?;
713 let builtin = self.env.builtins.table_grow::<M::ABI>()?;
714 let builtin = self.prepare_builtin_defined_table_arg(table_index, at, builtin)?;
715 FnCall::emit::<M>(&mut self.env, self.masm, &mut self.context, builtin)?;
716
717 // Pop everything that's on the stack now. The builtin took `delta` and
718 // pushed a result, and then peel off our duplicate of `delta` plus the
719 // initialization element of `table.grow` itself.
720 let result = self.context.pop_to_reg(self.masm, None)?;
721 let len = self.context.pop_to_reg(self.masm, None)?;
722 let init = self.context.pop_to_reg(self.masm, None)?;
723
724 // Save a copy of `result` on the stack since we'll need it after
725 // `table.fill` is done.
726 let tmp_result = self.context.any_gpr(self.masm)?;
727 self.masm.mov(
728 writable!(tmp_result),
729 result.reg.into(),
730 result.ty.try_into()?,
731 )?;
732 self.context
733 .stack
734 .push(TypedReg::new(result.ty, tmp_result).into());
735
736 // Test if the result of growth is -1. If it is, then we're done.
737 // Otherwise fall through to `table.fill`.
738 let done = self.masm.get_label()?;
739 self.masm.branch(
740 IntCmpKind::Eq,
741 result.reg,
742 RegImm::i64(-1),
743 done,
744 OperandSize::S64,
745 )?;
746
747 // Prepare the arguments for `table.fill` in the order the wasm
748 // instruction expects.
749 self.context.stack.push(result.into());
750 self.context.stack.push(init.into());
751 self.context.stack.push(len.into());
752 self.emit_table_fill(table_index)?;
753
754 self.masm.bind(done)?;

Callers 1

visit_table_growMethod · 0.80

Calls 15

i64Function · 0.85
OkFunction · 0.85
pop_to_regMethod · 0.80
any_gprMethod · 0.80
ensure_index_atMethod · 0.80
emit_table_fillMethod · 0.80
newFunction · 0.50
ptr_typeMethod · 0.45
tableMethod · 0.45
movMethod · 0.45
try_intoMethod · 0.45

Tested by

no test coverage detected