Skip to content

Commit 6e41520

Browse files
committed
refactor: remove get_function_table_entry, expose evaluate_scalar instead
get_function_table_entry was the wrong abstraction for walrus — it operated on raw wasm table indices rather than IDs, and encoded wasm-bindgen-specific logic that doesn't belong in a general-purpose IR library. The right primitive is ConstExpr::evaluate_scalar, which lets callers correctly resolve element segment offsets regardless of whether they are expressed as Value, Global, or Extended const expressions. Coverage is provided by the elem.wast spec tests.
1 parent 18aaff6 commit 6e41520

2 files changed

Lines changed: 1 addition & 222 deletions

File tree

crates/tests/tests/element_segment_global_offset.rs

Lines changed: 0 additions & 151 deletions
This file was deleted.

src/module/tables.rs

Lines changed: 1 addition & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
//! Tables within a wasm module.
22
33
use crate::emit::{Emit, EmitContext};
4-
use crate::ir::Value;
54
use crate::map::IdHashSet;
6-
use crate::module::globals::GlobalKind;
75
use crate::parse::IndicesToIds;
86
use crate::tombstone_arena::{Id, Tombstone, TombstoneArena};
9-
use crate::{
10-
ConstExpr, Element, ElementItems, ElementKind, FunctionId, ImportId, Module, RefType, Result,
11-
};
7+
use crate::{ConstExpr, Element, ImportId, Module, RefType, Result};
128
use anyhow::bail;
139

1410
/// The id of a table.
@@ -169,72 +165,6 @@ impl ModuleTables {
169165
}
170166

171167
impl Module {
172-
/// Look up a function by its index in the module's main function table.
173-
///
174-
/// This handles element segments whose offsets are expressed as:
175-
///
176-
/// - `ConstExpr::Value(Value::I32(n))` — a plain literal (the common case
177-
/// produced by lld for small modules).
178-
/// - `ConstExpr::Global(g)` — a `global.get` referencing an immutable
179-
/// local i32 global (e.g. `__table_base`, produced by lld for large
180-
/// position-independent modules with rustc 1.94+).
181-
///
182-
/// Segments with `ConstExpr::Extended` offsets (e.g.
183-
/// `global.get $__table_base + i32.const K`) require expression
184-
/// evaluation and are skipped; `idx` will not be found via those segments.
185-
///
186-
/// # Errors
187-
///
188-
/// Returns an error if the module has no function table, if there is more
189-
/// than one function table, or if `idx` is not found in any element
190-
/// segment.
191-
pub fn get_function_table_entry(&self, idx: u32) -> Result<FunctionId> {
192-
let table_id = self
193-
.tables
194-
.main_function_table()?
195-
.ok_or_else(|| anyhow::anyhow!("no function table found in module"))?;
196-
let table = self.tables.get(table_id);
197-
198-
let resolve = |g| match &self.globals.get(g).kind {
199-
GlobalKind::Local(expr) => Some(expr.clone()),
200-
GlobalKind::Import(_) => None,
201-
};
202-
203-
for &seg_id in &table.elem_segments {
204-
let seg = self.elements.get(seg_id);
205-
206-
let offset = match &seg.kind {
207-
ElementKind::Active { offset, .. } => match offset.evaluate_scalar(&resolve) {
208-
Some(Value::I32(n)) => n as u32,
209-
_ => continue,
210-
},
211-
_ => continue,
212-
};
213-
214-
let local_idx = match idx.checked_sub(offset) {
215-
Some(i) => i as usize,
216-
None => continue,
217-
};
218-
219-
let found = match &seg.items {
220-
ElementItems::Functions(funcs) => funcs.get(local_idx).copied(),
221-
ElementItems::Expressions(_, exprs) => exprs.get(local_idx).and_then(|e| {
222-
if let ConstExpr::RefFunc(f) = e {
223-
Some(*f)
224-
} else {
225-
None
226-
}
227-
}),
228-
};
229-
230-
if let Some(f) = found {
231-
return Ok(f);
232-
}
233-
}
234-
235-
bail!("failed to find `{}` in function table", idx)
236-
}
237-
238168
/// Construct a new, empty set of tables for a module.
239169
pub(crate) fn parse_tables(
240170
&mut self,

0 commit comments

Comments
 (0)