mirror of
https://github.com/exoticorn/microw8.git
synced 2026-01-20 19:26:43 +01:00
add support for global vars
This commit is contained in:
@@ -11,11 +11,18 @@ use ValType::*;
|
|||||||
pub struct BaseModule {
|
pub struct BaseModule {
|
||||||
pub types: Vec<FunctionType>,
|
pub types: Vec<FunctionType>,
|
||||||
pub function_imports: Vec<(&'static str, String, u32)>,
|
pub function_imports: Vec<(&'static str, String, u32)>,
|
||||||
|
pub global_imports: Vec<(&'static str, String, GlobalType)>,
|
||||||
pub functions: Vec<u32>,
|
pub functions: Vec<u32>,
|
||||||
pub exports: Vec<(&'static str, u32)>,
|
pub exports: Vec<(&'static str, u32)>,
|
||||||
pub memory: u32,
|
pub memory: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct GlobalType {
|
||||||
|
pub type_: ValType,
|
||||||
|
pub mutable: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct FunctionType {
|
pub struct FunctionType {
|
||||||
pub params: Vec<ValType>,
|
pub params: Vec<ValType>,
|
||||||
@@ -23,7 +30,7 @@ pub struct FunctionType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BaseModule {
|
impl BaseModule {
|
||||||
pub fn for_format_version(version: u32) -> Result<BaseModule> {
|
pub fn for_format_version(version: u8) -> Result<BaseModule> {
|
||||||
if version != 1 {
|
if version != 1 {
|
||||||
bail!("Unsupported format version ({})", version);
|
bail!("Unsupported format version ({})", version);
|
||||||
}
|
}
|
||||||
@@ -68,24 +75,36 @@ impl BaseModule {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut global_imports = vec![];
|
||||||
|
for i in 0..16 {
|
||||||
|
global_imports.push((
|
||||||
|
"env",
|
||||||
|
format!("g_reserved{}", i),
|
||||||
|
GlobalType {
|
||||||
|
type_: I32,
|
||||||
|
mutable: false,
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
let first_function = functions.len() as u32;
|
let first_function = functions.len() as u32;
|
||||||
|
|
||||||
Ok(BaseModule {
|
Ok(BaseModule {
|
||||||
types,
|
types,
|
||||||
function_imports: functions,
|
function_imports: functions,
|
||||||
|
global_imports,
|
||||||
functions: vec![lookup_type(&type_map, &[I32], None)],
|
functions: vec![lookup_type(&type_map, &[I32], None)],
|
||||||
exports: vec![("tic", first_function)],
|
exports: vec![("tic", first_function)],
|
||||||
memory: 4,
|
memory: 4,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_to_file<P: AsRef<Path>>(&self, path: P) -> Result<()> {
|
pub fn to_wasm(&self) -> Vec<u8> {
|
||||||
fn inner(m: &BaseModule, path: &Path) -> Result<()> {
|
|
||||||
let mut module = Module::new();
|
let mut module = Module::new();
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut types = TypeSection::new();
|
let mut types = TypeSection::new();
|
||||||
for type_ in &m.types {
|
for type_ in &self.types {
|
||||||
types.function(type_.params.iter().cloned(), type_.result.iter().cloned());
|
types.function(type_.params.iter().cloned(), type_.result.iter().cloned());
|
||||||
}
|
}
|
||||||
module.section(&types);
|
module.section(&types);
|
||||||
@@ -94,15 +113,26 @@ impl BaseModule {
|
|||||||
{
|
{
|
||||||
let mut imports = ImportSection::new();
|
let mut imports = ImportSection::new();
|
||||||
|
|
||||||
for (module, name, type_) in &m.function_imports {
|
for (module, name, type_) in &self.function_imports {
|
||||||
imports.import(*module, Some(name.as_str()), EntityType::Function(*type_));
|
imports.import(*module, Some(name.as_str()), EntityType::Function(*type_));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (module, name, import) in &self.global_imports {
|
||||||
|
imports.import(
|
||||||
|
*module,
|
||||||
|
Some(name.as_str()),
|
||||||
|
EntityType::Global(wasm_encoder::GlobalType {
|
||||||
|
val_type: import.type_,
|
||||||
|
mutable: import.mutable,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
imports.import(
|
imports.import(
|
||||||
"env",
|
"env",
|
||||||
Some("memory"),
|
Some("memory"),
|
||||||
MemoryType {
|
MemoryType {
|
||||||
minimum: m.memory as u64,
|
minimum: self.memory as u64,
|
||||||
maximum: None,
|
maximum: None,
|
||||||
memory64: false,
|
memory64: false,
|
||||||
},
|
},
|
||||||
@@ -114,7 +144,7 @@ impl BaseModule {
|
|||||||
{
|
{
|
||||||
let mut functions = FunctionSection::new();
|
let mut functions = FunctionSection::new();
|
||||||
|
|
||||||
for type_ in &m.functions {
|
for type_ in &self.functions {
|
||||||
functions.function(*type_);
|
functions.function(*type_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,7 +154,7 @@ impl BaseModule {
|
|||||||
{
|
{
|
||||||
let mut exports = ExportSection::new();
|
let mut exports = ExportSection::new();
|
||||||
|
|
||||||
for (name, fnc) in &m.exports {
|
for (name, fnc) in &self.exports {
|
||||||
exports.export(*name, Export::Function(*fnc));
|
exports.export(*name, Export::Function(*fnc));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,7 +164,7 @@ impl BaseModule {
|
|||||||
{
|
{
|
||||||
let mut code = CodeSection::new();
|
let mut code = CodeSection::new();
|
||||||
|
|
||||||
for _ in &m.functions {
|
for _ in &self.functions {
|
||||||
let mut function = Function::new([]);
|
let mut function = Function::new([]);
|
||||||
function.instruction(&Instruction::End);
|
function.instruction(&Instruction::End);
|
||||||
code.function(&function);
|
code.function(&function);
|
||||||
@@ -143,13 +173,12 @@ impl BaseModule {
|
|||||||
module.section(&code);
|
module.section(&code);
|
||||||
}
|
}
|
||||||
|
|
||||||
let data = module.finish();
|
module.finish()
|
||||||
|
|
||||||
File::create(path)?.write_all(&data)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
inner(self, path.as_ref())
|
|
||||||
|
pub fn write_to_file<P: AsRef<Path>>(&self, path: P) -> Result<()> {
|
||||||
|
File::create(path)?.write_all(&self.to_wasm())?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,15 +13,20 @@ fn main() -> Result<()> {
|
|||||||
if let Some(cmd) = args.subcommand()? {
|
if let Some(cmd) = args.subcommand()? {
|
||||||
match cmd.as_str() {
|
match cmd.as_str() {
|
||||||
"make-base" => {
|
"make-base" => {
|
||||||
let version: u32 = args.free_from_str()?;
|
let version: u8 = args.free_from_str()?;
|
||||||
BaseModule::for_format_version(version)?
|
BaseModule::for_format_version(version)?
|
||||||
.write_to_file(format!("base{}.wasm", version))?;
|
.write_to_file(format!("base{}.wasm", version))?;
|
||||||
}
|
}
|
||||||
"pack" => {
|
"pack" => {
|
||||||
let version: u32 = args.opt_value_from_str(["-v", "--version"])?.unwrap_or(1);
|
let version: u8 = args.opt_value_from_str(["-v", "--version"])?.unwrap_or(1);
|
||||||
let source: PathBuf = args.free_from_str()?;
|
let source: PathBuf = args.free_from_str()?;
|
||||||
let dest: PathBuf = args.free_from_str()?;
|
let dest: PathBuf = args.free_from_str()?;
|
||||||
pack::pack(&source, &dest, version)?;
|
pack::pack_file(&source, &dest, version)?;
|
||||||
|
}
|
||||||
|
"unpack" => {
|
||||||
|
let source: PathBuf = args.free_from_str()?;
|
||||||
|
let dest: PathBuf = args.free_from_str()?;
|
||||||
|
pack::unpack_file(&source, &dest)?;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
eprintln!("Unknown subcommand '{}'", cmd);
|
eprintln!("Unknown subcommand '{}'", cmd);
|
||||||
@@ -32,7 +37,6 @@ fn main() -> Result<()> {
|
|||||||
print_help();
|
print_help();
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseModule::for_format_version(1)?.write_to_file("base.wasm")?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::base_module::{self, BaseModule, FunctionType};
|
use crate::base_module::{self, BaseModule, FunctionType, GlobalType};
|
||||||
use anyhow::{anyhow, bail, Result};
|
use anyhow::{anyhow, bail, Result};
|
||||||
use enc::ValType;
|
use enc::ValType;
|
||||||
use std::{
|
use std::{
|
||||||
@@ -9,11 +9,11 @@ use std::{
|
|||||||
};
|
};
|
||||||
use wasm_encoder as enc;
|
use wasm_encoder as enc;
|
||||||
use wasmparser::{
|
use wasmparser::{
|
||||||
ExportSectionReader, ExternalKind, FunctionBody, FunctionSectionReader, ImportSectionEntryType,
|
BinaryReader, ExportSectionReader, ExternalKind, FunctionBody, FunctionSectionReader,
|
||||||
ImportSectionReader, TypeSectionReader,
|
ImportSectionEntryType, ImportSectionReader, TypeSectionReader,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn pack(source: &Path, dest: &Path, version: u32) -> Result<()> {
|
pub fn pack_file(source: &Path, dest: &Path, version: u8) -> Result<()> {
|
||||||
let base = BaseModule::for_format_version(version)?;
|
let base = BaseModule::for_format_version(version)?;
|
||||||
|
|
||||||
let mut source_data = vec![];
|
let mut source_data = vec![];
|
||||||
@@ -29,6 +29,60 @@ pub fn pack(source: &Path, dest: &Path, version: u32) -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn unpack_file(source: &Path, dest: &Path) -> Result<()> {
|
||||||
|
let mut source_data = vec![];
|
||||||
|
File::open(source)?.read_to_end(&mut source_data)?;
|
||||||
|
let unpacked = unpack(source_data)?;
|
||||||
|
File::create(dest)?.write_all(&unpacked)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unpack(data: Vec<u8>) -> Result<Vec<u8>> {
|
||||||
|
let version = data[0];
|
||||||
|
if version == 0 {
|
||||||
|
return Ok(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
let base_data = BaseModule::for_format_version(version)?.to_wasm();
|
||||||
|
|
||||||
|
let mut data = &data[1..];
|
||||||
|
let mut base_data = base_data.as_slice();
|
||||||
|
|
||||||
|
let mut dest = base_data[..8].to_vec();
|
||||||
|
base_data = &base_data[8..];
|
||||||
|
|
||||||
|
fn section_length(data: &[u8]) -> Result<usize> {
|
||||||
|
let mut reader = BinaryReader::new_with_offset(&data[1..], 1);
|
||||||
|
let inner_len = reader.read_var_u32()? as usize;
|
||||||
|
let header_len = reader.original_position();
|
||||||
|
let len = header_len + inner_len;
|
||||||
|
dbg!(len);
|
||||||
|
if len > data.len() {
|
||||||
|
bail!("Section length greater than size of the rest of the file");
|
||||||
|
}
|
||||||
|
Ok(len)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn copy_section<'a>(dest: &mut Vec<u8>, source: &'a [u8]) -> Result<&'a [u8]> {
|
||||||
|
let len = section_length(source)?;
|
||||||
|
dest.extend_from_slice(&source[..len]);
|
||||||
|
Ok(&source[len..])
|
||||||
|
}
|
||||||
|
|
||||||
|
while !data.is_empty() || !base_data.is_empty() {
|
||||||
|
if !data.is_empty() && (base_data.is_empty() || data[0] <= base_data[0]) {
|
||||||
|
if !base_data.is_empty() && data[0] == base_data[0] {
|
||||||
|
base_data = &base_data[section_length(base_data)?..];
|
||||||
|
}
|
||||||
|
data = copy_section(&mut dest, data)?;
|
||||||
|
} else {
|
||||||
|
base_data = copy_section(&mut dest, base_data)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(dest)
|
||||||
|
}
|
||||||
|
|
||||||
fn to_val_type(type_: &wasmparser::Type) -> Result<ValType> {
|
fn to_val_type(type_: &wasmparser::Type) -> Result<ValType> {
|
||||||
use wasmparser::Type::*;
|
use wasmparser::Type::*;
|
||||||
Ok(match *type_ {
|
Ok(match *type_ {
|
||||||
@@ -49,6 +103,7 @@ struct ParsedModule<'a> {
|
|||||||
data: &'a [u8],
|
data: &'a [u8],
|
||||||
types: Section<Vec<base_module::FunctionType>>,
|
types: Section<Vec<base_module::FunctionType>>,
|
||||||
imports: Section<ImportSection>,
|
imports: Section<ImportSection>,
|
||||||
|
globals: Option<Section<u32>>,
|
||||||
functions: Section<Vec<u32>>,
|
functions: Section<Vec<u32>>,
|
||||||
exports: Section<Vec<(String, u32)>>,
|
exports: Section<Vec<(String, u32)>>,
|
||||||
function_bodies: Vec<wasmparser::FunctionBody<'a>>,
|
function_bodies: Vec<wasmparser::FunctionBody<'a>>,
|
||||||
@@ -60,6 +115,7 @@ impl<'a> ParsedModule<'a> {
|
|||||||
|
|
||||||
let mut type_section = None;
|
let mut type_section = None;
|
||||||
let mut import_section = None;
|
let mut import_section = None;
|
||||||
|
let mut global_section = None;
|
||||||
let mut function_section = None;
|
let mut function_section = None;
|
||||||
let mut export_section = None;
|
let mut export_section = None;
|
||||||
let mut function_bodies = Vec::new();
|
let mut function_bodies = Vec::new();
|
||||||
@@ -87,6 +143,9 @@ impl<'a> ParsedModule<'a> {
|
|||||||
Payload::ImportSection(reader) => {
|
Payload::ImportSection(reader) => {
|
||||||
import_section = Some(Section::new(range, ImportSection::parse(reader)?));
|
import_section = Some(Section::new(range, ImportSection::parse(reader)?));
|
||||||
}
|
}
|
||||||
|
Payload::GlobalSection(reader) => {
|
||||||
|
global_section = Some(Section::new(range, reader.get_count()));
|
||||||
|
}
|
||||||
Payload::FunctionSection(reader) => {
|
Payload::FunctionSection(reader) => {
|
||||||
function_section = Some(Section::new(range, read_function_section(reader)?));
|
function_section = Some(Section::new(range, read_function_section(reader)?));
|
||||||
}
|
}
|
||||||
@@ -107,6 +166,7 @@ impl<'a> ParsedModule<'a> {
|
|||||||
data,
|
data,
|
||||||
types: type_section.ok_or_else(|| anyhow!("No type section found"))?,
|
types: type_section.ok_or_else(|| anyhow!("No type section found"))?,
|
||||||
imports: import_section.ok_or_else(|| anyhow!("No import section found"))?,
|
imports: import_section.ok_or_else(|| anyhow!("No import section found"))?,
|
||||||
|
globals: global_section,
|
||||||
functions: function_section.ok_or_else(|| anyhow!("No function section found"))?,
|
functions: function_section.ok_or_else(|| anyhow!("No function section found"))?,
|
||||||
exports: export_section.ok_or_else(|| anyhow!("No export section found"))?,
|
exports: export_section.ok_or_else(|| anyhow!("No export section found"))?,
|
||||||
function_bodies,
|
function_bodies,
|
||||||
@@ -146,6 +206,8 @@ impl<'a> ParsedModule<'a> {
|
|||||||
|
|
||||||
let mut function_map = HashMap::new();
|
let mut function_map = HashMap::new();
|
||||||
let mut function_count = 0;
|
let mut function_count = 0;
|
||||||
|
let mut global_map = HashMap::new();
|
||||||
|
let mut global_count = 0;
|
||||||
|
|
||||||
if uses_base_types {
|
if uses_base_types {
|
||||||
if self.imports.data.memory > base.memory {
|
if self.imports.data.memory > base.memory {
|
||||||
@@ -185,16 +247,54 @@ impl<'a> ParsedModule<'a> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function_count += base.function_imports.len();
|
function_count += base.function_imports.len();
|
||||||
|
|
||||||
|
let base_global_import_map: HashMap<(String, String), (GlobalType, u32)> = base
|
||||||
|
.global_imports
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(idx, (module, field, type_))| {
|
||||||
|
(
|
||||||
|
(module.to_string(), field.clone()),
|
||||||
|
(type_.clone(), idx as u32),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
for (idx, glb) in self.imports.data.globals.iter().enumerate() {
|
||||||
|
if let Some((base_type, base_idx)) =
|
||||||
|
base_global_import_map.get(&(glb.module.clone(), glb.field.clone()))
|
||||||
|
{
|
||||||
|
if base_type == &glb.type_ {
|
||||||
|
global_map.insert(idx as u32, *base_idx);
|
||||||
} else {
|
} else {
|
||||||
|
bail!(
|
||||||
|
"Import global {}.{} has incompatible type",
|
||||||
|
glb.module,
|
||||||
|
glb.field
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bail!(
|
||||||
|
"Import global {}.{} not found in base",
|
||||||
|
glb.module,
|
||||||
|
glb.field
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
global_count += base.global_imports.len();
|
||||||
|
} else {
|
||||||
|
copy_section(&mut module, &self.data[self.imports.range.clone()])?;
|
||||||
|
|
||||||
function_map = (0..self.imports.data.functions.len() as u32)
|
function_map = (0..self.imports.data.functions.len() as u32)
|
||||||
.map(|i| (i, i))
|
.map(|i| (i, i))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
copy_section(&mut module, &self.data[self.imports.range.clone()])?;
|
|
||||||
|
|
||||||
function_count += self.imports.data.functions.len();
|
function_count += self.imports.data.functions.len();
|
||||||
|
|
||||||
|
global_map = (0..self.imports.data.globals.len() as u32)
|
||||||
|
.map(|i| (i, i))
|
||||||
|
.collect();
|
||||||
|
global_count += self.imports.data.globals.len();
|
||||||
}
|
}
|
||||||
|
|
||||||
let functions = {
|
let functions = {
|
||||||
@@ -246,6 +346,17 @@ impl<'a> ParsedModule<'a> {
|
|||||||
module.section(&function_section);
|
module.section(&function_section);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(ref globals) = self.globals {
|
||||||
|
copy_section(&mut module, &self.data[globals.range.clone()])?;
|
||||||
|
for i in 0..globals.data {
|
||||||
|
global_map.insert(
|
||||||
|
self.imports.data.globals.len() as u32 + i,
|
||||||
|
global_count as u32,
|
||||||
|
);
|
||||||
|
global_count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut base_exports = base.exports.clone();
|
let mut base_exports = base.exports.clone();
|
||||||
base_exports.sort();
|
base_exports.sort();
|
||||||
@@ -274,7 +385,12 @@ impl<'a> ParsedModule<'a> {
|
|||||||
let mut code_section = enc::CodeSection::new();
|
let mut code_section = enc::CodeSection::new();
|
||||||
|
|
||||||
for (_, function) in &functions {
|
for (_, function) in &functions {
|
||||||
code_section.function(&remap_function(function, &type_map, &function_map)?);
|
code_section.function(&remap_function(
|
||||||
|
function,
|
||||||
|
&type_map,
|
||||||
|
&function_map,
|
||||||
|
&global_map,
|
||||||
|
)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.section(&code_section);
|
module.section(&code_section);
|
||||||
@@ -292,10 +408,7 @@ fn copy_section(module: &mut wasm_encoder::Module, data: &[u8]) -> Result<()> {
|
|||||||
let data = &data[reader.current_position()..];
|
let data = &data[reader.current_position()..];
|
||||||
assert!(data.len() == size as usize);
|
assert!(data.len() == size as usize);
|
||||||
|
|
||||||
module.section(&wasm_encoder::RawSection {
|
module.section(&wasm_encoder::RawSection { id, data });
|
||||||
id,
|
|
||||||
data: &data[reader.current_position()..],
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -336,12 +449,14 @@ impl<T> Section<T> {
|
|||||||
struct ImportSection {
|
struct ImportSection {
|
||||||
memory: u32,
|
memory: u32,
|
||||||
functions: Vec<FunctionImport>,
|
functions: Vec<FunctionImport>,
|
||||||
|
globals: Vec<GlobalImport>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImportSection {
|
impl ImportSection {
|
||||||
fn parse(reader: ImportSectionReader) -> Result<ImportSection> {
|
fn parse(reader: ImportSectionReader) -> Result<ImportSection> {
|
||||||
let mut memory = 0;
|
let mut memory = 0;
|
||||||
let mut functions = vec![];
|
let mut functions = vec![];
|
||||||
|
let mut globals = vec![];
|
||||||
|
|
||||||
for import in reader {
|
for import in reader {
|
||||||
let import = import?;
|
let import = import?;
|
||||||
@@ -367,6 +482,16 @@ impl ImportSection {
|
|||||||
}
|
}
|
||||||
memory = mem.maximum.unwrap_or(mem.initial) as u32;
|
memory = mem.maximum.unwrap_or(mem.initial) as u32;
|
||||||
}
|
}
|
||||||
|
ImportSectionEntryType::Global(glbl) => {
|
||||||
|
globals.push(GlobalImport {
|
||||||
|
module: import.module.to_string(),
|
||||||
|
field: field.to_string(),
|
||||||
|
type_: GlobalType {
|
||||||
|
type_: to_val_type(&glbl.content_type)?,
|
||||||
|
mutable: glbl.mutable,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
_ => bail!("Unsupported import item {:?}", import.ty),
|
_ => bail!("Unsupported import item {:?}", import.ty),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -381,7 +506,11 @@ impl ImportSection {
|
|||||||
bail!("No memory import found");
|
bail!("No memory import found");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ImportSection { memory, functions })
|
Ok(ImportSection {
|
||||||
|
memory,
|
||||||
|
functions,
|
||||||
|
globals,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,6 +521,13 @@ struct FunctionImport {
|
|||||||
type_: u32,
|
type_: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct GlobalImport {
|
||||||
|
module: String,
|
||||||
|
field: String,
|
||||||
|
type_: GlobalType,
|
||||||
|
}
|
||||||
|
|
||||||
fn read_function_section(reader: FunctionSectionReader) -> Result<Vec<u32>> {
|
fn read_function_section(reader: FunctionSectionReader) -> Result<Vec<u32>> {
|
||||||
let mut functions = vec![];
|
let mut functions = vec![];
|
||||||
for func_type in reader {
|
for func_type in reader {
|
||||||
@@ -418,6 +554,7 @@ fn remap_function(
|
|||||||
reader: &FunctionBody,
|
reader: &FunctionBody,
|
||||||
type_map: &HashMap<u32, u32>,
|
type_map: &HashMap<u32, u32>,
|
||||||
function_map: &HashMap<u32, u32>,
|
function_map: &HashMap<u32, u32>,
|
||||||
|
global_map: &HashMap<u32, u32>,
|
||||||
) -> Result<enc::Function> {
|
) -> Result<enc::Function> {
|
||||||
let mut locals = Vec::new();
|
let mut locals = Vec::new();
|
||||||
for local in reader.get_locals_reader()? {
|
for local in reader.get_locals_reader()? {
|
||||||
@@ -440,6 +577,12 @@ fn remap_function(
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let global_idx = |idx: u32| -> Result<u32> {
|
||||||
|
Ok(*global_map
|
||||||
|
.get(&idx)
|
||||||
|
.ok_or_else(|| anyhow!("Global index out of range: {}", idx))?)
|
||||||
|
};
|
||||||
|
|
||||||
fn mem(m: wasmparser::MemoryImmediate) -> enc::MemArg {
|
fn mem(m: wasmparser::MemoryImmediate) -> enc::MemArg {
|
||||||
enc::MemArg {
|
enc::MemArg {
|
||||||
offset: m.offset,
|
offset: m.offset,
|
||||||
@@ -481,8 +624,8 @@ fn remap_function(
|
|||||||
De::LocalGet { local_index } => En::LocalGet(local_index),
|
De::LocalGet { local_index } => En::LocalGet(local_index),
|
||||||
De::LocalSet { local_index } => En::LocalSet(local_index),
|
De::LocalSet { local_index } => En::LocalSet(local_index),
|
||||||
De::LocalTee { local_index } => En::LocalTee(local_index),
|
De::LocalTee { local_index } => En::LocalTee(local_index),
|
||||||
De::GlobalGet { global_index } => En::GlobalGet(global_index),
|
De::GlobalGet { global_index } => En::GlobalGet(global_idx(global_index)?),
|
||||||
De::GlobalSet { global_index } => En::GlobalSet(global_index),
|
De::GlobalSet { global_index } => En::GlobalSet(global_idx(global_index)?),
|
||||||
De::I32Load { memarg } => En::I32Load(mem(memarg)),
|
De::I32Load { memarg } => En::I32Load(mem(memarg)),
|
||||||
De::I64Load { memarg } => En::I64Load(mem(memarg)),
|
De::I64Load { memarg } => En::I64Load(mem(memarg)),
|
||||||
De::F32Load { memarg } => En::F32Load(mem(memarg)),
|
De::F32Load { memarg } => En::F32Load(mem(memarg)),
|
||||||
|
|||||||
@@ -92,6 +92,10 @@ async function runModule(data) {
|
|||||||
importObject.env['reserved' + i] = () => { };
|
importObject.env['reserved' + i] = () => { };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < 16; ++i) {
|
||||||
|
importObject.env['g_reserved' + i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
let instance = new WebAssembly.Instance(await WebAssembly.compile(data), importObject);
|
let instance = new WebAssembly.Instance(await WebAssembly.compile(data), importObject);
|
||||||
|
|
||||||
let buffer = imageData.data;
|
let buffer = imageData.data;
|
||||||
|
|||||||
Reference in New Issue
Block a user