Path: blob/main/crates/wizer/src/component/parse.rs
2459 views
use crate::component::ComponentContext;1use anyhow::{Result, bail};2use std::collections::hash_map::Entry;3use wasmparser::{4CanonicalFunction, ComponentAlias, ComponentExternalKind, ComponentOuterAliasKind, Encoding,5Instance, Parser, Payload,6};78/// Parse the given Wasm bytes into a `ComponentContext` tree.9///10/// This will parse the input component and build up metadata that Wizer needs11/// to know about the component. At this time there are limitations to this12/// parsing phase which in theory could be lifted in the future but serve as13/// simplifying assumptions for now:14///15/// * Nested components with modules are not supported.16/// * Imported modules or components are not supported.17/// * Instantiating a module twice is not supported.18/// * Component-level start functions are not supported.19///20/// Some of these restrictions are likely to be loosened over time, however.21pub(crate) fn parse<'a>(full_wasm: &'a [u8]) -> anyhow::Result<ComponentContext<'a>> {22let mut component = ComponentContext::default();23let parser = Parser::new(0).parse_all(full_wasm);24parse_into(Some(&mut component), full_wasm, parser)?;25Ok(component)26}2728fn parse_into<'a>(29mut cx: Option<&mut ComponentContext<'a>>,30full_wasm: &'a [u8],31mut iter: impl Iterator<Item = wasmparser::Result<Payload<'a>>>,32) -> anyhow::Result<()> {33let mut stack = Vec::new();34while let Some(payload) = iter.next() {35let payload = payload?;3637match &payload {38// Module sections get parsed with wizer's core wasm support.39Payload::ModuleSection { .. } => match &mut cx {40Some(component) => {41let info = crate::parse::parse_with(&full_wasm, &mut iter)?;42component.push_module_section(info);43}44None => {45bail!("nested components with modules not currently supported");46}47},4849// All other sections get pushed raw as-is into the component.50_ => {51if let Some((id, range)) = payload.as_section()52&& let Some(component) = &mut cx53{54component.push_raw_section(wasm_encoder::RawSection {55id,56data: &full_wasm[range],57});58}59}60}6162// Further validation/handling of each section, mostly about maintaining63// index spaces so we know what indices are used when the instrumented64// component is produced.65match payload {66Payload::Version {67encoding: Encoding::Module,68..69} => {70bail!("expected a component, found a core module");71}7273Payload::ComponentSection { .. } => {74stack.push(cx.take());75}7677Payload::End(_) => {78if stack.len() > 0 {79cx = stack.pop().unwrap();80}81}8283Payload::InstanceSection(reader) => {84if let Some(component) = &mut cx {85for instance in reader {86let instance_index = component.inc_core_instances();8788if let Instance::Instantiate { module_index, .. } = instance? {89match component.core_instantiations.entry(module_index) {90Entry::Vacant(entry) => {91entry.insert(instance_index);92}93Entry::Occupied(_) => {94bail!("modules may be instantiated at most once")95}96}97}98}99}100}101Payload::ComponentInstanceSection(reader) => {102if let Some(component) = &mut cx {103for _ in reader {104component.inc_instances();105}106}107}108109Payload::ComponentAliasSection(reader) => {110for alias in reader {111match alias? {112ComponentAlias::CoreInstanceExport { kind, .. } => {113if let Some(component) = &mut cx {114component.inc_core(kind);115}116}117ComponentAlias::InstanceExport { kind, .. } => {118validate_item_kind(kind, "aliases")?;119if let Some(component) = &mut cx {120component.inc(kind);121}122}123ComponentAlias::Outer { kind, .. } => match kind {124ComponentOuterAliasKind::CoreType => {}125ComponentOuterAliasKind::Type => {126if let Some(component) = &mut cx {127component.inc_types();128}129}130ComponentOuterAliasKind::CoreModule => {131bail!("wizer does not currently support module aliases");132}133ComponentOuterAliasKind::Component => {134bail!("wizer does not currently support component aliases");135}136},137}138}139}140141Payload::ComponentCanonicalSection(reader) => {142for function in reader {143match function? {144CanonicalFunction::Lift { .. } => {145if let Some(component) = &mut cx {146component.inc_funcs();147}148}149_ => {150if let Some(component) = &mut cx {151component.inc_core_funcs();152}153}154}155}156}157158Payload::ComponentImportSection(reader) => {159for import in reader {160let kind = import?.ty.kind();161validate_item_kind(kind, "imports")?;162if let Some(component) = &mut cx {163component.inc(kind);164}165}166}167168Payload::ComponentExportSection(reader) => {169for export in reader {170let kind = export?.kind;171validate_item_kind(kind, "exports")?;172if let Some(component) = &mut cx {173component.inc(kind);174}175}176}177178Payload::ComponentTypeSection(reader) => {179for _ in reader {180if let Some(component) = &mut cx {181component.inc_types();182}183}184}185186// The `start` section for components is itself not stable, so not187// super urgent to handle. A simplifying assumption is made to just188// reject it outright for now if it shows up.189Payload::ComponentStartSection { .. } => {190bail!("wizer does not currently support component start functions");191}192193_ => {}194}195}196197Ok(())198}199200fn validate_item_kind(kind: ComponentExternalKind, msg: &str) -> Result<()> {201match kind {202// Aliasing modules would require keeping track of where a module's203// original definition is. There's not much usage of this in the wild204// so reject it for now as a simplifying assumption.205ComponentExternalKind::Module => {206bail!("wizer does not currently support module {msg}");207}208209// Aliasing components deals with nested instantiations or similar,210// where a simplifying assumption is made to not worry about that for now.211ComponentExternalKind::Component => {212bail!("wizer does not currently support component {msg}");213}214215// Like start sections, support for this is just deferred to some other216// time, if ever.217ComponentExternalKind::Value => {218bail!("wizer does not currently support value {msg}");219}220221ComponentExternalKind::Func222| ComponentExternalKind::Type223| ComponentExternalKind::Instance => Ok(()),224}225}226227228