move all imports to module "env", some tweaks to rust example

This commit is contained in:
2021-11-06 19:46:16 +01:00
parent 32d2519d2d
commit d86f91789b
8 changed files with 126 additions and 86 deletions

View File

@@ -5,8 +5,8 @@ A nightly rust compiler is needed for the unstable sqrtf32
intrinsic.
Simply compiling with rustc as shown in build.sh results in a
339 byte tunnel.wasm. Using wasm-opt this can be reduced to
244 bytes.
342 byte tunnel.wasm. Using wasm-opt this can be reduced to
243 bytes.
When you disassemble this wasm file using wasm2wat you can see
these globals and exports:
@@ -21,5 +21,5 @@ values that are not simple scalars (i32, f32, etc.). Since our
code doesn't actually use any of that, we can just delete them
in a text editor and assemble the code again with wat2wasm.
This gives us a 200 byte wasm file. Running this through
This gives us a 199 byte wasm file. Running this through
uw8-tool pack brings us to the final size of 137 bytes.

View File

@@ -1,25 +1,43 @@
#![no_std]
#![feature(core_intrinsics)]
#[link(wasm_import_module = "math")]
mod env {
// "env" is the default module for imports, but it is still needed here
// since there is a compiler builtin of the same name which is used
// if we don't make it clear that this is a module import.
#[link(wasm_import_module = "env")]
extern "C" {
fn atan2(x: f32, y: f32) -> f32;
pub fn atan2(x: f32, y: f32) -> f32;
}
}
fn atan2(x: f32, y: f32) -> f32 {
unsafe { env::atan2(x, y) }
}
fn sqrt(v: f32) -> f32 {
unsafe { core::intrinsics::sqrtf32(v) }
}
fn ftoi(v: f32) -> i32 {
// The compiler is allowed to do bad things to our code if this
// ever results in a value that doesn't fit in an i32.
// (the joy of undefined behavior)
// But that would trap in wasm anyway, so we don't really
// care.
unsafe { v.to_int_unchecked() }
}
#[no_mangle]
pub fn tic(time: i32) {
unsafe {
for i in 0..320 * 256 {
let t = time as f32 / 10 as f32;
let x = (i % 320 - 160) as f32;
let y = (i / 320 - 128) as f32;
let d = 20000 as f32 / sqrt(x * x + y * y + 1 as f32);
let u = atan2(x, y) * 512f32 / 3.141;
let c = ((d + t).to_int_unchecked::<i32>() ^ (u + t).to_int_unchecked::<i32>()) as u8;
let c = (ftoi(d + t) ^ ftoi(u + t)) as u8;
unsafe {
*((120 + i) as *mut u8) = c;
}
}

Binary file not shown.

1
site/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/public/

View File

@@ -14,19 +14,18 @@ at offset 120 in memory.
The memory has to be imported as `"env" "memory"` and has a maximum size of 256kb (4 pages).
Other imports provided by the platform:
Other imports provided by the platform, also all in module `env`:
* in module `math`:
* * `fn acos(f32) -> f32`
* * `fn asin(f32) -> f32`
* * `fn atan(f32) -> f32`
* * `fn atan2(f32, f32) -> f32`
* * `fn cos(f32) -> f32`
* * `fn exp(f32, f32) -> f32`
* * `fn log(f32) -> f32`
* * `fn sin(f32) -> f32`
* * `fn tan(f32) -> f32`
* * `fn pow(f32) -> f32`
* `fn acos(f32) -> f32`
* `fn asin(f32) -> f32`
* `fn atan(f32) -> f32`
* `fn atan2(f32, f32) -> f32`
* `fn cos(f32) -> f32`
* `fn exp(f32, f32) -> f32`
* `fn log(f32) -> f32`
* `fn sin(f32) -> f32`
* `fn tan(f32) -> f32`
* `fn pow(f32) -> f32`
## `.uw8` format

File diff suppressed because one or more lines are too long

View File

@@ -1,25 +1,25 @@
use std::{collections::HashMap, fs::File, path::Path};
use anyhow::{bail, Result};
use std::io::prelude::*;
use wasm_encoder::{
CodeSection, EntityType, Export, ExportSection, Function, FunctionSection,
ImportSection, Instruction, MemoryType, Module, TypeSection, ValType,
CodeSection, EntityType, Export, ExportSection, Function, FunctionSection, ImportSection,
Instruction, MemoryType, Module, TypeSection, ValType,
};
use ValType::*;
use anyhow::{Result, bail};
use std::io::prelude::*;
pub struct BaseModule {
pub types: Vec<FunctionType>,
pub function_imports: Vec<(&'static str, String, u32)>,
pub functions: Vec<u32>,
pub exports: Vec<(&'static str, u32)>,
pub memory: u32
pub memory: u32,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct FunctionType {
pub params: Vec<ValType>,
pub result: Option<ValType>
pub result: Option<ValType>,
}
impl BaseModule {
@@ -48,18 +48,24 @@ impl BaseModule {
}
let mut functions = vec![];
add_function(&mut functions, &type_map, "math","sin", &[F32], Some(F32));
add_function(&mut functions, &type_map, "math", "cos", &[F32], Some(F32));
add_function(&mut functions, &type_map, "math", "tan", &[F32], Some(F32));
add_function(&mut functions, &type_map, "math", "asin", &[F32], Some(F32));
add_function(&mut functions, &type_map, "math", "acos", &[F32], Some(F32));
add_function(&mut functions, &type_map, "math", "atan", &[F32], Some(F32));
add_function(&mut functions, &type_map, "math", "atan2", &[F32, F32], Some(F32));
add_function(&mut functions, &type_map, "math", "pow", &[F32, F32], Some(F32));
add_function(&mut functions, &type_map, "math", "log", &[F32], Some(F32));
add_function(&mut functions, &type_map, "sin", &[F32], Some(F32));
add_function(&mut functions, &type_map, "cos", &[F32], Some(F32));
add_function(&mut functions, &type_map, "tan", &[F32], Some(F32));
add_function(&mut functions, &type_map, "asin", &[F32], Some(F32));
add_function(&mut functions, &type_map, "acos", &[F32], Some(F32));
add_function(&mut functions, &type_map, "atan", &[F32], Some(F32));
add_function(&mut functions, &type_map, "atan2", &[F32, F32], Some(F32));
add_function(&mut functions, &type_map, "pow", &[F32, F32], Some(F32));
add_function(&mut functions, &type_map, "log", &[F32], Some(F32));
for i in functions.len()..64 {
add_function(&mut functions, &type_map, "uw8", &format!("reserved{}", i), &[], None);
add_function(
&mut functions,
&type_map,
&format!("reserved{}", i),
&[],
None,
);
}
let first_function = functions.len() as u32;
@@ -69,7 +75,7 @@ impl BaseModule {
function_imports: functions,
functions: vec![lookup_type(&type_map, &[I32], None)],
exports: vec![("tic", first_function)],
memory: 4
memory: 4,
})
}
@@ -92,11 +98,15 @@ impl BaseModule {
imports.import(*module, Some(name.as_str()), EntityType::Function(*type_));
}
imports.import("env", Some("memory"), MemoryType {
imports.import(
"env",
Some("memory"),
MemoryType {
minimum: m.memory as u64,
maximum: None,
memory64: false
});
memory64: false,
},
);
module.section(&imports);
}
@@ -143,14 +153,28 @@ impl BaseModule {
}
}
fn add_function(functions: &mut Vec<(&'static str, String, u32)>, type_map: &HashMap<FunctionType, u32>, module: &'static str, name: &str, params: &[ValType], result: Option<ValType>) {
functions.push((module, name.to_string(), lookup_type(type_map, params, result)));
fn add_function(
functions: &mut Vec<(&'static str, String, u32)>,
type_map: &HashMap<FunctionType, u32>,
name: &str,
params: &[ValType],
result: Option<ValType>,
) {
functions.push((
"env".into(),
name.to_string(),
lookup_type(type_map, params, result),
));
}
fn lookup_type(type_map: &HashMap<FunctionType, u32>, params: &[ValType], result: Option<ValType>) -> u32 {
fn lookup_type(
type_map: &HashMap<FunctionType, u32>,
params: &[ValType],
result: Option<ValType>,
) -> u32 {
let key = FunctionType {
params: params.to_vec(),
result
result,
};
*type_map.get(&key).unwrap()
}

View File

@@ -82,16 +82,14 @@ async function runModule(data) {
env: {
memory: new WebAssembly.Memory({ initial: 4, maximum: 4 }),
},
math: {},
uw8: {}
};
for (let n of ['acos', 'asin', 'atan', 'atan2', 'cos', 'exp', 'log', 'sin', 'tan', 'pow']) {
importObject.math[n] = Math[n];
importObject.env[n] = Math[n];
}
for (let i = 9; i < 64; ++i) {
importObject.uw8['reserved' + i] = () => {};
importObject.env['reserved' + i] = () => { };
}
let instance = new WebAssembly.Instance(await WebAssembly.compile(data), importObject);