Next Generation WASM Microkernel Operating System
at trap_handler 219 lines 7.6 kB view raw
1use crate::core::binary::EncodeOptions; 2use crate::core::*; 3use crate::parser::{Parse, Parser, Result}; 4use crate::token::{Id, Index, NameAnnotation, Span}; 5use crate::{annotation, kw}; 6use alloc::vec::Vec; 7 8pub use crate::core::resolve::Names; 9 10/// A parsed WebAssembly core module. 11#[derive(Debug)] 12pub struct Module<'a> { 13 /// Where this `module` was defined 14 pub span: Span, 15 /// An optional identifier this module is known by 16 pub id: Option<Id<'a>>, 17 /// An optional `@name` annotation for this module 18 pub name: Option<NameAnnotation<'a>>, 19 /// What kind of module this was parsed as. 20 pub kind: ModuleKind<'a>, 21} 22 23/// The different kinds of ways to define a module. 24#[derive(Debug)] 25pub enum ModuleKind<'a> { 26 /// A module defined in the textual s-expression format. 27 Text(Vec<ModuleField<'a>>), 28 /// A module that had its raw binary bytes defined via the `binary` 29 /// directive. 30 Binary(Vec<&'a [u8]>), 31} 32 33impl<'a> Module<'a> { 34 /// Performs a name resolution pass on this [`Module`], resolving all 35 /// symbolic names to indices. 36 /// 37 /// The WAT format contains a number of shorthands to make it easier to 38 /// write, such as inline exports, inline imports, inline type definitions, 39 /// etc. Additionally it allows using symbolic names such as `$foo` instead 40 /// of using indices. This module will postprocess an AST to remove all of 41 /// this syntactic sugar, preparing the AST for binary emission. This is 42 /// where expansion and name resolution happens. 43 /// 44 /// This function will mutate the AST of this [`Module`] and replace all 45 /// [`Index`](crate::token::Index) arguments with `Index::Num`. This will 46 /// also expand inline exports/imports listed on fields and handle various 47 /// other shorthands of the text format. 48 /// 49 /// If successful the AST was modified to be ready for binary encoding. A 50 /// [`Names`] structure is also returned so if you'd like to do your own 51 /// name lookups on the result you can do so as well. 52 /// 53 /// # Errors 54 /// 55 /// If an error happens during resolution, such a name resolution error or 56 /// items are found in the wrong order, then an error is returned. 57 pub fn resolve(&mut self) -> core::result::Result<Names<'a>, crate::Error> { 58 let names = match &mut self.kind { 59 ModuleKind::Text(fields) => crate::core::resolve::resolve(fields)?, 60 ModuleKind::Binary(_blobs) => Default::default(), 61 }; 62 Ok(names) 63 } 64 65 /// Encodes this [`Module`] to its binary form. 66 /// 67 /// This function will take the textual representation in [`Module`] and 68 /// perform all steps necessary to convert it to a binary WebAssembly 69 /// module, suitable for writing to a `*.wasm` file. This function may 70 /// internally modify the [`Module`], for example: 71 /// 72 /// * Name resolution is performed to ensure that `Index::Id` isn't present 73 /// anywhere in the AST. 74 /// 75 /// * Inline shorthands such as imports/exports/types are all expanded to be 76 /// dedicated fields of the module. 77 /// 78 /// * Module fields may be shuffled around to preserve index ordering from 79 /// expansions. 80 /// 81 /// After all of this expansion has happened the module will be converted to 82 /// its binary form and returned as a `Vec<u8>`. This is then suitable to 83 /// hand off to other wasm runtimes and such. 84 /// 85 /// # Errors 86 /// 87 /// This function can return an error for name resolution errors and other 88 /// expansion-related errors. 89 pub fn encode(&mut self) -> core::result::Result<Vec<u8>, crate::Error> { 90 EncodeOptions::default().encode_module(self) 91 } 92 93 pub(crate) fn validate(&self, parser: Parser<'_>) -> Result<()> { 94 let mut starts = 0; 95 if let ModuleKind::Text(fields) = &self.kind { 96 for item in fields.iter() { 97 if let ModuleField::Start(_) = item { 98 starts += 1; 99 } 100 } 101 } 102 if starts > 1 { 103 return Err(parser.error("multiple start sections found")); 104 } 105 Ok(()) 106 } 107 108 pub(crate) fn parse_without_module_keyword( 109 module_keyword_span: Span, 110 parser: Parser<'a>, 111 ) -> Result<Self> { 112 let id = parser.parse()?; 113 let name = parser.parse()?; 114 115 let kind = if parser.peek::<kw::binary>()? { 116 parser.parse::<kw::binary>()?; 117 let mut data = Vec::new(); 118 while !parser.is_empty() { 119 data.push(parser.parse()?); 120 } 121 ModuleKind::Binary(data) 122 } else { 123 ModuleKind::Text(ModuleField::parse_remaining(parser)?) 124 }; 125 Ok(Module { 126 span: module_keyword_span, 127 id, 128 name, 129 kind, 130 }) 131 } 132} 133 134impl<'a> Parse<'a> for Module<'a> { 135 fn parse(parser: Parser<'a>) -> Result<Self> { 136 parser.with_standard_annotations_registered(|parser| { 137 let span = parser.parse::<kw::module>()?.0; 138 Self::parse_without_module_keyword(span, parser) 139 }) 140 } 141} 142 143/// A listing of all possible fields that can make up a WebAssembly module. 144#[allow(missing_docs)] 145#[derive(Debug)] 146pub enum ModuleField<'a> { 147 Type(Type<'a>), 148 Rec(Rec<'a>), 149 Import(Import<'a>), 150 Func(Func<'a>), 151 Table(Table<'a>), 152 Memory(Memory<'a>), 153 Global(Global<'a>), 154 Export(Export<'a>), 155 Start(Index<'a>), 156 Elem(Elem<'a>), 157 Data(Data<'a>), 158 Tag(Tag<'a>), 159 Custom(Custom<'a>), 160} 161 162impl<'a> ModuleField<'a> { 163 pub(crate) fn parse_remaining(parser: Parser<'a>) -> Result<Vec<ModuleField<'a>>> { 164 let mut fields = Vec::new(); 165 while !parser.is_empty() { 166 fields.push(parser.parens(ModuleField::parse)?); 167 } 168 Ok(fields) 169 } 170} 171 172impl<'a> Parse<'a> for ModuleField<'a> { 173 fn parse(parser: Parser<'a>) -> Result<Self> { 174 if parser.peek::<Type<'a>>()? { 175 return Ok(ModuleField::Type(parser.parse()?)); 176 } 177 if parser.peek::<kw::rec>()? { 178 return Ok(ModuleField::Rec(parser.parse()?)); 179 } 180 if parser.peek::<kw::import>()? { 181 return Ok(ModuleField::Import(parser.parse()?)); 182 } 183 if parser.peek::<kw::func>()? { 184 return Ok(ModuleField::Func(parser.parse()?)); 185 } 186 if parser.peek::<kw::table>()? { 187 return Ok(ModuleField::Table(parser.parse()?)); 188 } 189 if parser.peek::<kw::memory>()? { 190 return Ok(ModuleField::Memory(parser.parse()?)); 191 } 192 if parser.peek::<kw::global>()? { 193 return Ok(ModuleField::Global(parser.parse()?)); 194 } 195 if parser.peek::<kw::export>()? { 196 return Ok(ModuleField::Export(parser.parse()?)); 197 } 198 if parser.peek::<kw::start>()? { 199 parser.parse::<kw::start>()?; 200 return Ok(ModuleField::Start(parser.parse()?)); 201 } 202 if parser.peek::<kw::elem>()? { 203 return Ok(ModuleField::Elem(parser.parse()?)); 204 } 205 if parser.peek::<kw::data>()? { 206 return Ok(ModuleField::Data(parser.parse()?)); 207 } 208 if parser.peek::<kw::tag>()? { 209 return Ok(ModuleField::Tag(parser.parse()?)); 210 } 211 if parser.peek::<annotation::custom>()? 212 || parser.peek::<annotation::producers>()? 213 || parser.peek::<annotation::dylink_0>()? 214 { 215 return Ok(ModuleField::Custom(parser.parse()?)); 216 } 217 Err(parser.error("expected valid module field")) 218 } 219}