pub struct CallIndirectGuards {
pub tables: Vec<TableGuards>,
}Expand description
#642/#650: everything the call_indirect lowering needs to emit its
guards — computed once per module by
DecodedModule::call_indirect_guards and threaded to the instruction
selector via CompileConfig.
§The R11 multi-table layout contract (#650)
The runtime/harness links every funcref table as ONE contiguous region of
raw 4-byte code pointers based at R11, in declaration order (imported
tables first): table 0 at R11 + 0, table N at
R11 + sum(size(0..N)) * 4. The offsets are compile-time constants
because tables are provably fixed-size (table.grow/table.set are
unsupported ops whose functions loud-skip at decode — #642). A
single-table module degenerates to the pre-#650 contract (table 0 at
R11, offset 0) BY CONSTRUCTION, keeping its emitted bytes identical.
WASM Core §4.4.8 requires call_indirect to trap when index >= table.size and when the callee’s type does not match the instruction’s
expected type. The region stores no size fields and no type ids, so, per
table:
- the BOUNDS check is emitted at runtime against THAT table’s
compile-time
table_sizeimmediate (sound: fixed-size, see above), and - the TYPE check is discharged at COMPILE time: for expected type
t,tables[n].type_reject[t]isNoneonly when every INITIALIZED slot of tablenverifiably holds a function whose signature structurally equals typet(the closed-world property — no runtime mismatch is then possible). Otherwise it holds the reason, and the lowering declines LOUDLY rather than emit an unchecked indirect branch, and - a NULL (uninitialized) slot traps at RUNTIME (#664): the layout
contract requires the runtime/harness to link every uninitialized
slot as a ZERO word (null funcref has no code address; 0 is never a
valid function pointer in the region), and when
has_null_slotsis set the dispatch emits a null check on the loaded pointer (CMP #0→ trap) between the bounds guard and the indirect branch. A fully-initialized table (has_null_slots == false) keeps the pre-#664 dispatch bytes identical BY CONSTRUCTION.
Fields§
§tables: Vec<TableGuards>Per-table guard inputs, indexed by table index (imports first). The
default (empty — no module context) DECLINES every call_indirect.
Implementations§
Trait Implementations§
Source§impl Clone for CallIndirectGuards
impl Clone for CallIndirectGuards
Source§fn clone(&self) -> CallIndirectGuards
fn clone(&self) -> CallIndirectGuards
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for CallIndirectGuards
impl Debug for CallIndirectGuards
Source§impl Default for CallIndirectGuards
impl Default for CallIndirectGuards
Source§fn default() -> CallIndirectGuards
fn default() -> CallIndirectGuards
impl Eq for CallIndirectGuards
Source§impl PartialEq for CallIndirectGuards
impl PartialEq for CallIndirectGuards
Source§fn eq(&self, other: &CallIndirectGuards) -> bool
fn eq(&self, other: &CallIndirectGuards) -> bool
self and other values to be equal, and is used by ==.impl StructuralPartialEq for CallIndirectGuards
Auto Trait Implementations§
impl Freeze for CallIndirectGuards
impl RefUnwindSafe for CallIndirectGuards
impl Send for CallIndirectGuards
impl Sync for CallIndirectGuards
impl Unpin for CallIndirectGuards
impl UnsafeUnpin for CallIndirectGuards
impl UnwindSafe for CallIndirectGuards
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.