Path: blob/main/crates/wizer/src/component/rewrite.rs
2459 views
use crate::component::ComponentContext;1use crate::component::info::RawSection;2use crate::component::snapshot::ComponentSnapshot;3use crate::{FuncRenames, Wizer};4use wasm_encoder::reencode::{Reencode, ReencodeComponent};56impl Wizer {7/// Helper method which is the equivalent of [`Wizer::rewrite`], but for8/// components.9///10/// This effectively plumbs through all non-module sections as-is and11/// updates module sections with whatever [`Wizer::rewrite`] returns.12pub(crate) fn rewrite_component(13&self,14component: &mut ComponentContext<'_>,15snapshot: &ComponentSnapshot,16) -> Vec<u8> {17let mut encoder = wasm_encoder::Component::new();18let mut reencoder = Reencoder {19funcs: 0,20removed_func: None,21wizer: self,22};2324let mut module_index = 0;25for section in component.sections.iter_mut() {26match section {27RawSection::Module(module) => {28let snapshot = snapshot29.modules30.iter()31.find(|(i, _)| *i == module_index)32.map(|(_, s)| s);33module_index += 1;34match snapshot {35// This module's snapshot is used for [`Wizer::rewrite`]36// and the results of that are spliced into the37// component.38Some(snapshot) => {39let rewritten_wasm =40self.rewrite(module, snapshot, &FuncRenames::default());41encoder.section(&wasm_encoder::RawSection {42id: wasm_encoder::ComponentSectionId::CoreModule as u8,43data: &rewritten_wasm,44});45}4647// This module wasn't instantiated and has no snapshot,48// plumb it through as-is.49None => {50let mut module_encoder = wasm_encoder::Module::new();51for section in module.raw_sections() {52module_encoder.section(section);53}54encoder.section(&wasm_encoder::ModuleSection(&module_encoder));55}56}57}58RawSection::Raw(s) => {59reencoder.raw_section(&mut encoder, s);60}61}62}6364encoder.finish()65}66}6768struct Reencoder<'a> {69/// Number of defined functions encountered so far.70funcs: u32,71/// Index of the start function that's being removed, used to renumber all72/// other functions.73removed_func: Option<u32>,74/// Wizer configuration.75wizer: &'a Wizer,76}7778impl Reencoder<'_> {79fn raw_section(80&mut self,81encoder: &mut wasm_encoder::Component,82section: &wasm_encoder::RawSection,83) {84match section.id {85// These can't define component functions so the sections are86// plumbed as-is.87id if id == wasm_encoder::ComponentSectionId::CoreCustom as u888|| id == wasm_encoder::ComponentSectionId::CoreInstance as u889|| id == wasm_encoder::ComponentSectionId::CoreType as u890|| id == wasm_encoder::ComponentSectionId::Component as u891|| id == wasm_encoder::ComponentSectionId::Type as u8 =>92{93encoder.section(section);94}9596id if id == wasm_encoder::ComponentSectionId::CoreModule as u8 => {97panic!("should happen in caller");98}99id if id == wasm_encoder::ComponentSectionId::Start as u8 => {100// Component start sections aren't supported yet anyway101todo!()102}103104// These sections all might affect or refer to component function105// indices so they're reencoded here, optionally updating function106// indices in case the index is higher than the one that we're107// removing.108id if id == wasm_encoder::ComponentSectionId::Instance as u8 => {109self.rewrite(110encoder,111section.data,112Self::parse_component_instance_section,113);114}115id if id == wasm_encoder::ComponentSectionId::Alias as u8 => {116self.rewrite(encoder, section.data, Self::parse_component_alias_section);117}118id if id == wasm_encoder::ComponentSectionId::CanonicalFunction as u8 => {119self.rewrite(120encoder,121section.data,122Self::parse_component_canonical_section,123);124}125id if id == wasm_encoder::ComponentSectionId::Import as u8 => {126self.rewrite(encoder, section.data, Self::parse_component_import_section);127}128id if id == wasm_encoder::ComponentSectionId::Export as u8 => {129self.rewrite(encoder, section.data, Self::parse_component_export_section);130}131other => panic!("unexpected component section id: {other}"),132}133}134135fn rewrite<'a, T, S>(136&mut self,137encoder: &mut wasm_encoder::Component,138data: &'a [u8],139f: fn(&mut Self, dst: &mut S, wasmparser::SectionLimited<'a, T>) -> Result<(), Error>,140) where141T: wasmparser::FromReader<'a>,142S: Default + wasm_encoder::ComponentSection,143{144let mut section = S::default();145f(146self,147&mut section,148wasmparser::SectionLimited::new(wasmparser::BinaryReader::new(data, 0)).unwrap(),149)150.unwrap();151encoder.section(§ion);152}153}154155impl Reencode for Reencoder<'_> {156type Error = std::convert::Infallible;157}158type Error = wasm_encoder::reencode::Error<std::convert::Infallible>;159160impl ReencodeComponent for Reencoder<'_> {161fn component_func_index(&mut self, original_index: u32) -> u32 {162match self.removed_func {163None => original_index,164Some(removed) => {165if original_index < removed {166original_index167} else if original_index == removed {168panic!("referenced removed function")169} else {170original_index - 1171}172}173}174}175176fn parse_component_alias_section(177&mut self,178aliases: &mut wasm_encoder::ComponentAliasSection,179section: wasmparser::ComponentAliasSectionReader<'_>,180) -> Result<(), Error> {181for alias in section.clone() {182let alias = alias?;183if let wasmparser::ComponentAlias::InstanceExport {184kind: wasmparser::ComponentExternalKind::Func,185..186} = alias187{188self.funcs += 1;189}190}191192wasm_encoder::reencode::component_utils::parse_component_alias_section(193self, aliases, section,194)195}196197fn parse_component_canonical_section(198&mut self,199canonicals: &mut wasm_encoder::CanonicalFunctionSection,200section: wasmparser::ComponentCanonicalSectionReader<'_>,201) -> Result<(), Error> {202for canonical in section.clone() {203let canonical = canonical?;204if let wasmparser::CanonicalFunction::Lift { .. } = canonical {205self.funcs += 1;206}207}208209wasm_encoder::reencode::component_utils::parse_component_canonical_section(210self, canonicals, section,211)212}213214fn parse_component_import_section(215&mut self,216imports: &mut wasm_encoder::ComponentImportSection,217section: wasmparser::ComponentImportSectionReader<'_>,218) -> Result<(), Error> {219for import in section.clone() {220let import = import?;221if let wasmparser::ComponentExternalKind::Func = import.ty.kind() {222self.funcs += 1;223}224}225226wasm_encoder::reencode::component_utils::parse_component_import_section(227self, imports, section,228)229}230231fn parse_component_export_section(232&mut self,233exports: &mut wasm_encoder::ComponentExportSection,234section: wasmparser::ComponentExportSectionReader<'_>,235) -> Result<(), Error> {236for export in section {237let export = export?;238if !self.wizer.get_keep_init_func() && export.name.0 == self.wizer.get_init_func() {239self.removed_func = Some(self.funcs);240} else {241if export.kind == wasmparser::ComponentExternalKind::Func {242self.funcs += 1;243}244self.parse_component_export(exports, export)?;245}246}247Ok(())248}249}250251252