more stuff
This commit is contained in:
parent
ad1a16d150
commit
6c87f4f9b8
913
Cargo.lock
generated
913
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
|||
[workspace]
|
||||
members=[ "wars", "wars-macro","wars-rt", "wars-test"]
|
||||
members=[ "waffle-func-reloop", "wars", "wars-component", "wars-macro","wars-rt", "wars-test"]
|
||||
resolver="2"
|
||||
|
||||
[workspace.dependencies]
|
||||
|
|
10
waffle-func-reloop/Cargo.toml
Normal file
10
waffle-func-reloop/Cargo.toml
Normal file
|
@ -0,0 +1,10 @@
|
|||
[package]
|
||||
name = "waffle-func-reloop"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
portal-pc-waffle.workspace = true
|
||||
relooper = "0.1.0"
|
40
waffle-func-reloop/src/lib.rs
Normal file
40
waffle-func-reloop/src/lib.rs
Normal file
|
@ -0,0 +1,40 @@
|
|||
use relooper::ShapedBlock;
|
||||
use waffle::{cfg::CFGInfo, Block, FunctionBody};
|
||||
|
||||
pub fn go(b: &FunctionBody) -> Box<ShapedBlock<Block>> {
|
||||
let cfg = CFGInfo::new(b);
|
||||
let reloop = std::panic::catch_unwind(|| {
|
||||
relooper::reloop(
|
||||
b.blocks
|
||||
.entries()
|
||||
.filter(|k| cfg.dominates(b.entry, k.0))
|
||||
.map(|(k, l)| {
|
||||
(
|
||||
k,
|
||||
l.succs
|
||||
.iter()
|
||||
.cloned()
|
||||
.chain(b.blocks.iter().filter(|x| cfg.dominates(*x, k)))
|
||||
.collect(),
|
||||
)
|
||||
})
|
||||
// .chain(once((Block::invalid(), vec![b.entry])))
|
||||
.collect(),
|
||||
// Block::invalid(),
|
||||
b.entry,
|
||||
)
|
||||
});
|
||||
let reloop = match reloop {
|
||||
Ok(a) => a,
|
||||
Err(e) => {
|
||||
panic!(
|
||||
"reloop failure ({}) in {}",
|
||||
e.downcast_ref::<&str>()
|
||||
.map(|a| *a)
|
||||
.unwrap_or("unknown panic"),
|
||||
b.display("", None)
|
||||
);
|
||||
}
|
||||
};
|
||||
reloop
|
||||
}
|
14
wars-component/Cargo.toml
Normal file
14
wars-component/Cargo.toml
Normal file
|
@ -0,0 +1,14 @@
|
|||
[package]
|
||||
name = "wars-component"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
golem-wasm-ast = "0.2.2"
|
||||
proc-macro2 = "1.0.85"
|
||||
quasiquote = "0.1.1"
|
||||
quote = "1.0.36"
|
||||
syn = "2.0.66"
|
||||
wars = { version = "0.1.0", path = "../wars" }
|
6
wars-component/src/lib.rs
Normal file
6
wars-component/src/lib.rs
Normal file
|
@ -0,0 +1,6 @@
|
|||
pub trait Component{
|
||||
|
||||
}
|
||||
impl Component for Opts<golem_wasm_ast::Component>{
|
||||
|
||||
}
|
|
@ -11,9 +11,9 @@ proc-macro2 = "1.0.85"
|
|||
quote = "1.0.36"
|
||||
syn = "2.0.66"
|
||||
wars = { version = "0.1.0", path = "../wars" }
|
||||
wars-rt = { version = "0.1.0", path = "../wars-rt" }
|
||||
wat = "1.209.1"
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
wars-rt = { version = "0.1.0", path = "../wars-rt" }
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
use std::sync::Arc;
|
||||
use std::{collections::BTreeMap, sync::Arc};
|
||||
|
||||
use expander::{Edition, Expander};
|
||||
use proc_macro::TokenStream;
|
||||
use proc_macro2::Span;
|
||||
use quote::quote;
|
||||
use syn::{parse::Parse, parse_macro_input, Ident, Path, Token};
|
||||
use wars::Opts;
|
||||
use syn::{parse::Parse, parse_macro_input, Ident, LitBool, Path, Token};
|
||||
use wars::{Flags, Opts};
|
||||
|
||||
struct O {
|
||||
pub crate_path: syn::Path,
|
||||
pub module: Vec<u8>,
|
||||
pub name: Ident,
|
||||
// pub cfg: Arc<dyn ImportCfg>,
|
||||
pub flags: Flags,
|
||||
pub embed: proc_macro2::TokenStream,
|
||||
pub data: BTreeMap<Ident, proc_macro2::TokenStream>, // pub cfg: Arc<dyn ImportCfg>,
|
||||
}
|
||||
// struct NoopCfg {}
|
||||
// impl ImportCfg for NoopCfg {
|
||||
|
@ -27,6 +29,9 @@ impl Parse for O {
|
|||
crate_path: syn::parse(quote! {::wars_rt}.into())?,
|
||||
module: vec![],
|
||||
name: Ident::new("Wars", Span::call_site()),
|
||||
flags: Default::default(),
|
||||
embed: Default::default(),
|
||||
data: BTreeMap::new(),
|
||||
// cfg: Arc::new(NoopCfg {}),
|
||||
};
|
||||
while input.lookahead1().peek(Ident) {
|
||||
|
@ -59,6 +64,22 @@ impl Parse for O {
|
|||
"name" => {
|
||||
o.name = input.parse()?;
|
||||
}
|
||||
"r#async" => {
|
||||
let b: LitBool = input.parse()?;
|
||||
if b.value {
|
||||
o.flags |= Flags::ASYNC
|
||||
} else {
|
||||
o.flags &= Flags::ASYNC.complement();
|
||||
}
|
||||
}
|
||||
"legacy_host" => {
|
||||
let b: LitBool = input.parse()?;
|
||||
if b.value {
|
||||
o.flags |= Flags::LEGACY
|
||||
} else {
|
||||
o.flags &= Flags::LEGACY.complement();
|
||||
}
|
||||
}
|
||||
_ => return Err(syn::Error::new(i.span(), "unexpected type")),
|
||||
};
|
||||
let _comma: Token![,] = input.parse()?;
|
||||
|
@ -73,12 +94,18 @@ impl Parse for O {
|
|||
#[proc_macro]
|
||||
pub fn wars(a: TokenStream) -> TokenStream {
|
||||
let o = parse_macro_input!(a as O);
|
||||
let x = wars::go(&Opts {
|
||||
crate_path: o.crate_path,
|
||||
module: o.module,
|
||||
name: o.name,
|
||||
// cfg: o.cfg,
|
||||
});
|
||||
let x = wars::go(
|
||||
&Opts {
|
||||
crate_path: o.crate_path,
|
||||
module: o.module,
|
||||
name: o.name,
|
||||
flags: o.flags,
|
||||
embed: o.embed,
|
||||
data: o.data,
|
||||
// cfg: o.cfg,
|
||||
}
|
||||
.to_mod(),
|
||||
);
|
||||
let expanded = Expander::new("wars")
|
||||
.add_comment("This is generated code!".to_owned())
|
||||
.fmt(Edition::_2021)
|
||||
|
@ -92,3 +119,20 @@ pub fn wars(a: TokenStream) -> TokenStream {
|
|||
});
|
||||
expanded.into()
|
||||
}
|
||||
|
||||
// #[proc_macro]
|
||||
// pub fn wasix(a: TokenStream) -> TokenStream {
|
||||
// let x = wars::wasix::wasix();
|
||||
// let expanded = Expander::new("wars_wasix")
|
||||
// .add_comment("This is generated code!".to_owned())
|
||||
// .fmt(Edition::_2021)
|
||||
// .verbose(true)
|
||||
// // common way of gating this, by making it part of the default feature set
|
||||
// .dry(cfg!(feature = "no-file-expansion"))
|
||||
// .write_to_out_dir(x.clone())
|
||||
// .unwrap_or_else(|e| {
|
||||
// eprintln!("Failed to write to file: {:?}", e);
|
||||
// x
|
||||
// });
|
||||
// expanded.into()
|
||||
// }
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
wars_macro::wars!(
|
||||
file = "target/wasm32-unknown-unknown/debug/wars_test.wasm",
|
||||
r#async = true,
|
||||
);
|
||||
|
||||
fn x<A: Wars>(){
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -12,3 +12,5 @@ derive_more = "0.99.17"
|
|||
paste = "1.0.15"
|
||||
tramp = "0.3.0"
|
||||
tuple_list = "0.1.3"
|
||||
wars-macro = { version = "0.1.0", path = "../wars-macro" }
|
||||
wasm_runtime_layer = "0.4.0"
|
||||
|
|
|
@ -2,6 +2,10 @@ use std::sync::Arc;
|
|||
|
||||
use anyhow::Context;
|
||||
use tramp::{tramp, BorrowRec, Thunk};
|
||||
pub mod unsync;
|
||||
pub fn ret<'a,T>(a: T) -> BorrowRec<'a,T>{
|
||||
BorrowRec::Ret(a)
|
||||
}
|
||||
pub trait CtxSpec: Sized {
|
||||
type ExternRef: Clone;
|
||||
}
|
||||
|
@ -16,7 +20,7 @@ pub enum Value<C: CtxSpec> {
|
|||
&'a mut C,
|
||||
Vec<Value<C>>,
|
||||
) -> tramp::BorrowRec<'a, anyhow::Result<Vec<Value<C>>>>
|
||||
+ 'static,
|
||||
+ Send + Sync + 'static,
|
||||
>,
|
||||
),
|
||||
Null,
|
||||
|
@ -140,13 +144,13 @@ pub fn map_rec<'a, T: 'a, U>(
|
|||
}
|
||||
}
|
||||
pub type Df<A, B, C> =
|
||||
Arc<dyn for<'a> Fn(&'a mut C, A) -> tramp::BorrowRec<'a, anyhow::Result<B>> + 'static>;
|
||||
Arc<dyn for<'a> Fn(&'a mut C, A) -> tramp::BorrowRec<'a, anyhow::Result<B>> + Send + Sync + 'static>;
|
||||
|
||||
pub fn da<
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
F: for<'a> Fn(&'a mut C, A) -> tramp::BorrowRec<'a, anyhow::Result<B>> + 'static,
|
||||
F: for<'a> Fn(&'a mut C, A) -> tramp::BorrowRec<'a, anyhow::Result<B>> + Send + Sync + 'static,
|
||||
>(
|
||||
f: F,
|
||||
) -> Df<A,B,C> {
|
||||
|
|
207
wars-rt/src/func/unsync.rs
Normal file
207
wars-rt/src/func/unsync.rs
Normal file
|
@ -0,0 +1,207 @@
|
|||
use std::{future::Future, pin::Pin, sync::Arc};
|
||||
|
||||
use anyhow::Context;
|
||||
// use tramp::{tramp, BorrowRec, Thunk};
|
||||
pub fn ret<'a,T>(a: T) -> AsyncRec<'a,T>{
|
||||
AsyncRec::Ret(a)
|
||||
}
|
||||
pub enum AsyncRec<'a,T>{
|
||||
Ret(T),
|
||||
Async(Pin<Box<dyn Future<Output = AsyncRec<'a,T>> + Send + Sync + 'a>>)
|
||||
}
|
||||
impl<'a,T> AsyncRec<'a,T>{
|
||||
pub async fn go(mut self) -> T{
|
||||
loop{
|
||||
self = match self{
|
||||
AsyncRec::Ret(r) => return r,
|
||||
AsyncRec::Async(a) => a.await,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pub trait CtxSpec: Sized {
|
||||
type ExternRef: Clone;
|
||||
}
|
||||
pub enum Value<C: CtxSpec> {
|
||||
I32(u32),
|
||||
I64(u64),
|
||||
F32(f32),
|
||||
F64(f64),
|
||||
FunRef(
|
||||
Arc<
|
||||
dyn for<'a> Fn(
|
||||
&'a mut C,
|
||||
Vec<Value<C>>,
|
||||
) -> AsyncRec<'a, anyhow::Result<Vec<Value<C>>>>
|
||||
+ Send + Sync + 'static,
|
||||
>,
|
||||
),
|
||||
Null,
|
||||
ExRef(C::ExternRef),
|
||||
}
|
||||
pub fn call_ref<'a, A: CoeVec<C> + 'static, B: CoeVec<C> + 'static, C: CtxSpec + 'static>(
|
||||
ctx: &'a mut C,
|
||||
go: Df<A,B,C>,
|
||||
a: A,
|
||||
) -> AsyncRec<'a, anyhow::Result<B>> {
|
||||
// let go: Df<A, B, C> = cast(go);
|
||||
go(ctx, a)
|
||||
}
|
||||
|
||||
impl<C: CtxSpec> Clone for Value<C> {
|
||||
fn clone(&self) -> Self {
|
||||
match self {
|
||||
Self::I32(arg0) => Self::I32(arg0.clone()),
|
||||
Self::I64(arg0) => Self::I64(arg0.clone()),
|
||||
Self::F32(arg0) => Self::F32(arg0.clone()),
|
||||
Self::F64(arg0) => Self::F64(arg0.clone()),
|
||||
Self::FunRef(arg0) => Self::FunRef(arg0.clone()),
|
||||
Self::Null => Self::Null,
|
||||
Self::ExRef(e) => Self::ExRef(e.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
pub trait Coe<C: CtxSpec>: Sized {
|
||||
fn coe(self) -> Value<C>;
|
||||
fn uncoe(x: Value<C>) -> anyhow::Result<Self>;
|
||||
}
|
||||
pub fn cast<A: Coe<C> + 'static, B: Coe<C> + 'static, C: CtxSpec>(a: A) -> B {
|
||||
let a = match castaway::cast!(a, B) {
|
||||
Ok(b) => return b,
|
||||
Err(a) => a,
|
||||
};
|
||||
B::uncoe(A::coe(a)).unwrap()
|
||||
}
|
||||
impl<C: CtxSpec> Coe<C> for Value<C> {
|
||||
fn coe(self) -> Value<C> {
|
||||
self
|
||||
}
|
||||
|
||||
fn uncoe(x: Value<C>) -> anyhow::Result<Self> {
|
||||
Ok(x)
|
||||
}
|
||||
}
|
||||
impl<C: CtxSpec, D: Coe<C>> Coe<C> for Option<D> {
|
||||
fn coe(self) -> Value<C> {
|
||||
match self {
|
||||
None => Value::Null,
|
||||
Some(d) => d.coe(),
|
||||
}
|
||||
}
|
||||
|
||||
fn uncoe(x: Value<C>) -> anyhow::Result<Self> {
|
||||
if let Value::Null = x {
|
||||
return Ok(None);
|
||||
}
|
||||
return Ok(Some(D::uncoe(x)?));
|
||||
}
|
||||
}
|
||||
macro_rules! coe_impl_prim {
|
||||
($a:tt in $b:ident) => {
|
||||
impl<C: CtxSpec> Coe<C> for $a {
|
||||
fn coe(self) -> Value<C> {
|
||||
Value::$b(self)
|
||||
}
|
||||
fn uncoe(x: Value<C>) -> anyhow::Result<Self> {
|
||||
match x {
|
||||
Value::$b(a) => Ok(a),
|
||||
_ => anyhow::bail!("invalid type"),
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
coe_impl_prim!(u32 in I32);
|
||||
coe_impl_prim!(u64 in I64);
|
||||
coe_impl_prim!(f32 in F32);
|
||||
coe_impl_prim!(f64 in F64);
|
||||
pub trait CoeVec<C: CtxSpec>: Sized {
|
||||
fn coe(self) -> Vec<Value<C>>;
|
||||
fn uncoe(a: Vec<Value<C>>) -> anyhow::Result<Self>;
|
||||
}
|
||||
impl<C: CtxSpec> CoeVec<C> for () {
|
||||
fn coe(self) -> Vec<Value<C>> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn uncoe(a: Vec<Value<C>>) -> anyhow::Result<Self> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl<C: CtxSpec, A: Coe<C>, B: CoeVec<C>> CoeVec<C> for (A, B) {
|
||||
fn coe(self) -> Vec<Value<C>> {
|
||||
let mut a = self.1.coe();
|
||||
a.push(self.0.coe());
|
||||
return a;
|
||||
}
|
||||
|
||||
fn uncoe(mut a: Vec<Value<C>>) -> anyhow::Result<Self> {
|
||||
let Some(x) = a.pop() else {
|
||||
anyhow::bail!("list too small")
|
||||
};
|
||||
let y = A::uncoe(x).context("invalid item (note coe lists are REVERSED)")?;
|
||||
let z = B::uncoe(a)?;
|
||||
Ok((y, z))
|
||||
}
|
||||
}
|
||||
pub fn map_rec<'a, T: 'a, U>(
|
||||
r: AsyncRec<'a, T>,
|
||||
go: impl FnOnce(T) -> U + Send + Sync + 'a,
|
||||
) -> AsyncRec<'a, U> {
|
||||
match r {
|
||||
AsyncRec::Ret(x) => AsyncRec::Ret(go(x)),
|
||||
AsyncRec::Async(a) => AsyncRec::Async(Box::pin(async move{
|
||||
let v = a.await;
|
||||
map_rec(v, go)
|
||||
})),
|
||||
}
|
||||
}
|
||||
pub type Df<A, B, C> =
|
||||
Arc<dyn for<'a> Fn(&'a mut C, A) -> AsyncRec<'a, anyhow::Result<B>> + Send + Sync + 'static>;
|
||||
|
||||
pub fn da<
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
F: for<'a> Fn(&'a mut C, A) -> AsyncRec<'a, anyhow::Result<B>> + Send + Sync + 'static,
|
||||
>(
|
||||
f: F,
|
||||
) -> Df<A,B,C> {
|
||||
Arc::new(f)
|
||||
}
|
||||
|
||||
impl<C: CtxSpec + 'static, A: CoeVec<C> + 'static, B: CoeVec<C> + 'static> Coe<C> for Df<A, B, C> {
|
||||
fn coe(self) -> Value<C> {
|
||||
pub fn x<
|
||||
C: CtxSpec,
|
||||
T: for<'a> Fn(
|
||||
&'a mut C,
|
||||
Vec<Value<C>>,
|
||||
) -> AsyncRec<'a, anyhow::Result<Vec<Value<C>>>>
|
||||
+ 'static,
|
||||
>(
|
||||
a: T,
|
||||
) -> T {
|
||||
return a;
|
||||
}
|
||||
Value::FunRef(Arc::new(x(move |ctx, x| {
|
||||
let x = match A::uncoe(x) {
|
||||
Ok(x) => x,
|
||||
Err(e) => return AsyncRec::Ret(Err(e)),
|
||||
};
|
||||
let x = self(ctx, x);
|
||||
map_rec(x, |a| a.map(|b| b.coe()))
|
||||
})))
|
||||
}
|
||||
|
||||
fn uncoe(x: Value<C>) -> anyhow::Result<Self> {
|
||||
let Value::FunRef(x) = x else {
|
||||
anyhow::bail!("invalid value")
|
||||
};
|
||||
Ok(Arc::new(move |ctx, a| {
|
||||
let v = a.coe();
|
||||
let v = x(ctx, v);
|
||||
map_rec(v, |a| a.and_then(B::uncoe))
|
||||
}))
|
||||
}
|
||||
}
|
|
@ -1,7 +1,85 @@
|
|||
pub mod func;
|
||||
pub mod wrl;
|
||||
pub mod wasix;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
// use as_ref::AsSlice;
|
||||
use func::CtxSpec;
|
||||
pub use func::Value;
|
||||
pub trait Memory {
|
||||
fn read<'a>(&'a self, a: usize, s: usize) -> anyhow::Result<Box<dyn AsRef<[u8]> + 'a>>;
|
||||
fn write(&mut self, a: usize, x: &[u8]) -> anyhow::Result<()>;
|
||||
fn size(&self) -> anyhow::Result<usize>;
|
||||
fn grow(&mut self, x: usize) -> anyhow::Result<()>;
|
||||
}
|
||||
impl Memory for Vec<u8> {
|
||||
fn read<'a>(&'a self, a: usize, s: usize) -> anyhow::Result<Box<dyn AsRef<[u8]> + 'a>>{
|
||||
Ok(Box::new(&self[a..][..s]))
|
||||
}
|
||||
|
||||
fn write(&mut self, a: usize, x: &[u8]) -> anyhow::Result<()> {
|
||||
self[a..][..x.len()].copy_from_slice(x);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn size(&self) -> anyhow::Result<usize> {
|
||||
Ok(self.len())
|
||||
}
|
||||
|
||||
fn grow(&mut self, x: usize) -> anyhow::Result<()> {
|
||||
self.extend((0..x).map(|a| 0u8));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl<T: Memory> Memory for Arc<Mutex<T>>{
|
||||
fn read<'a>(&'a self, a: usize, s: usize) -> anyhow::Result<Box<dyn AsRef<[u8]> + 'a>> {
|
||||
let l = self.lock().unwrap();
|
||||
let r = l.read(a, s)?;
|
||||
return Ok(Box::new(r.as_ref().as_ref().to_vec()));
|
||||
}
|
||||
|
||||
fn write(&mut self, a: usize, x: &[u8]) -> anyhow::Result<()> {
|
||||
let mut l = self.lock().unwrap();
|
||||
return l.write(a, x);
|
||||
}
|
||||
|
||||
fn size(&self) -> anyhow::Result<usize> {
|
||||
let l = self.lock().unwrap();
|
||||
return l.size();
|
||||
}
|
||||
|
||||
fn grow(&mut self, x: usize) -> anyhow::Result<()> {
|
||||
let mut l = self.lock().unwrap();
|
||||
return l.grow(x)
|
||||
}
|
||||
}
|
||||
pub unsafe fn host_memory() -> impl Memory{
|
||||
struct W{}
|
||||
impl Memory for W{
|
||||
fn read<'a>(&'a self, a: usize, s: usize) -> anyhow::Result<Box<dyn AsRef<[u8]> + 'a>> {
|
||||
return Ok(Box::new(unsafe{
|
||||
std::slice::from_raw_parts(a as *const u8, s)
|
||||
}))
|
||||
}
|
||||
|
||||
fn write(&mut self, a: usize, x: &[u8]) -> anyhow::Result<()> {
|
||||
let n = unsafe{
|
||||
std::slice::from_raw_parts_mut(a as *mut u8, x.len())
|
||||
};
|
||||
n.copy_from_slice(x);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fn size(&self) -> anyhow::Result<usize> {
|
||||
anyhow::bail!("host memory cannot use size")
|
||||
}
|
||||
|
||||
fn grow(&mut self, x: usize) -> anyhow::Result<()> {
|
||||
anyhow::bail!("host memory cannot use grow")
|
||||
}
|
||||
}
|
||||
return W{};
|
||||
}
|
||||
pub mod _rexport {
|
||||
pub use anyhow;
|
||||
pub use tramp;
|
||||
|
@ -135,59 +213,61 @@ macro_rules! int_ty{
|
|||
Ok(tuple_list::tuple_list!(a.wrapping_sub(b)))
|
||||
}
|
||||
//LOADS and STORES
|
||||
pub fn [<$p load>]<T: TryInto<usize>>(a: &mut Vec<u8>, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||
let r = &a[b.try_into()?..][..std::mem::size_of::<$int>()];
|
||||
Ok(tuple_list::tuple_list!($int::from_ne_bytes(r.try_into()?)))
|
||||
pub fn [<$p load>]<T: TryInto<usize>,M: Memory + ?Sized>(a: &mut M, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||
let r = a.read(b.try_into()?,std::mem::size_of::<$int>())?;
|
||||
Ok(tuple_list::tuple_list!($int::from_ne_bytes(r.as_ref().as_ref().try_into()?)))
|
||||
}
|
||||
pub fn [<$p store>]<T: TryInto<usize>>(a: &mut Vec<u8>, b: T, c: $int) -> anyhow::Result<()> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||
let mut r = &mut a[b.try_into()?..][..std::mem::size_of::<$int>()];
|
||||
r.copy_from_slice(&c.to_ne_bytes());
|
||||
pub fn [<$p store>]<T: TryInto<usize>,M: Memory + ?Sized>(a: &mut M, b: T, c: $int) -> anyhow::Result<()> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||
// let mut r = &mut a[b.try_into()?..][..std::mem::size_of::<$int>()];
|
||||
// r.copy_from_slice(&c.to_ne_bytes());
|
||||
a.write(b.try_into()?,&c.to_ne_bytes())?;
|
||||
Ok(())
|
||||
}
|
||||
//8 BIT
|
||||
pub fn [<$p load8u>]<T: TryInto<usize>>(a: &mut Vec<u8>, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||
let r = a[b.try_into()?..][0];
|
||||
pub fn [<$p load8u>]<T: TryInto<usize>,M: Memory + ?Sized>(a: &mut M, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||
let r = a.read(b.try_into()?,1)?.as_ref().as_ref()[0];
|
||||
Ok(tuple_list::tuple_list!(r as $int))
|
||||
}
|
||||
pub fn [<$p load8s>]<T: TryInto<usize>>(a: &mut Vec<u8>, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||
let r = a[b.try_into()?..][0];
|
||||
pub fn [<$p load8s>]<T: TryInto<usize>,M: Memory + ?Sized>(a: &mut M, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||
let r = a.read(b.try_into()?,1)?.as_ref().as_ref()[0];
|
||||
Ok(tuple_list::tuple_list!(r as i8 as $p as $int))
|
||||
}
|
||||
pub fn [<$p store8>]<T: TryInto<usize>>(a: &mut Vec<u8>, b: T, c: $int) -> anyhow::Result<()> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||
let mut r = &mut a[b.try_into()?..][..1];
|
||||
r[0] = (c & 0xff) as u8;
|
||||
pub fn [<$p store8>]<T: TryInto<usize>,M: Memory + ?Sized>(a: &mut M, b: T, c: $int) -> anyhow::Result<()> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||
// let mut r = &mut a[b.try_into()?..][..1];
|
||||
// r[0] = (c & 0xff) as u8;
|
||||
a.write(b.try_into()?,&[(c & 0xff) as u8])?;
|
||||
Ok(())
|
||||
}
|
||||
//16 BIT
|
||||
pub fn [<$p load16u>]<T: TryInto<usize>>(a: &mut Vec<u8>, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||
let r = &a[b.try_into()?..][..2];
|
||||
let r = u16::from_ne_bytes(r.try_into()?);
|
||||
pub fn [<$p load16u>]<T: TryInto<usize>,M: Memory + ?Sized>(a: &mut M, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||
let r = a.read(b.try_into()?,2)?;
|
||||
let r = u16::from_ne_bytes(r.as_ref().as_ref().try_into()?);
|
||||
Ok(tuple_list::tuple_list!(r as $int))
|
||||
}
|
||||
pub fn [<$p load16s>]<T: TryInto<usize>>(a: &mut Vec<u8>, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||
let r = &a[b.try_into()?..][..2];
|
||||
let r = u16::from_ne_bytes(r.try_into()?);
|
||||
pub fn [<$p load16s>]<T: TryInto<usize>,M: Memory + ?Sized>(a: &mut M, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||
let r = a.read(b.try_into()?,2)?;
|
||||
let r = u16::from_ne_bytes(r.as_ref().as_ref().try_into()?);
|
||||
Ok(tuple_list::tuple_list!(r as i16 as $p as $int))
|
||||
}
|
||||
pub fn [<$p store16>]<T: TryInto<usize>>(a: &mut Vec<u8>, b: T, c: $int) -> anyhow::Result<()> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||
let mut r = &mut a[b.try_into()?..][..2];
|
||||
r.copy_from_slice(&((c & 0xff) as u16).to_ne_bytes());
|
||||
pub fn [<$p store16>]<T: TryInto<usize>,M: Memory + ?Sized>(a: &mut M, b: T, c: $int) -> anyhow::Result<()> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||
// let mut r = &mut a[b.try_into()?..][..2];
|
||||
a.write(b.try_into()?,&((c & 0xffff) as u16).to_ne_bytes())?;
|
||||
Ok(())
|
||||
}
|
||||
//32 BIT
|
||||
pub fn [<$p load32u>]<T: TryInto<usize>>(a: &mut Vec<u8>, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||
let r = &a[b.try_into()?..][..4];
|
||||
let r = u32::from_ne_bytes(r.try_into()?);
|
||||
pub fn [<$p load32u>]<T: TryInto<usize>,M: Memory + ?Sized>(a: &mut M, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||
let r = a.read(b.try_into()?,4)?;
|
||||
let r = u32::from_ne_bytes(r.as_ref().as_ref().try_into()?);
|
||||
Ok(tuple_list::tuple_list!(r as $int))
|
||||
}
|
||||
pub fn [<$p load32s>]<T: TryInto<usize>>(a: &mut Vec<u8>, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||
let r = &a[b.try_into()?..][..4];
|
||||
let r = u32::from_ne_bytes(r.try_into()?);
|
||||
pub fn [<$p load32s>]<T: TryInto<usize>,M: Memory + ?Sized>(a: &mut M, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||
let r = a.read(b.try_into()?,4)?;
|
||||
let r = u32::from_ne_bytes(r.as_ref().as_ref().try_into()?);
|
||||
Ok(tuple_list::tuple_list!(r as i32 as $p as $int))
|
||||
}
|
||||
pub fn [<$p store32>]<T: TryInto<usize>>(a: &mut Vec<u8>, b: T, c: $int) -> anyhow::Result<()> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||
let mut r = &mut a[b.try_into()?..][..4];
|
||||
r.copy_from_slice(&((c & 0xffffff) as u32).to_ne_bytes());
|
||||
pub fn [<$p store32>]<T: TryInto<usize>,M: Memory + ?Sized>(a: &mut M, b: T, c: $int) -> anyhow::Result<()> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||
// let mut r = &mut a[b.try_into()?..][..4];
|
||||
a.write(b.try_into()?,&((c & 0xffffffff) as u32).to_ne_bytes())?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -200,4 +280,4 @@ pub fn select<T>(u: u32, t: T, t2: T) -> anyhow::Result<tuple_list::tuple_list_t
|
|||
}
|
||||
pub fn i32wrapi64(a: u64) -> anyhow::Result<tuple_list::tuple_list_type!(u32)> {
|
||||
return Ok(tuple_list::tuple_list!((a & 0xffffffff) as u32));
|
||||
}
|
||||
}
|
||||
|
|
0
wars-rt/src/wasix.rs
Normal file
0
wars-rt/src/wasix.rs
Normal file
135
wars-rt/src/wrl.rs
Normal file
135
wars-rt/src/wrl.rs
Normal file
|
@ -0,0 +1,135 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use wasm_runtime_layer::{AsContextMut, ExternRef, FuncType};
|
||||
|
||||
use crate::func::CtxSpec;
|
||||
#[derive(Clone)]
|
||||
pub enum MetaType {
|
||||
I32,
|
||||
I64,
|
||||
F32,
|
||||
F64,
|
||||
ExternRef,
|
||||
FunRef {
|
||||
params: Vec<MetaType>,
|
||||
returns: Vec<MetaType>,
|
||||
},
|
||||
}
|
||||
impl MetaType {
|
||||
fn wrl(&self) -> wasm_runtime_layer::ValueType {
|
||||
match self {
|
||||
MetaType::I32 => wasm_runtime_layer::ValueType::I32,
|
||||
MetaType::I64 => wasm_runtime_layer::ValueType::I64,
|
||||
MetaType::F32 => wasm_runtime_layer::ValueType::F32,
|
||||
MetaType::F64 => wasm_runtime_layer::ValueType::F64,
|
||||
MetaType::ExternRef => wasm_runtime_layer::ValueType::ExternRef,
|
||||
MetaType::FunRef { params, returns } => wasm_runtime_layer::ValueType::FuncRef,
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn translate_in<C: CtxSpec + AsContextMut<UserState = D> + 'static, D: AsMut<C>>(
|
||||
val: &crate::func::Value<C>,
|
||||
ctx: &mut C,
|
||||
wrl_ty: &MetaType,
|
||||
) -> anyhow::Result<wasm_runtime_layer::Value>
|
||||
where
|
||||
C::ExternRef: Send + Sync + 'static,
|
||||
{
|
||||
Ok(match val {
|
||||
crate::Value::I32(a) => wasm_runtime_layer::Value::I32(*a as i32),
|
||||
crate::Value::I64(a) => wasm_runtime_layer::Value::I64(*a as i64),
|
||||
crate::Value::F32(a) => wasm_runtime_layer::Value::F32(*a),
|
||||
crate::Value::F64(a) => wasm_runtime_layer::Value::F64(*a),
|
||||
crate::Value::FunRef(f) => {
|
||||
// let wasm_runtime_layer::ValueType::FuncRef()
|
||||
let MetaType::FunRef { params, returns } = wrl_ty.clone() else {
|
||||
unreachable!()
|
||||
};
|
||||
let ty = FuncType::new(
|
||||
params.iter().map(|a| a.wrl()),
|
||||
returns.iter().map(|a| a.wrl()),
|
||||
);
|
||||
let f = f.clone();
|
||||
wasm_runtime_layer::Value::FuncRef(Some(wasm_runtime_layer::Func::new(
|
||||
ctx,
|
||||
ty,
|
||||
move |mut ctx, args, rets| {
|
||||
let args2 = args
|
||||
.iter()
|
||||
.zip(params.iter())
|
||||
.rev()
|
||||
.map(|(x, y)| translate_out(x, ctx.data_mut().as_mut(), y))
|
||||
.collect::<anyhow::Result<Vec<_>>>()?;
|
||||
let v = tramp::tramp(f(ctx.data_mut().as_mut(), args2))?;
|
||||
for ((w, v), t) in v.iter().rev().zip(rets.iter_mut()).zip(returns.iter()) {
|
||||
*v = translate_in(w, ctx.data_mut().as_mut(), t)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
},
|
||||
)))
|
||||
}
|
||||
crate::Value::Null => match wrl_ty{
|
||||
MetaType::ExternRef => wasm_runtime_layer::Value::ExternRef(None),
|
||||
MetaType::FunRef { params, returns } => wasm_runtime_layer::Value::FuncRef(None),
|
||||
_ => anyhow::bail!("invalid null")
|
||||
},
|
||||
crate::Value::ExRef(e) => {
|
||||
wasm_runtime_layer::Value::ExternRef(Some(ExternRef::new(ctx, e.clone())))
|
||||
}
|
||||
})
|
||||
}
|
||||
pub fn translate_out<C: CtxSpec + AsContextMut<UserState = D> + 'static, D: AsMut<C>>(
|
||||
val: &wasm_runtime_layer::Value,
|
||||
ctx: &mut C,
|
||||
wrl_ty: &MetaType,
|
||||
) -> anyhow::Result<crate::func::Value<C>>
|
||||
where
|
||||
C::ExternRef: Send + Sync + 'static,
|
||||
{
|
||||
Ok(match val {
|
||||
wasm_runtime_layer::Value::I32(i) => crate::Value::I32(*i as u32),
|
||||
wasm_runtime_layer::Value::I64(i) => crate::Value::I64(*i as u64),
|
||||
wasm_runtime_layer::Value::F32(f) => crate::Value::F32(*f),
|
||||
wasm_runtime_layer::Value::F64(f) => crate::Value::F64(*f),
|
||||
wasm_runtime_layer::Value::FuncRef(f) => match f {
|
||||
None => crate::Value::Null,
|
||||
Some(a) => {
|
||||
let a = a.clone();
|
||||
let MetaType::FunRef { params, returns } = wrl_ty.clone() else {
|
||||
unreachable!()
|
||||
};
|
||||
crate::Value::FunRef(Arc::new(move |ctx, args| {
|
||||
let args_in: anyhow::Result<Vec<_>> = args
|
||||
.iter()
|
||||
.rev()
|
||||
.zip(params.iter())
|
||||
.map(|(x, y)| translate_in(x, &mut *ctx, y))
|
||||
.collect();
|
||||
let mut results =
|
||||
vec![wasm_runtime_layer::Value::I32(0); a.ty(&mut *ctx).results().len()];
|
||||
let args_in = match args_in {
|
||||
Ok(a) => a,
|
||||
Err(e) => return tramp::BorrowRec::Ret(Err(e)),
|
||||
};
|
||||
tramp::BorrowRec::Ret(match a.call(&mut *ctx, &args_in, &mut results) {
|
||||
Err(e) => Err(e),
|
||||
Ok(_) => results
|
||||
.iter()
|
||||
.zip(returns.iter())
|
||||
.rev()
|
||||
.map(|(x, y)| translate_out(x, ctx, y))
|
||||
.collect(),
|
||||
})
|
||||
}))
|
||||
}
|
||||
},
|
||||
wasm_runtime_layer::Value::ExternRef(x) => match x
|
||||
.as_ref()
|
||||
.and_then(|a| a.downcast::<C::ExternRef, _, _>(ctx.as_context()).ok())
|
||||
{
|
||||
None => crate::Value::Null,
|
||||
Some(x) => crate::Value::ExRef(x.clone()),
|
||||
},
|
||||
})
|
||||
}
|
|
@ -6,9 +6,13 @@ edition = "2021"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
bitflags = "2.5.0"
|
||||
portal-pc-waffle.workspace = true
|
||||
proc-macro2 = "1.0.85"
|
||||
quasiquote = "0.1.1"
|
||||
quote = "1.0.36"
|
||||
relooper = "0.1.0"
|
||||
syn = "2.0.66"
|
||||
waffle-func-reloop = { version = "0.1.0", path = "../waffle-func-reloop" }
|
||||
witx = {git="https://github.com/wasix-org/wasix-witx.git",branch="main"}
|
||||
|
||||
|
|
701
wars/src/lib.rs
701
wars/src/lib.rs
|
@ -1,14 +1,25 @@
|
|||
use std::{convert::Infallible, iter::once, sync::Arc};
|
||||
use std::{collections::BTreeMap, convert::Infallible, iter::once, sync::Arc};
|
||||
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::{format_ident, quote};
|
||||
use quasiquote::quasiquote;
|
||||
use quote::{format_ident, quote, ToTokens};
|
||||
use relooper::{reloop, BranchMode, ShapedBlock};
|
||||
use syn::{Ident, Lifetime};
|
||||
use waffle::{
|
||||
cfg::CFGInfo, entity::EntityRef, Block, BlockTarget, ExportKind, Func, ImportKind, Memory,
|
||||
Module, Operator, Signature, SignatureData, Type, Value,
|
||||
cfg::CFGInfo, entity::EntityRef, Block, BlockTarget, Export, ExportKind, Func, ImportKind, Memory, Module, Operator, Signature, SignatureData, Type, Value
|
||||
};
|
||||
bitflags::bitflags! {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||
pub struct Flags: u32{
|
||||
const HOST_MEMORY = 0x1;
|
||||
const ASYNC = 0x2;
|
||||
const LEGACY = 0x4;
|
||||
// const WASIX = 0x8;
|
||||
// const UNSANDBOXED = 0x2;
|
||||
}
|
||||
}
|
||||
pub mod unswitch;
|
||||
// pub mod wasix;
|
||||
pub fn mangle_value(a: Value, b: usize) -> Ident {
|
||||
if b == 0 {
|
||||
format_ident!("{a}")
|
||||
|
@ -32,20 +43,123 @@ pub fn bindname(a: &str) -> String {
|
|||
// }
|
||||
pub const INTRINSIC: &'static str = "wars_intrinsic/";
|
||||
impl Opts<Module<'static>> {
|
||||
pub fn fp(&self) -> TokenStream {
|
||||
let root = self.crate_path.clone();
|
||||
if self.flags.contains(Flags::ASYNC) {
|
||||
quote! {
|
||||
#root::func::unsync
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
#root::func
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn mem(&self, m: Memory) -> TokenStream {
|
||||
if let Some(i) = self
|
||||
.module
|
||||
.imports
|
||||
.iter()
|
||||
.find(|x| x.kind == ImportKind::Memory(m))
|
||||
{
|
||||
if i.module == "!!unsafe" && i.name == "host" && self.flags.contains(Flags::HOST_MEMORY)
|
||||
{
|
||||
return quote! {
|
||||
unsafe{
|
||||
::std::slice::from_raw_parts_mut(::std::ptr::null(),usize::MAX)
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
let m2 = format_ident!("{m}");
|
||||
quote! {
|
||||
ctx.#m2()
|
||||
}
|
||||
}
|
||||
pub fn import(
|
||||
&self,
|
||||
module: &str,
|
||||
name: &str,
|
||||
params: impl Iterator<Item = TokenStream>,
|
||||
mut params: impl Iterator<Item = TokenStream>,
|
||||
) -> TokenStream {
|
||||
let root = self.crate_path.clone();
|
||||
let Some(a) = module.strip_prefix(INTRINSIC) else {
|
||||
let id = format_ident!("{}_{}", bindname(module), bindname(name));
|
||||
return quote! {
|
||||
ctx.#id(#(#params),*)
|
||||
};
|
||||
// if self.flags.contains(Flags::UNSANDBOXED) {
|
||||
if self.flags.contains(Flags::HOST_MEMORY) {
|
||||
if module == "wars/memory/host" {
|
||||
match name {
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
// if a == "fs" {
|
||||
// match name {
|
||||
// "open" => {
|
||||
// let p0 = params.next().unwrap();
|
||||
// let l = params.next().unwrap();
|
||||
// return quote! {
|
||||
// #root::_rexport::tramp::BorrowRec::Ret({
|
||||
// let f = #p0;
|
||||
// let l = #l;
|
||||
// let f = ::std::str::from_utf8(&ctx.memory()[(f as usize)..][..(l as usize)]);
|
||||
// let f = match f{
|
||||
// Ok(a) => a,
|
||||
// Err(e) => return #root::_rexport::tramp::BorrowRec::Ret(Er(e.into()));
|
||||
// };
|
||||
// let f = ::std::fs::open(f);
|
||||
// let f = match f{
|
||||
// Ok(a) => alloc(&mut ctx.data().files,::std::sync::Arc::new(a)) * 2,
|
||||
// Err(e) => alloc(&mut ctx.data().io_errors,::std::sync::Arc::new(e)) * 2 + 1;
|
||||
// };
|
||||
// f
|
||||
// })
|
||||
// };
|
||||
// }
|
||||
// "read" => {
|
||||
// let fd = params.next().unwrap();
|
||||
// let p0 = params.next().unwrap();
|
||||
// let l = params.next().unwrap();
|
||||
// return quote! {
|
||||
// {
|
||||
// let f = #p0;
|
||||
// let l = #l;
|
||||
// let fd = #fd;
|
||||
// let fd = ctx.data().files.get(&fd).unwrap().clone();
|
||||
// let f = &mut ctx.memory()[(f as usize)..][..(l as usize)];
|
||||
// let f = ::std::io::Read::read(&mut fd.as_ref(),f);
|
||||
// match f{
|
||||
// Ok(a) => #root::_rexport::tuple_list::tuple_list!(a as u64 * 2),
|
||||
// Err(e) => #root::_rexport::tuple_list::tuple_list!(alloc(&mut ctx.data().io_errors,::std::sync::Arc::new(e)) as u64 * 2 + 1);
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
// "write" => {
|
||||
// let fd = params.next().unwrap();
|
||||
// let p0 = params.next().unwrap();
|
||||
// let l = params.next().unwrap();
|
||||
// return quote! {
|
||||
// {
|
||||
// let f = #p0;
|
||||
// let l = #l;
|
||||
// let fd = #fd;
|
||||
// let fd = ctx.data().files.get(&fd).unwrap().clone();
|
||||
// let f = &ctx.memory()[(f as usize)..][..(l as usize)];
|
||||
// let f = ::std::io::Write::write(&mut fd.as_ref(),f);
|
||||
// match f{
|
||||
// Ok(a) => #root::_rexport::tuple_list::tuple_list!(a as u64 * 2),
|
||||
// Err(e) => #root::_rexport::tuple_list::tuple_list!(alloc(&mut ctx.data().io_errors,::std::sync::Arc::new(e)) as u64 * 2 + 1);
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
// _ => {}
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
let id = format_ident!("{}_{}", bindname(module), bindname(name));
|
||||
return quote! {
|
||||
ctx.#id(#(#params),*)
|
||||
};
|
||||
quote! {}
|
||||
}
|
||||
pub fn render_ty(&self, ctx: &TokenStream, ty: Type) -> TokenStream {
|
||||
let root = self.crate_path.clone();
|
||||
|
@ -62,8 +176,14 @@ impl Opts<Module<'static>> {
|
|||
let data = &self.module.signatures[sig_index];
|
||||
let params = data.params.iter().map(|x| self.render_ty(ctx, *x));
|
||||
let returns = data.returns.iter().map(|x| self.render_ty(ctx, *x));
|
||||
let mut x = quote! {
|
||||
#root::func::Df<#root::_rexport::tuple_list::tuple_list_type!(#(#params),*),#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*),#ctx>
|
||||
let mut x = if self.flags.contains(Flags::ASYNC) {
|
||||
quote! {
|
||||
#root::func::unsync::Df<#root::_rexport::tuple_list::tuple_list_type!(#(#params),*),#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*),#ctx>
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
#root::func::Df<#root::_rexport::tuple_list::tuple_list_type!(#(#params),*),#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*),#ctx>
|
||||
}
|
||||
};
|
||||
if nullable {
|
||||
x = quote! {
|
||||
|
@ -72,7 +192,7 @@ impl Opts<Module<'static>> {
|
|||
}
|
||||
x
|
||||
}
|
||||
_ => quote! {#root::func::Value<#ctx>},
|
||||
_ => quasiquote! {#{self.fp()}::Value<#ctx>},
|
||||
}
|
||||
}
|
||||
pub fn render_generics(&self, ctx: &TokenStream, data: &SignatureData) -> TokenStream {
|
||||
|
@ -100,23 +220,28 @@ impl Opts<Module<'static>> {
|
|||
.enumerate()
|
||||
.map(|(a, _)| format_ident!("p{a}"));
|
||||
let returns = data.returns.iter().map(|x| self.render_ty(&ctx, *x));
|
||||
|
||||
quote! {
|
||||
fn #name<'a,C: #base + 'static>(ctx: &'a mut C, #root::_rexport::tuple_list::tuple_list!(#(#param_ids),*): #root::_rexport::tuple_list::tuple_list_type!(#(#params),*)) -> #root::_rexport::tramp::BorrowRec<'a,#root::_rexport::anyhow::Result<#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*)>>
|
||||
if self.flags.contains(Flags::ASYNC) {
|
||||
quote! {
|
||||
fn #name<'a,C: #base + 'static>(ctx: &'a mut C, #root::_rexport::tuple_list::tuple_list!(#(#param_ids),*): #root::_rexport::tuple_list::tuple_list_type!(#(#params),*)) -> #root::func::unsync::AsyncRec<'a,#root::_rexport::anyhow::Result<#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*)>>
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
fn #name<'a,C: #base + 'static>(ctx: &'a mut C, #root::_rexport::tuple_list::tuple_list!(#(#param_ids),*): #root::_rexport::tuple_list::tuple_list_type!(#(#params),*)) -> #root::_rexport::tramp::BorrowRec<'a,#root::_rexport::anyhow::Result<#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*)>>
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn render_fun_ref(&self, ctx: &TokenStream, x: Func) -> TokenStream {
|
||||
let root = self.crate_path.clone();
|
||||
if x.is_invalid() {
|
||||
return quote! {
|
||||
#root::func::da::<(),(),C,_>(|ctx,arg|panic!("invalid func"))
|
||||
return quasiquote! {
|
||||
#{self.fp()}::da::<(),(),C,_>(|ctx,arg|panic!("invalid func"))
|
||||
};
|
||||
}
|
||||
let generics =
|
||||
self.render_generics(ctx, &self.module.signatures[self.module.funcs[x].sig()]);
|
||||
let x = format_ident!("{x}");
|
||||
quote! {
|
||||
#root::func::da::<#generics,C,_>(|ctx,arg|#x(ctx,arg))
|
||||
quasiquote! {
|
||||
#{self.fp()}::da::<#generics,C,_>(|ctx,arg|#x(ctx,arg))
|
||||
}
|
||||
}
|
||||
pub fn render_self_sig(
|
||||
|
@ -138,10 +263,17 @@ impl Opts<Module<'static>> {
|
|||
.collect::<Vec<_>>();
|
||||
|
||||
let returns = data.returns.iter().map(|x| self.render_ty(&ctx, *x));
|
||||
|
||||
quote! {
|
||||
fn #name<'a>(self: &'a mut Self, #root::_rexport::tuple_list::tuple_list!(#(#param_ids),*): #root::_rexport::tuple_list::tuple_list_type!(#(#params),*)) -> #root::_rexport::tramp::BorrowRec<'a,#root::_rexport::anyhow::Result<#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*)>> where Self: 'static{
|
||||
return #wrapped(self,#root::_rexport::tuple_list::tuple_list!(#(#param_ids),*));
|
||||
if self.flags.contains(Flags::ASYNC) {
|
||||
quote! {
|
||||
fn #name<'a>(self: &'a mut Self, #root::_rexport::tuple_list::tuple_list!(#(#param_ids),*): #root::_rexport::tuple_list::tuple_list_type!(#(#params),*)) -> #root::func::unsync::AsyncRec<'a,#root::_rexport::anyhow::Result<#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*)>> where Self: 'static{
|
||||
return #wrapped(self,#root::_rexport::tuple_list::tuple_list!(#(#param_ids),*));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
fn #name<'a>(self: &'a mut Self, #root::_rexport::tuple_list::tuple_list!(#(#param_ids),*): #root::_rexport::tuple_list::tuple_list_type!(#(#params),*)) -> #root::_rexport::tramp::BorrowRec<'a,#root::_rexport::anyhow::Result<#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*)>> where Self: 'static{
|
||||
return #wrapped(self,#root::_rexport::tuple_list::tuple_list!(#(#param_ids),*));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -159,9 +291,14 @@ impl Opts<Module<'static>> {
|
|||
.collect::<Vec<_>>();
|
||||
|
||||
let returns = data.returns.iter().map(|x| self.render_ty(&ctx, *x));
|
||||
|
||||
quote! {
|
||||
fn #name<'a>(self: &'a mut Self, #root::_rexport::tuple_list::tuple_list!(#(#param_ids),*): #root::_rexport::tuple_list::tuple_list_type!(#(#params),*)) -> #root::_rexport::tramp::BorrowRec<'a,#root::_rexport::anyhow::Result<#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*)>>;
|
||||
if self.flags.contains(Flags::ASYNC) {
|
||||
quote! {
|
||||
fn #name<'a>(self: &'a mut Self, #root::_rexport::tuple_list::tuple_list!(#(#param_ids),*): #root::_rexport::tuple_list::tuple_list_type!(#(#params),*)) -> #root::func::unsync::AsyncRec<'a,#root::_rexport::anyhow::Result<#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*)>>;
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
fn #name<'a>(self: &'a mut Self, #root::_rexport::tuple_list::tuple_list!(#(#param_ids),*): #root::_rexport::tuple_list::tuple_list_type!(#(#params),*)) -> #root::_rexport::tramp::BorrowRec<'a,#root::_rexport::anyhow::Result<#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*)>>;
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn render_relooped_block(&self, f: Func, x: &ShapedBlock<Block>) -> TokenStream {
|
||||
|
@ -228,6 +365,7 @@ impl Opts<Module<'static>> {
|
|||
#next;
|
||||
};
|
||||
}
|
||||
let fp = self.fp();
|
||||
let stmts = b.blocks[stmts].params.iter().map(|a|&a.1).chain(b.blocks[stmts].insts.iter()).map(|a|{
|
||||
let av = b.values[*a].tys(&b.type_pool).iter().enumerate().map(|b|mangle_value(*a,b.0));
|
||||
let b = match &b.values[*a]{
|
||||
|
@ -251,10 +389,21 @@ impl Opts<Module<'static>> {
|
|||
Some(_) => {
|
||||
let func = format_ident!("{function_index}");
|
||||
let vals = vals.iter().map(|a|format_ident!("{a}"));
|
||||
quote! {
|
||||
match #root::_rexport::tramp::tramp(#func(ctx,#root::_rexport::tuple_list::tuple_list!(#(#root::func::cast::<_,_,C>(#vals .clone())),*))){
|
||||
Ok(a) => a,
|
||||
Err(e) => return #root::_rexport::tramp::BorrowRec::Ret(Err(e))
|
||||
quasiquote! {
|
||||
{
|
||||
let x = #func(ctx,#root::_rexport::tuple_list::tuple_list!(#(#fp::cast::<_,_,C>(#vals .clone())),*));
|
||||
match #{if self.flags.contains(Flags::ASYNC){
|
||||
quote!{
|
||||
x.go().await
|
||||
}
|
||||
}else{
|
||||
quote!{
|
||||
#root::_rexport::tramp::tramp(x)
|
||||
}
|
||||
}}{
|
||||
Ok(a) => a,
|
||||
Err(e) => return #{self.fp()}::ret(Err(e))
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -270,10 +419,18 @@ impl Opts<Module<'static>> {
|
|||
i.name.as_str(),
|
||||
vals.iter().map(|a|format_ident!("{a}")).map(|a| quote! {#a}),
|
||||
);
|
||||
quote!{
|
||||
match #root::_rexport::tramp::tramp(x){
|
||||
quasiquote!{
|
||||
match #{if self.flags.contains(Flags::ASYNC){
|
||||
quote!{
|
||||
#x.go().await
|
||||
}
|
||||
}else{
|
||||
quote!{
|
||||
#root::_rexport::tramp::tramp(#x)
|
||||
}
|
||||
}}{
|
||||
Ok(a) => a,
|
||||
Err(e) => return #root::_rexport::tramp::BorrowRec::Ret(Err(e))
|
||||
Err(e) => return #{self.fp()}::ret(Err(e))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -286,12 +443,23 @@ impl Opts<Module<'static>> {
|
|||
let vals = vals.iter().map(|a|format_ident!("{a}"));
|
||||
let r = format_ident!("{r}");
|
||||
let g = self.render_generics("e! {c}, &self.module.signatures[*sig_index]);
|
||||
quote! {
|
||||
match #root::_rexport::tramp::tramp(#root::func::call_ref::<#g,C>(ctx,#root::func::cast(#r.clone()),#root::_rexport::tuple_list::tuple_list!(#(#root::func::cast::<_,_,C>(#vals .clone())),*))){
|
||||
quasiquote! {
|
||||
{
|
||||
let x = #{self.fp()}::call_ref::<#g,C>(ctx,#{self.fp()}(#r.clone()),#root::_rexport::tuple_list::tuple_list!(#(#fp::cast::<_,_,C>(#vals .clone())),*));
|
||||
match #{if self.flags.contains(Flags::ASYNC){
|
||||
quote!{
|
||||
x.go().await
|
||||
}
|
||||
}else{
|
||||
quote!{
|
||||
#root::_rexport::tramp::tramp(x)
|
||||
}
|
||||
}}{
|
||||
Ok(a) => a,
|
||||
Err(e) => return #root::_rexport::tramp::BorrowRec::Ret(Err(e))
|
||||
Err(e) => return #{self.fp()}::ret(Err(e))
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Operator::CallIndirect { sig_index, table_index } => {
|
||||
let t = format_ident!("{table_index}");
|
||||
|
@ -304,12 +472,21 @@ impl Opts<Module<'static>> {
|
|||
ctx.#t()[#r as usize]
|
||||
};
|
||||
let g = self.render_generics("e! {c}, &self.module.signatures[*sig_index]);
|
||||
quote! {
|
||||
quasiquote! {
|
||||
{
|
||||
let r = #r.clone();
|
||||
match #root::_rexport::tramp::tramp(#root::func::call_ref::<#g,C>(ctx,#root::func::cast(r),#root::_rexport::tuple_list::tuple_list!(#(#root::func::cast::<_,_,C>(#vals .clone())),*))){
|
||||
let x = #{self.fp()}::call_ref::<#g,C>(ctx,#{self.fp()}::cast(r),#root::_rexport::tuple_list::tuple_list!(#(#fp::cast::<_,_,C>(#vals .clone())),*));
|
||||
match #{if self.flags.contains(Flags::ASYNC){
|
||||
quote!{
|
||||
x.go().await
|
||||
}
|
||||
}else{
|
||||
quote!{
|
||||
#root::_rexport::tramp::tramp(x)
|
||||
}
|
||||
}}{
|
||||
Ok(a) => a,
|
||||
Err(e) => return #root::_rexport::tramp::BorrowRec::Ret(Err(e))
|
||||
Err(e) => return #{self.fp()}::ret(Err(e))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -324,8 +501,11 @@ impl Opts<Module<'static>> {
|
|||
quote! {u32}
|
||||
};
|
||||
let m = Ident::new(&mem.to_string(), Span::call_site());
|
||||
quote! {
|
||||
#root::_rexport::tuple_list::tuple_list!((ctx.#m().len() / 65536) as #rt)
|
||||
quasiquote! {
|
||||
#root::_rexport::tuple_list::tuple_list!(((match #root::Memory::size(ctx.#m()){
|
||||
Ok(a) => a,
|
||||
Err(e) => return #{self.fp()}::ret(Err(e))
|
||||
}) / 65536) as #rt)
|
||||
}
|
||||
}
|
||||
waffle::Operator::MemoryGrow { mem } => {
|
||||
|
@ -337,25 +517,30 @@ impl Opts<Module<'static>> {
|
|||
}else{
|
||||
quote! {u32}
|
||||
};
|
||||
quote! {
|
||||
quasiquote! {
|
||||
{
|
||||
let vn = ctx.#m().len() / 65536;
|
||||
let l = ctx.#m().len();
|
||||
ctx.#m().resize(l + (#a .clone() as usize) * 65536,0);
|
||||
let vn = (match #root::Memory::size(ctx.#m()){
|
||||
Ok(a) => a,
|
||||
Err(e) => return #{self.fp()}::ret(Err(e))
|
||||
}) / 65536;
|
||||
match #root::Memory::grow(ctx.#m(),(#a .clone() as usize) * 65536){
|
||||
Ok(a) => a,
|
||||
Err(e) => return #{self.fp()}::ret(Err(e))
|
||||
};
|
||||
#root::_rexport::tuple_list::tuple_list!(vn as #rt)
|
||||
}
|
||||
}
|
||||
},
|
||||
waffle::Operator::MemoryCopy { dst_mem, src_mem } => {
|
||||
let dst = format_ident!("{dst_mem}");
|
||||
let src = format_ident!("{src_mem}");
|
||||
let dst = self.mem(*dst_mem);
|
||||
let src = self.mem(*src_mem);
|
||||
let dst_ptr = format_ident!("{}",vals[0].to_string());
|
||||
let src_ptr = format_ident!("{}",vals[1].to_string());
|
||||
let len = format_ident!("{}",vals[2].to_string());
|
||||
quote!{
|
||||
{
|
||||
let m = ctx.#src()[(#src_ptr as usize)..][..(#len as usize)].to_owned();
|
||||
ctx.#dst()[(#dst_ptr as usize)..][..(#len as usize)].copy_from_slice(&m);
|
||||
let m = #src[(#src_ptr as usize)..][..(#len as usize)].to_owned();
|
||||
#dst[(#dst_ptr as usize)..][..(#len as usize)].copy_from_slice(&m);
|
||||
()
|
||||
}
|
||||
}
|
||||
|
@ -377,6 +562,55 @@ impl Opts<Module<'static>> {
|
|||
}
|
||||
}
|
||||
}
|
||||
Operator::TableGet { table_index } => {
|
||||
let table = format_ident!("{table_index}");
|
||||
let [i,..] = vals else{
|
||||
unreachable!()
|
||||
};
|
||||
let i = format_ident!("{i}");
|
||||
// let j = format_ident!("{j}");
|
||||
quasiquote!{
|
||||
{
|
||||
(ctx.#table()[#i as usize].clone(),())
|
||||
}
|
||||
}
|
||||
},
|
||||
Operator::TableSet { table_index } => {
|
||||
let table = format_ident!("{table_index}");
|
||||
let [i,j,..] = vals else{
|
||||
unreachable!()
|
||||
};
|
||||
let i = format_ident!("{i}");
|
||||
let j = format_ident!("{j}");
|
||||
quasiquote!{
|
||||
{
|
||||
ctx.#table()[#i as usize] = #{self.fp()}::cast::<_,_,C>(#j.clone());
|
||||
()
|
||||
}
|
||||
}
|
||||
},
|
||||
Operator::TableSize { table_index } => {
|
||||
let table = format_ident!("{table_index}");
|
||||
quote!{
|
||||
(ctx.#table().len() as u32,())
|
||||
}
|
||||
},
|
||||
Operator::TableGrow { table_index } => {
|
||||
let table = format_ident!("{table_index}");
|
||||
let [i,j,..] = vals else{
|
||||
unreachable!()
|
||||
};
|
||||
let i = format_ident!("{i}");
|
||||
let j = format_ident!("{j}");
|
||||
quasiquote!{
|
||||
{
|
||||
for _ in 0..#i{
|
||||
ctx.#table().push(#{self.fp()}::cast::<_,_,C>(#j.clone()));
|
||||
}
|
||||
()
|
||||
}
|
||||
}
|
||||
},
|
||||
_ if waffle::op_traits::mem_count(o) == 1 => {
|
||||
let mut mem = Memory::invalid();
|
||||
waffle::op_traits::rewrite_mem(&mut o.clone(), &mut [();4], |m,_|{
|
||||
|
@ -386,7 +620,7 @@ impl Opts<Module<'static>> {
|
|||
// let clean = o.to_string();
|
||||
let clean = format_ident!("{}",o.to_string().split_once("<").unwrap().0);
|
||||
let m2 = mem;
|
||||
let mem = format_ident!("{mem}");
|
||||
let mem = self.mem(m2);
|
||||
let mut vals = vals.iter().map(|a|format_ident!("{a}"));
|
||||
let rt = if self.module.memories[m2].memory64{
|
||||
quote! {u64}
|
||||
|
@ -402,10 +636,10 @@ impl Opts<Module<'static>> {
|
|||
};
|
||||
let val = vals.next().unwrap();
|
||||
let vals = once(quote! {(#val.clone() + #offset)}).chain(vals.map(|w|quote!{#w}));
|
||||
quote! {
|
||||
match #root::#clean::<#rt>(ctx.#mem(),#(#root::func::cast::<_,_,C>(#vals .clone())),*){
|
||||
quasiquote! {
|
||||
match #root::#clean::<#rt,_>(#mem,#(#fp::cast::<_,_,C>(#vals .clone())),*){
|
||||
Ok(a) => a,
|
||||
Err(e) => return #root::_rexport::tramp::BorrowRec::Ret(Err(e))
|
||||
Err(e) => return #{self.fp()}::ret(Err(e))
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -426,10 +660,10 @@ impl Opts<Module<'static>> {
|
|||
// let clean = o.to_string();
|
||||
let clean = format_ident!("{o}");
|
||||
let vals = vals.iter().map(|a|format_ident!("{a}"));
|
||||
quote! {
|
||||
match #root::#clean(#(#root::func::cast::<_,_,C>(#vals .clone())),*){
|
||||
quasiquote! {
|
||||
match #root::#clean(#(#fp::cast::<_,_,C>(#vals .clone())),*){
|
||||
Ok(a) => a,
|
||||
Err(e) => return #root::_rexport::tramp::BorrowRec::Ret(Err(e))
|
||||
Err(e) => return #{self.fp()}::ret(Err(e))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -459,8 +693,8 @@ impl Opts<Module<'static>> {
|
|||
let vars = k.args.iter().enumerate().map(|(i, a)| {
|
||||
let a = format_ident!("{a}");
|
||||
let i = format_ident!("{}param{i}", k.block.to_string());
|
||||
quote! {
|
||||
#i = #a;
|
||||
quasiquote! {
|
||||
#i = #{self.fp()}::cast::<_,_,C>(#a);
|
||||
}
|
||||
});
|
||||
let br = term(
|
||||
|
@ -523,8 +757,8 @@ impl Opts<Module<'static>> {
|
|||
let values = b.rets.iter().enumerate().map(|(a, _)| match values.get(a) {
|
||||
Some(v) => {
|
||||
let v = format_ident!("{v}");
|
||||
quote! {
|
||||
#v
|
||||
quasiquote! {
|
||||
#{self.fp()}::cast::<_,_,C>(#v)
|
||||
}
|
||||
}
|
||||
None => {
|
||||
|
@ -533,19 +767,29 @@ impl Opts<Module<'static>> {
|
|||
}
|
||||
}
|
||||
});
|
||||
quote! {
|
||||
return #root::_rexport::tramp::BorrowRec::Ret(Ok(#root::_rexport::tuple_list::tuple_list!(#(#values),*)))
|
||||
quasiquote! {
|
||||
return #{self.fp()}::ret(Ok(#root::_rexport::tuple_list::tuple_list!(#(#values),*)))
|
||||
}
|
||||
}
|
||||
waffle::Terminator::ReturnCall { func, args } => {
|
||||
match self.module.funcs[*func].body() {
|
||||
Some(_) => {
|
||||
let values = args.iter().map(|v| format_ident!("{v}"));
|
||||
let values = args.iter().map(|v| format_ident!("{v}")).map(|a| {
|
||||
quasiquote! {
|
||||
#{self.fp()}::cast::<_,_,C>(#a)
|
||||
}
|
||||
});
|
||||
let func = format_ident!("{func}");
|
||||
quote! {
|
||||
return #root::_rexport::tramp::BorrowRec::Call(#root::_rexport::tramp::Thunk::new(move||{
|
||||
if self.flags.contains(Flags::ASYNC) {
|
||||
quote! {
|
||||
#func(ctx,#root::_rexport::tuple_list::tuple_list!(#(#values),*))
|
||||
}))
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
return #root::_rexport::tramp::BorrowRec::Call(#root::_rexport::tramp::Thunk::new(move||{
|
||||
#func(ctx,#root::_rexport::tuple_list::tuple_list!(#(#values),*))
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
|
@ -562,8 +806,12 @@ impl Opts<Module<'static>> {
|
|||
.map(|a| format_ident!("{a}"))
|
||||
.map(|a| quote! {#a}),
|
||||
);
|
||||
quote! {
|
||||
return #root::_rexport::tramp::BorrowRec::Call(#root::_rexport::tramp::Thunk::new(move||{#x}))
|
||||
if self.flags.contains(Flags::ASYNC) {
|
||||
x
|
||||
} else {
|
||||
quote! {
|
||||
return #root::_rexport::tramp::BorrowRec::Call(#root::_rexport::tramp::Thunk::new(move||{#x}))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -573,30 +821,50 @@ impl Opts<Module<'static>> {
|
|||
let mut vals = args.to_owned();
|
||||
let r = vals.pop().unwrap();
|
||||
// let func = format_ident!("{function_index}");
|
||||
let vals = vals.iter().map(|a| format_ident!("{a}"));
|
||||
let vals = vals.iter().map(|a| format_ident!("{a}")).map(|a| {
|
||||
quasiquote! {
|
||||
#{self.fp()}::cast::<_,_,C>(#a)
|
||||
}
|
||||
});
|
||||
let r = format_ident!("{r}");
|
||||
let r = quote! {
|
||||
ctx.#t()[#r as usize]
|
||||
};
|
||||
let g = self.render_generics("e! {c}, &self.module.signatures[*sig]);
|
||||
quote! {
|
||||
let r = #r.clone();
|
||||
return #root::_rexport::tramp::BorrowRec::Call(#root::_rexport::tramp::Thunk::new(move||{
|
||||
#root::func::call_ref::<#g,C>(ctx,#root::func::cast(r),#root::_rexport::tuple_list::tuple_list!(#(#root::func::cast::<_,_,C>(#vals .clone())),*))
|
||||
}))
|
||||
if self.flags.contains(Flags::ASYNC) {
|
||||
quasiquote! {
|
||||
return #{self.fp()}::call_ref::<#g,C>(ctx,#{self.fp()}::cast(r),#root::_rexport::tuple_list::tuple_list!(#(#{self.fp()}::cast::<_,_,C>(#vals .clone())),*))
|
||||
}
|
||||
} else {
|
||||
quasiquote! {
|
||||
let r = #r.clone();
|
||||
return #root::_rexport::tramp::BorrowRec::Call(#root::_rexport::tramp::Thunk::new(move||{
|
||||
#{self.fp()}::call_ref::<#g,C>(ctx,#{self.fp()}::cast(r),#root::_rexport::tuple_list::tuple_list!(#(#{self.fp()}::cast::<_,_,C>(#vals .clone())),*))
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
waffle::Terminator::ReturnCallRef { sig, args } => {
|
||||
let mut vals = args.clone();
|
||||
let r = vals.pop().unwrap();
|
||||
// let func = format_ident!("{function_index}");
|
||||
let vals = vals.iter().map(|a| format_ident!("{a}"));
|
||||
let vals = vals.iter().map(|a| format_ident!("{a}")).map(|a| {
|
||||
quasiquote! {
|
||||
#{self.fp()}::cast::<_,_,C>(#a)
|
||||
}
|
||||
});
|
||||
let r = format_ident!("{r}");
|
||||
let g = self.render_generics("e! {c}, &self.module.signatures[*sig]);
|
||||
quote! {
|
||||
return #root::_rexport::tramp::BorrowRec::Call(#root::_rexport::tramp::Thunk::new(move||{
|
||||
#root::func::call_ref::<#g,C>(ctx,#root::func::cast(#r.clone()),#root::_rexport::tuple_list::tuple_list!(#(#root::func::cast::<_,_,C>(#vals .clone())),*))
|
||||
}))
|
||||
if self.flags.contains(Flags::ASYNC) {
|
||||
quasiquote! {
|
||||
return #{self.fp()}::call_ref::<#g,C>(ctx,#root::func::cast(#r.clone()),#root::_rexport::tuple_list::tuple_list!(#(#root::func::cast::<_,_,C>(#vals .clone())),*))
|
||||
}
|
||||
} else {
|
||||
quasiquote! {
|
||||
return #root::_rexport::tramp::BorrowRec::Call(#root::_rexport::tramp::Thunk::new(move||{
|
||||
#{self.fp()}::call_ref::<#g,C>(ctx,#root::func::cast(#r.clone()),#root::_rexport::tuple_list::tuple_list!(#(#root::func::cast::<_,_,C>(#vals .clone())),*))
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
waffle::Terminator::Unreachable => quote! {
|
||||
|
@ -753,45 +1021,56 @@ impl Opts<Module<'static>> {
|
|||
}
|
||||
})
|
||||
});
|
||||
let reloop = std::panic::catch_unwind(|| {
|
||||
reloop(
|
||||
b.blocks
|
||||
.entries()
|
||||
.filter(|k| cfg.dominates(b.entry, k.0))
|
||||
.map(|(k, l)| {
|
||||
(
|
||||
k,
|
||||
l.succs
|
||||
.iter()
|
||||
.cloned()
|
||||
.chain(b.blocks.iter().filter(|x| cfg.dominates(*x, k)))
|
||||
.collect(),
|
||||
)
|
||||
})
|
||||
.chain(once((Block::invalid(), vec![b.entry])))
|
||||
.collect(),
|
||||
Block::invalid(),
|
||||
)
|
||||
});
|
||||
let reloop = match reloop {
|
||||
Ok(a) => a,
|
||||
Err(e) => {
|
||||
panic!(
|
||||
"reloop failure ({}) in {}",
|
||||
e.downcast_ref::<&str>()
|
||||
.map(|a| *a)
|
||||
.unwrap_or("unknown panic"),
|
||||
b.display("", None)
|
||||
);
|
||||
}
|
||||
};
|
||||
let reloop = waffle_func_reloop::go(b);
|
||||
// let reloop = std::panic::catch_unwind(|| {
|
||||
// reloop(
|
||||
// b.blocks
|
||||
// .entries()
|
||||
// .filter(|k| cfg.dominates(b.entry, k.0))
|
||||
// .map(|(k, l)| {
|
||||
// (
|
||||
// k,
|
||||
// l.succs
|
||||
// .iter()
|
||||
// .cloned()
|
||||
// .chain(b.blocks.iter().filter(|x| cfg.dominates(*x, k)))
|
||||
// .collect(),
|
||||
// )
|
||||
// })
|
||||
// .chain(once((Block::invalid(), vec![b.entry])))
|
||||
// .collect(),
|
||||
// Block::invalid(),
|
||||
// )
|
||||
// });
|
||||
// let reloop = match reloop {
|
||||
// Ok(a) => a,
|
||||
// Err(e) => {
|
||||
// panic!(
|
||||
// "reloop failure ({}) in {}",
|
||||
// e.downcast_ref::<&str>()
|
||||
// .map(|a| *a)
|
||||
// .unwrap_or("unknown panic"),
|
||||
// b.display("", None)
|
||||
// );
|
||||
// }
|
||||
// };
|
||||
let x = self.render_relooped_block(f, reloop.as_ref());
|
||||
let mut b = quote! {
|
||||
let mut cff: usize = 0;
|
||||
#(let mut #bpvalues);*;
|
||||
#x;
|
||||
panic!("should have returned");
|
||||
};
|
||||
if self.flags.contains(Flags::ASYNC) {
|
||||
b = quasiquote! {
|
||||
return #{self.fp()}::AsyncRec::Async(Box::pin(async move{
|
||||
#b
|
||||
}))
|
||||
}
|
||||
}
|
||||
quote! {
|
||||
#sig {
|
||||
let mut cff: usize = 0;
|
||||
#(let mut #bpvalues);*;
|
||||
#x;
|
||||
panic!("should have returned");
|
||||
#b
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -800,45 +1079,92 @@ pub struct Opts<B> {
|
|||
pub crate_path: syn::Path,
|
||||
pub module: B,
|
||||
pub name: Ident,
|
||||
pub flags: Flags,
|
||||
pub embed: TokenStream,
|
||||
pub data: BTreeMap<Ident, TokenStream>,
|
||||
// pub cfg: Arc<dyn ImportCfg>,
|
||||
}
|
||||
pub fn go(opts: &Opts<Vec<u8>>) -> proc_macro2::TokenStream {
|
||||
let mut module = waffle::Module::from_wasm_bytes(&opts.module, &Default::default()).unwrap();
|
||||
module.expand_all_funcs().unwrap();
|
||||
let mut module = module.without_orig_bytes();
|
||||
// module.per_func_body(|b|unswitch::go(b)); //TODO: reloop better and make it not needed
|
||||
// eprintln!("{}",module.display());
|
||||
module.per_func_body(|f| f.convert_to_max_ssa(None));
|
||||
impl<X: AsRef<[u8]>> Opts<X> {
|
||||
pub fn to_mod(&self) -> Opts<Module<'static>> {
|
||||
let opts = self;
|
||||
let mut module =
|
||||
waffle::Module::from_wasm_bytes(opts.module.as_ref(), &Default::default()).unwrap();
|
||||
module.expand_all_funcs().unwrap();
|
||||
let mut module = module.without_orig_bytes();
|
||||
// module.per_func_body(|b|unswitch::go(b)); //TODO: reloop better and make it not needed
|
||||
// eprintln!("{}",module.display());
|
||||
module.per_func_body(|f| f.convert_to_max_ssa(None));
|
||||
let internal_path = format_ident!("_{}_internal", opts.name);
|
||||
let data = format_ident!("{}Data", opts.name);
|
||||
let name = opts.name.clone();
|
||||
let opts = Opts {
|
||||
crate_path: opts.crate_path.clone(),
|
||||
module,
|
||||
name: name.clone(),
|
||||
flags: opts.flags,
|
||||
embed: opts.embed.clone(),
|
||||
data: opts.data.clone(),
|
||||
// cfg: opts.cfg.clone(),
|
||||
};
|
||||
return opts;
|
||||
}
|
||||
}
|
||||
impl ToTokens for Opts<Module<'static>> {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
go(self).to_tokens(tokens)
|
||||
}
|
||||
}
|
||||
pub fn go(opts: &Opts<Module<'static>>) -> proc_macro2::TokenStream {
|
||||
// let mut module = waffle::Module::from_wasm_bytes(&opts.module, &Default::default()).unwrap();
|
||||
// module.expand_all_funcs().unwrap();
|
||||
// let mut module = module.without_orig_bytes();
|
||||
// // module.per_func_body(|b|unswitch::go(b)); //TODO: reloop better and make it not needed
|
||||
// // eprintln!("{}",module.display());
|
||||
// module.per_func_body(|f| f.convert_to_max_ssa(None));
|
||||
let internal_path = format_ident!("_{}_internal", opts.name);
|
||||
let data = format_ident!("{}Data", opts.name);
|
||||
let name = opts.name.clone();
|
||||
let opts = Opts {
|
||||
crate_path: opts.crate_path.clone(),
|
||||
module,
|
||||
name: name.clone(),
|
||||
// cfg: opts.cfg.clone(),
|
||||
};
|
||||
// let opts = Opts {
|
||||
// crate_path: opts.crate_path.clone(),
|
||||
// module,
|
||||
// name: name.clone(),
|
||||
// flags: opts.flags,
|
||||
// // cfg: opts.cfg.clone(),
|
||||
// };
|
||||
let root = opts.crate_path.clone();
|
||||
let funcs = opts.module.funcs.iter().map(|a| opts.render_fn(a));
|
||||
let mut z = vec![];
|
||||
let mut fields = vec![];
|
||||
let mut fs = vec![];
|
||||
fs.push(opts.embed.clone());
|
||||
for (k, v) in opts.data.iter() {
|
||||
fields.push(k.clone());
|
||||
z.push(quote! {
|
||||
#k : #v
|
||||
});
|
||||
}
|
||||
let mut init = vec![];
|
||||
for (t, d) in opts.module.tables.entries() {
|
||||
// let dty = opts.render_ty("e! {Target}, d.ty.clone());
|
||||
let n = Ident::new(&t.to_string(), Span::call_site());
|
||||
z.push(quote! {
|
||||
#n: Vec<#root::func::Value<Target>>
|
||||
z.push(quasiquote! {
|
||||
#n: Vec<#{opts.fp()}::Value<Target>>
|
||||
});
|
||||
fields.push(n.clone());
|
||||
if let Some(e) = d.func_elements.as_ref() {
|
||||
let e = e.iter().map(|x| opts.render_fun_ref("e! {C}, *x));
|
||||
init.push(quote! {
|
||||
#(ctx.data().#n.push(#root::func::Coe::coe(#e)));*;
|
||||
init.push(if opts.flags.contains(Flags::ASYNC) {
|
||||
quote! {
|
||||
#(ctx.data().#n.push(#root::func::unsync::Coe::coe(#e)));*;
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
#(ctx.data().#n.push(#root::func::Coe::coe(#e)));*;
|
||||
}
|
||||
})
|
||||
}
|
||||
fs.push(quote! {
|
||||
fn #n(&mut self) -> &mut Vec<#root::func::Value<Self>>{
|
||||
fs.push(quasiquote! {
|
||||
fn #n(&mut self) -> &mut Vec<#{opts.fp()}::Value<Self>>{
|
||||
&mut self.data().#n
|
||||
}
|
||||
})
|
||||
|
@ -893,15 +1219,25 @@ pub fn go(opts: &Opts<Vec<u8>>) -> proc_macro2::TokenStream {
|
|||
});
|
||||
}
|
||||
Some((a, b)) => {
|
||||
// let a = bindname(&a);
|
||||
// let b = bindname(&b);
|
||||
let m = Ident::new(&format!("{a}_{b}"), Span::call_site());
|
||||
fs.push(quote! {
|
||||
fn #m<'a>(&'a mut self) -> &'a mut Vec<u8>;
|
||||
fn #n<'a>(&'a mut self) -> &'a mut Vec<u8>{
|
||||
return self.#m();
|
||||
}
|
||||
});
|
||||
if a == "!!unsafe" && b == "host" && opts.flags.contains(Flags::HOST_MEMORY) {
|
||||
} else {
|
||||
// let a = bindname(&a);
|
||||
// let b = bindname(&b);
|
||||
let m = Ident::new(&format!("{a}_{b}"), Span::call_site());
|
||||
let p = if opts.flags.contains(Flags::LEGACY) {
|
||||
quote! {dyn #root::Memory}
|
||||
} else {
|
||||
quote! {
|
||||
impl #root::Memory
|
||||
}
|
||||
};
|
||||
fs.push(quote! {
|
||||
fn #m<'a>(&'a mut self) -> &'a mut #p;
|
||||
fn #n<'a>(&'a mut self) -> &'a mut #p{
|
||||
return self.#m();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
let pk = d.initial_pages * 65536;
|
||||
|
@ -930,6 +1266,10 @@ pub fn go(opts: &Opts<Vec<u8>>) -> proc_macro2::TokenStream {
|
|||
}
|
||||
}
|
||||
for xp in opts.module.exports.iter() {
|
||||
let xp = Export{
|
||||
name: bindname(&xp.name),
|
||||
kind: xp.kind.clone()
|
||||
};
|
||||
match &xp.kind {
|
||||
ExportKind::Func(f) => {
|
||||
let f = *f;
|
||||
|
@ -969,8 +1309,14 @@ pub fn go(opts: &Opts<Vec<u8>>) -> proc_macro2::TokenStream {
|
|||
ExportKind::Memory(m) => {
|
||||
let x = Ident::new(&m.to_string(), Span::call_site());
|
||||
let mn = Ident::new(&xp.name, Span::call_site());
|
||||
let i = quote! {
|
||||
fn #mn(&mut self) -> &mut Vec<u8>{
|
||||
let i = quasiquote! {
|
||||
fn #mn(&mut self) -> &mut #{if opts.flags.contains(Flags::LEGACY) {
|
||||
quote! {dyn #root::Memory}
|
||||
} else {
|
||||
quote! {
|
||||
impl #root::Memory
|
||||
}
|
||||
}}{
|
||||
return self.#x()
|
||||
}
|
||||
};
|
||||
|
@ -990,13 +1336,56 @@ pub fn go(opts: &Opts<Vec<u8>>) -> proc_macro2::TokenStream {
|
|||
));
|
||||
}
|
||||
}
|
||||
quote! {
|
||||
// if opts.flags.contains(Flags::UNSANDBOXED) {
|
||||
// for (x, y) in [
|
||||
// (
|
||||
// format_ident!("files"),
|
||||
// quote! {
|
||||
// ::std::collections::BTreeMap<u32,::std::sync::Arc<::std::fs::File>>
|
||||
// },
|
||||
// ),
|
||||
// (
|
||||
// format_ident!("io_errors"),
|
||||
// quote! {
|
||||
// ::std::collections::BTreeMap<u32,::std::sync::Arc<::std::io::Error>>
|
||||
// },
|
||||
// ),
|
||||
// ] {
|
||||
// fields.push(x.clone());
|
||||
// z.push(quote! {
|
||||
// #x: #y
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
let defaults = fields.iter().map(|a| {
|
||||
quote! {
|
||||
#a: Default::default()
|
||||
}
|
||||
});
|
||||
let clones = fields.iter().map(|a| {
|
||||
quote! {
|
||||
#a: self.#a.clone()
|
||||
}
|
||||
});
|
||||
quasiquote! {
|
||||
mod #internal_path{
|
||||
#(#funcs)*
|
||||
pub fn alloc<T>(m: &mut ::std::collections::BTreeMap<u32,T>, x: T) -> u32{
|
||||
let mut u = 0;
|
||||
while m.contains_key(&u){
|
||||
u += 1;
|
||||
};
|
||||
m.insert(u,x);
|
||||
return u;
|
||||
}
|
||||
pub struct #data<Target: #name + ?Sized>{
|
||||
#(#z),*
|
||||
}
|
||||
pub trait #name: #root::func::CtxSpec{
|
||||
pub trait #name: #{opts.fp()}::CtxSpec #{if opts.flags.contains(Flags::ASYNC){
|
||||
quote! {+ Send + Sync}
|
||||
}else{
|
||||
quote! {}
|
||||
}}{
|
||||
fn data(&mut self) -> &mut #data<Self>;
|
||||
#(#fs)*
|
||||
|
||||
|
@ -1005,6 +1394,20 @@ pub fn go(opts: &Opts<Vec<u8>>) -> proc_macro2::TokenStream {
|
|||
#(#init);*;
|
||||
return Ok(())
|
||||
}
|
||||
impl<Target: #name + ?Sized> Default for #data<Target>{
|
||||
fn default() -> Self{
|
||||
Self{
|
||||
#(#defaults),*
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<Target: #name + ?Sized> Clone for #data<Target>{
|
||||
fn clone(&self) -> Self{
|
||||
Self{
|
||||
#(#clones),*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
use #internal_path::{#name,#data};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue