Refactor Module interface to expose tables directly.

This commit is contained in:
Chris Fallin 2023-02-02 13:58:50 -08:00
parent b76ffd59cf
commit b35e0837a4
6 changed files with 70 additions and 136 deletions

View file

@ -519,7 +519,7 @@ pub fn compile(module: &Module<'_>) -> anyhow::Result<Vec<u8>> {
let mut into_mod = wasm_encoder::Module::new();
let mut types = wasm_encoder::TypeSection::new();
for (_sig, sig_data) in module.signatures() {
for sig_data in module.signatures.values() {
let params = sig_data
.params
.iter()
@ -537,16 +537,16 @@ pub fn compile(module: &Module<'_>) -> anyhow::Result<Vec<u8>> {
let mut num_table_imports = 0;
let mut num_global_imports = 0;
let mut num_mem_imports = 0;
for import in module.imports() {
for import in &module.imports {
let entity = match &import.kind {
&ImportKind::Func(func) => {
num_func_imports += 1;
let func = module.func(func);
let func = &module.funcs[func];
wasm_encoder::EntityType::Function(func.sig().index() as u32)
}
&ImportKind::Table(table) => {
num_table_imports += 1;
let table = module.table(table);
let table = &module.tables[table];
wasm_encoder::EntityType::Table(wasm_encoder::TableType {
element_type: wasm_encoder::ValType::from(table.ty),
minimum: table
@ -559,7 +559,7 @@ pub fn compile(module: &Module<'_>) -> anyhow::Result<Vec<u8>> {
}
&ImportKind::Global(global) => {
num_global_imports += 1;
let global = module.global(global);
let global = &module.globals[global];
wasm_encoder::EntityType::Global(wasm_encoder::GlobalType {
val_type: wasm_encoder::ValType::from(global.ty),
mutable: global.mutable,
@ -567,7 +567,7 @@ pub fn compile(module: &Module<'_>) -> anyhow::Result<Vec<u8>> {
}
&ImportKind::Memory(mem) => {
num_mem_imports += 1;
let mem = module.memory(mem);
let mem = &module.memories[mem];
wasm_encoder::EntityType::Memory(wasm_encoder::MemoryType {
memory64: false,
shared: false,
@ -582,7 +582,7 @@ pub fn compile(module: &Module<'_>) -> anyhow::Result<Vec<u8>> {
into_mod.section(&imports);
let mut funcs = wasm_encoder::FunctionSection::new();
for (func, func_decl) in module.funcs().skip(num_func_imports) {
for (func, func_decl) in module.funcs.entries().skip(num_func_imports) {
match func_decl {
FuncDecl::Import(_) => anyhow::bail!("Import comes after func with body: {}", func),
FuncDecl::Body(sig, _) => {
@ -593,7 +593,7 @@ pub fn compile(module: &Module<'_>) -> anyhow::Result<Vec<u8>> {
into_mod.section(&funcs);
let mut tables = wasm_encoder::TableSection::new();
for (_table, table_data) in module.tables().skip(num_table_imports) {
for table_data in module.tables.values().skip(num_table_imports) {
tables.table(wasm_encoder::TableType {
element_type: wasm_encoder::ValType::from(table_data.ty),
minimum: table_data
@ -607,7 +607,7 @@ pub fn compile(module: &Module<'_>) -> anyhow::Result<Vec<u8>> {
into_mod.section(&tables);
let mut memories = wasm_encoder::MemorySection::new();
for (_mem, mem_data) in module.memories().skip(num_mem_imports) {
for mem_data in module.memories.values().skip(num_mem_imports) {
memories.memory(wasm_encoder::MemoryType {
minimum: mem_data.initial_pages as u64,
maximum: mem_data.maximum_pages.map(|val| val as u64),
@ -618,7 +618,7 @@ pub fn compile(module: &Module<'_>) -> anyhow::Result<Vec<u8>> {
into_mod.section(&memories);
let mut globals = wasm_encoder::GlobalSection::new();
for (_global, global_data) in module.globals().skip(num_global_imports) {
for global_data in module.globals.values().skip(num_global_imports) {
globals.global(
wasm_encoder::GlobalType {
val_type: wasm_encoder::ValType::from(global_data.ty),
@ -630,7 +630,7 @@ pub fn compile(module: &Module<'_>) -> anyhow::Result<Vec<u8>> {
into_mod.section(&globals);
let mut exports = wasm_encoder::ExportSection::new();
for export in module.exports() {
for export in &module.exports {
match &export.kind {
&ExportKind::Table(table) => {
exports.export(
@ -672,7 +672,7 @@ pub fn compile(module: &Module<'_>) -> anyhow::Result<Vec<u8>> {
}
let mut elem = wasm_encoder::ElementSection::new();
for (table, table_data) in module.tables() {
for (table, table_data) in module.tables.entries() {
if let Some(elts) = &table_data.func_elements {
for (i, &elt) in elts.iter().enumerate() {
if elt.is_valid() {
@ -690,7 +690,8 @@ pub fn compile(module: &Module<'_>) -> anyhow::Result<Vec<u8>> {
let mut code = wasm_encoder::CodeSection::new();
let bodies = module
.funcs()
.funcs
.entries()
.skip(num_func_imports)
.collect::<Vec<_>>()
.par_iter()
@ -707,7 +708,7 @@ pub fn compile(module: &Module<'_>) -> anyhow::Result<Vec<u8>> {
into_mod.section(&code);
let mut data = wasm_encoder::DataSection::new();
for (mem, mem_data) in module.memories() {
for (mem, mem_data) in module.memories.entries() {
for segment in &mem_data.segments {
data.active(
mem.index() as u32,

View file

@ -62,7 +62,7 @@ fn handle_payload<'a>(
for ty in reader {
let ty = ty?;
let wasmparser::Type::Func(fty) = ty;
module.frontend_add_signature(fty.into());
module.signatures.push(fty.into());
}
}
Payload::ImportSection(reader) => {
@ -72,15 +72,16 @@ fn handle_payload<'a>(
let name = import.name.to_owned();
let kind = match import.ty {
TypeRef::Func(sig_idx) => {
let func =
module.frontend_add_func(FuncDecl::Import(Signature::from(sig_idx)));
let func = module
.funcs
.push(FuncDecl::Import(Signature::from(sig_idx)));
*next_func += 1;
ImportKind::Func(func)
}
TypeRef::Global(ty) => {
let mutable = ty.mutable;
let ty = ty.content_type.into();
let global = module.frontend_add_global(GlobalData {
let global = module.globals.push(GlobalData {
ty,
value: None,
mutable,
@ -92,7 +93,7 @@ fn handle_payload<'a>(
ImportKind::Table(table)
}
TypeRef::Memory(mem) => {
let mem = module.frontend_add_memory(MemoryData {
let mem = module.memories.push(MemoryData {
initial_pages: mem.initial as usize,
maximum_pages: mem.maximum.map(|max| max as usize),
segments: vec![],
@ -106,7 +107,7 @@ fn handle_payload<'a>(
)));
}
};
module.frontend_add_import(Import {
module.imports.push(Import {
module: module_name,
name,
kind,
@ -119,7 +120,7 @@ fn handle_payload<'a>(
let mutable = global.ty.mutable;
let ty = global.ty.content_type.into();
let init_expr = parse_init_expr(&global.init_expr)?;
module.frontend_add_global(GlobalData {
module.globals.push(GlobalData {
ty,
value: init_expr,
mutable,
@ -135,17 +136,19 @@ fn handle_payload<'a>(
Payload::FunctionSection(reader) => {
for sig_idx in reader {
let sig_idx = Signature::from(sig_idx?);
module.frontend_add_func(FuncDecl::Body(sig_idx, FunctionBody::default()));
module
.funcs
.push(FuncDecl::Body(sig_idx, FunctionBody::default()));
}
}
Payload::CodeSectionEntry(body) => {
let func_idx = Func::new(*next_func);
*next_func += 1;
let my_sig = module.func(func_idx).sig();
let my_sig = module.funcs[func_idx].sig();
let body = parse_body(module, my_sig, body)?;
let existing_body = module.func_mut(func_idx).body_mut().unwrap();
let existing_body = module.funcs[func_idx].body_mut().unwrap();
*existing_body = body;
}
Payload::ExportSection(reader) => {
@ -160,14 +163,14 @@ fn handle_payload<'a>(
_ => None,
};
if let Some(kind) = kind {
module.frontend_add_export(Export { name, kind });
module.exports.push(Export { name, kind });
}
}
}
Payload::MemorySection(reader) => {
for memory in reader {
let memory = memory?;
module.frontend_add_memory(MemoryData {
module.memories.push(MemoryData {
initial_pages: memory.initial as usize,
maximum_pages: memory.maximum.map(|max| max as usize),
segments: vec![],
@ -186,8 +189,7 @@ fn handle_payload<'a>(
let data = segment.data.to_vec();
let memory = Memory::from(*memory_index);
let offset = parse_init_expr(offset_expr)?.unwrap_or(0) as usize;
module
.memory_mut(memory)
module.memories[memory]
.segments
.push(MemorySegment { offset, data });
}
@ -232,7 +234,7 @@ fn handle_payload<'a>(
funcs.push(func);
}
let table_items = module.table_mut(table).func_elements.as_mut().unwrap();
let table_items = module.tables[table].func_elements.as_mut().unwrap();
let new_size = offset.checked_add(funcs.len()).ok_or_else(|| {
FrontendError::TooLarge(format!(
"Overflowing element offset + length: {} + {}",
@ -274,11 +276,11 @@ fn parse_body<'a>(
) -> Result<FunctionBody> {
let mut ret: FunctionBody = FunctionBody::default();
for &param in &module.signature(my_sig).params[..] {
for &param in &module.signatures[my_sig].params[..] {
ret.locals.push(param.into());
}
ret.n_params = module.signature(my_sig).params.len();
for &r in &module.signature(my_sig).returns[..] {
ret.n_params = module.signatures[my_sig].params.len();
for &r in &module.signatures[my_sig].returns[..] {
ret.rets.push(r.into());
}
@ -294,7 +296,7 @@ fn parse_body<'a>(
trace!(
"Parsing function body: locals = {:?} sig = {:?}",
ret.locals,
module.signature(my_sig)
module.signatures[my_sig]
);
let mut builder = FunctionBodyBuilder::new(module, my_sig, &mut ret);
@ -303,7 +305,7 @@ fn parse_body<'a>(
builder.locals.seal_block_preds(entry, &mut builder.body);
builder.locals.start_block(entry);
for (arg_idx, &arg_ty) in module.signature(my_sig).params.iter().enumerate() {
for (arg_idx, &arg_ty) in module.signatures[my_sig].params.iter().enumerate() {
let local_idx = Local::new(arg_idx);
builder.body.add_blockparam(entry, arg_ty);
let value = builder.body.blocks[entry].params.last().unwrap().1;
@ -312,7 +314,7 @@ fn parse_body<'a>(
builder.locals.set(local_idx, value);
}
let n_args = module.signature(my_sig).params.len();
let n_args = module.signatures[my_sig].params.len();
for (offset, local_ty) in locals.values().enumerate() {
let local_idx = Local::new(n_args + offset);
builder.locals.declare(local_idx, *local_ty);
@ -746,7 +748,7 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
};
// Push initial implicit Block.
let results = module.signature(my_sig).returns.to_vec();
let results = module.signatures[my_sig].returns.to_vec();
let out = ret.body.add_block();
ret.add_block_params(out, &results[..]);
ret.ctrl_stack.push(Frame::Block {
@ -1073,7 +1075,7 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
}
wasmparser::Operator::Return => {
let retvals = self.pop_n(self.module.signature(self.my_sig).returns.len());
let retvals = self.pop_n(self.module.signatures[self.my_sig].returns.len());
self.emit_ret(&retvals[..]);
self.reachable = false;
}
@ -1114,7 +1116,7 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
None => {
if self.reachable {
let retvals =
self.pop_n(self.module.signature(self.my_sig).returns.len());
self.pop_n(self.module.signatures[self.my_sig].returns.len());
self.emit_ret(&retvals[..]);
} else {
self.emit_unreachable();
@ -1369,7 +1371,7 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
BlockType::Empty => (vec![], vec![]),
BlockType::Type(ret_ty) => (vec![], vec![ret_ty.into()]),
BlockType::FuncType(sig_idx) => {
let sig = &self.module.signature(Signature::from(sig_idx));
let sig = &self.module.signatures[Signature::from(sig_idx)];
(
Vec::from(sig.params.clone()),
Vec::from(sig.returns.clone()),

View file

@ -151,7 +151,7 @@ impl<'a> Display for ModuleDisplay<'a> {
writeln!(f, " start = {}", func)?;
}
let mut sig_strs = HashMap::new();
for (sig, sig_data) in self.0.signatures() {
for (sig, sig_data) in self.0.signatures.entries() {
let arg_tys = sig_data
.params
.iter()
@ -166,14 +166,14 @@ impl<'a> Display for ModuleDisplay<'a> {
sig_strs.insert(sig, sig_str.clone());
writeln!(f, " {}: {}", sig, sig_str)?;
}
for (global, global_data) in self.0.globals() {
for (global, global_data) in self.0.globals.entries() {
writeln!(
f,
" {}: {:?} # {}",
global, global_data.value, global_data.ty
)?;
}
for (table, table_data) in self.0.tables() {
for (table, table_data) in self.0.tables.entries() {
writeln!(f, " {}: {}", table, table_data.ty)?;
if let Some(funcs) = &table_data.func_elements {
for (i, &func) in funcs.iter().enumerate() {
@ -181,7 +181,7 @@ impl<'a> Display for ModuleDisplay<'a> {
}
}
}
for (memory, memory_data) in self.0.memories() {
for (memory, memory_data) in self.0.memories.entries() {
writeln!(
f,
" {}: initial {} max {:?}",
@ -201,17 +201,17 @@ impl<'a> Display for ModuleDisplay<'a> {
)?;
}
}
for import in self.0.imports() {
for import in &self.0.imports {
writeln!(
f,
" import \"{}\".\"{}\": {}",
import.module, import.name, import.kind
)?;
}
for export in self.0.exports() {
for export in &self.0.exports {
writeln!(f, " export \"{}\": {}", export.name, export.kind)?;
}
for (func, func_decl) in self.0.funcs() {
for (func, func_decl) in self.0.funcs.entries() {
match func_decl {
FuncDecl::Body(sig, body) => {
writeln!(f, " {}: {} = # {}", func, sig, sig_strs.get(&sig).unwrap())?;

View file

@ -54,9 +54,9 @@ pub struct FunctionBody {
impl FunctionBody {
pub fn new(module: &Module, sig: Signature) -> FunctionBody {
let locals = EntityVec::from(module.signature(sig).params.clone());
let locals = EntityVec::from(module.signatures[sig].params.clone());
let n_params = locals.len();
let rets = module.signature(sig).returns.clone();
let rets = module.signatures[sig].returns.clone();
let mut blocks = EntityVec::default();
let entry = blocks.push(BlockDef::default());
let mut values = EntityVec::default();

View file

@ -6,14 +6,14 @@ use anyhow::Result;
#[derive(Clone, Debug)]
pub struct Module<'a> {
orig_bytes: &'a [u8],
funcs: EntityVec<Func, FuncDecl>,
signatures: EntityVec<Signature, SignatureData>,
globals: EntityVec<Global, GlobalData>,
tables: EntityVec<Table, TableData>,
imports: Vec<Import>,
exports: Vec<Export>,
memories: EntityVec<Memory, MemoryData>,
pub orig_bytes: &'a [u8],
pub funcs: EntityVec<Func, FuncDecl>,
pub signatures: EntityVec<Signature, SignatureData>,
pub globals: EntityVec<Global, GlobalData>,
pub tables: EntityVec<Table, TableData>,
pub imports: Vec<Import>,
pub exports: Vec<Export>,
pub memories: EntityVec<Memory, MemoryData>,
pub start_func: Option<Func>,
}
@ -142,59 +142,6 @@ impl<'a> Module<'a> {
}
impl<'a> Module<'a> {
pub fn func<'b>(&'b self, id: Func) -> &'b FuncDecl {
&self.funcs[id]
}
pub fn func_mut<'b>(&'b mut self, id: Func) -> &'b mut FuncDecl {
&mut self.funcs[id]
}
pub fn funcs<'b>(&'b self) -> impl Iterator<Item = (Func, &'b FuncDecl)> {
self.funcs.entries()
}
pub fn signature<'b>(&'b self, id: Signature) -> &'b SignatureData {
&self.signatures[id]
}
pub fn signatures<'b>(&'b self) -> impl Iterator<Item = (Signature, &'b SignatureData)> {
self.signatures.entries()
}
pub fn global<'b>(&'b self, id: Global) -> &'b GlobalData {
&self.globals[id]
}
pub fn globals<'b>(&'b self) -> impl Iterator<Item = (Global, &'b GlobalData)> + 'b {
self.globals.entries()
}
pub fn table<'b>(&'b self, id: Table) -> &'b TableData {
&self.tables[id]
}
pub fn tables<'b>(&'b self) -> impl Iterator<Item = (Table, &'b TableData)> + 'b {
self.tables.entries()
}
pub fn memories<'b>(&'b self) -> impl Iterator<Item = (Memory, &'b MemoryData)> + 'b {
self.memories.entries()
}
pub fn imports<'b>(&'b self) -> impl Iterator<Item = &'b Import> + 'b {
self.imports.iter()
}
pub fn exports<'b>(&'b self) -> impl Iterator<Item = &'b Export> + 'b {
self.exports.iter()
}
pub fn table_mut<'b>(&'b mut self, table: Table) -> &'b mut TableData {
&mut self.tables[table]
}
pub fn memory<'b>(&'b self, memory: Memory) -> &'b MemoryData {
&self.memories[memory]
}
pub fn memory_mut<'b>(&'b mut self, memory: Memory) -> &'b mut MemoryData {
&mut self.memories[memory]
}
pub(crate) fn frontend_add_signature(&mut self, ty: SignatureData) {
self.signatures.push(ty);
}
pub(crate) fn frontend_add_func(&mut self, body: FuncDecl) -> Func {
self.funcs.push(body)
}
pub(crate) fn frontend_add_table(&mut self, ty: Type, max: Option<u32>) -> Table {
let func_elements = if ty == Type::FuncRef {
Some(vec![])
@ -207,18 +154,6 @@ impl<'a> Module<'a> {
max,
})
}
pub(crate) fn frontend_add_global(&mut self, global: GlobalData) -> Global {
self.globals.push(global)
}
pub(crate) fn frontend_add_import(&mut self, import: Import) {
self.imports.push(import);
}
pub(crate) fn frontend_add_export(&mut self, export: Export) {
self.exports.push(export);
}
pub(crate) fn frontend_add_memory(&mut self, memory: MemoryData) -> Memory {
self.memories.push(memory)
}
pub fn from_wasm_bytes(bytes: &'a [u8]) -> Result<Self> {
frontend::wasm_to_ir(bytes)
@ -257,8 +192,4 @@ impl<'a> Module<'a> {
{
ModuleDisplay(self)
}
pub fn add_func(&mut self, sig: Signature, func: FunctionBody) -> Func {
self.funcs.push(FuncDecl::Body(sig, func))
}
}

View file

@ -14,11 +14,11 @@ pub fn op_inputs(
&Operator::Unreachable | &Operator::Nop => Ok(Cow::Borrowed(&[])),
&Operator::Call { function_index } => {
let sig = module.func(function_index).sig();
Ok(Vec::from(module.signature(sig).params.clone()).into())
let sig = module.funcs[function_index].sig();
Ok(Vec::from(module.signatures[sig].params.clone()).into())
}
&Operator::CallIndirect { sig_index, .. } => {
let mut params = module.signature(sig_index).params.to_vec();
let mut params = module.signatures[sig_index].params.to_vec();
params.push(Type::I32);
Ok(params.into())
}
@ -30,7 +30,7 @@ pub fn op_inputs(
&Operator::TypedSelect { ty } => Ok(vec![ty, ty, Type::I32].into()),
&Operator::GlobalGet { .. } => Ok(Cow::Borrowed(&[])),
&Operator::GlobalSet { global_index } => Ok(vec![module.global(global_index).ty].into()),
&Operator::GlobalSet { global_index } => Ok(vec![module.globals[global_index].ty].into()),
Operator::I32Load { .. }
| Operator::I64Load { .. }
@ -213,10 +213,10 @@ pub fn op_inputs(
Operator::I64ReinterpretF64 => Ok(Cow::Borrowed(&[Type::F64])),
Operator::TableGet { .. } => Ok(Cow::Borrowed(&[Type::I32])),
Operator::TableSet { table_index } => {
Ok(vec![Type::I32, module.table(*table_index).ty].into())
Ok(vec![Type::I32, module.tables[*table_index].ty].into())
}
Operator::TableGrow { table_index } => {
Ok(vec![Type::I32, module.table(*table_index).ty].into())
Ok(vec![Type::I32, module.tables[*table_index].ty].into())
}
Operator::TableSize { .. } => Ok(Cow::Borrowed(&[])),
Operator::MemorySize { .. } => Ok(Cow::Borrowed(&[])),
@ -233,11 +233,11 @@ pub fn op_outputs(
&Operator::Unreachable | &Operator::Nop => Ok(Cow::Borrowed(&[])),
&Operator::Call { function_index } => {
let sig = module.func(function_index).sig();
Ok(Vec::from(module.signature(sig).returns.clone()).into())
let sig = module.funcs[function_index].sig();
Ok(Vec::from(module.signatures[sig].returns.clone()).into())
}
&Operator::CallIndirect { sig_index, .. } => {
Ok(Vec::from(module.signature(sig_index).returns.clone()).into())
Ok(Vec::from(module.signatures[sig_index].returns.clone()).into())
}
&Operator::Select => {
@ -245,7 +245,7 @@ pub fn op_outputs(
Ok(vec![val_ty].into())
}
&Operator::TypedSelect { ty } => Ok(vec![ty].into()),
&Operator::GlobalGet { global_index } => Ok(vec![module.global(global_index).ty].into()),
&Operator::GlobalGet { global_index } => Ok(vec![module.globals[global_index].ty].into()),
&Operator::GlobalSet { .. } => Ok(Cow::Borrowed(&[])),
Operator::I32Load { .. }
@ -419,7 +419,7 @@ pub fn op_outputs(
Operator::F64ReinterpretI64 => Ok(Cow::Borrowed(&[Type::F64])),
Operator::I32ReinterpretF32 => Ok(Cow::Borrowed(&[Type::I32])),
Operator::I64ReinterpretF64 => Ok(Cow::Borrowed(&[Type::I64])),
Operator::TableGet { table_index } => Ok(vec![module.table(*table_index).ty].into()),
Operator::TableGet { table_index } => Ok(vec![module.tables[*table_index].ty].into()),
Operator::TableSet { .. } => Ok(Cow::Borrowed(&[])),
Operator::TableGrow { .. } => Ok(Cow::Borrowed(&[])),
Operator::TableSize { .. } => Ok(Cow::Borrowed(&[Type::I32])),