Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
xsmith
WebAssembly Sandbox
Commits
1851bbcc
Commit
1851bbcc
authored
Dec 07, 2021
by
Guy Watson
Browse files
WIP add support functions and trimmings for wasmtime
parent
15ad25cb
Changes
2
Hide whitespace changes
Inline
Side-by-side
wasmtime/load-wasmtime/Cargo.toml
View file @
1851bbcc
...
...
@@ -7,3 +7,4 @@ edition = "2021"
[dependencies]
wasmtime
=
"0.31.0"
structopt
=
"0.3.25"
wasmtime/load-wasmtime/src/main.rs
View file @
1851bbcc
...
...
@@ -3,6 +3,7 @@ use std::fs;
use
structopt
::
StructOpt
;
use
crc
::{
Crc
,
CRC_32_ISO_HDLC
};
use
std
::
sync
::{
Arc
,
Mutex
};
use
wasmtime
::{
Caller
,
Engine
,
Module
,
Store
,
Instance
,
Func
};
/// Run a wasm program using Wasmer
...
...
@@ -10,16 +11,16 @@ use std::sync::{Arc, Mutex};
#[structopt(name
=
"load-wasmtime"
,
about
=
"Uses Wasmtime to load and execute a WebAssembly program."
)]
struct
Cli
{
/// Compiler. Options are "singlepass", "cranelift", or "llvm".
#[structopt(long,
required(
true
))]
compiler
:
String
,
//
#[structopt(long, required(true))]
//
compiler: String,
/// Engine. Options are "universal" or "dylib".
#[structopt(long,
required(
true
))]
engine
:
String
,
//
#[structopt(long, required(true))]
//
engine: String,
/// Select if the compiler should apply optimizations.
#[structopt(long
=
"optimize"
)]
should_optimize
:
bool
,
//
#[structopt(long = "optimize")]
//
should_optimize: bool,
/// The path to the wasm program (.wasm).
#[structopt(required(
true
))]
...
...
@@ -31,77 +32,79 @@ static CRC_ALGORITHM: Crc<u32> = Crc::<u32>::new(&CRC_32_ISO_HDLC);
fn
main
()
->
anyhow
::
Result
<
()
>
{
// Get command line arguments
let
args
=
Cli
::
from_args
();
if
!
(
args
.compiler
==
"singlepass"
||
args
.compiler
==
"cranelift"
||
args
.compiler
==
"llvm"
)
{
panic!
(
"Provided compiler option must be [
\"
singlepass
\"
|
\"
cranelift
\"
|
\"
llvm
\"
]"
);
}
if
!
(
args
.engine
==
"universal"
||
args
.engine
==
"dylib"
)
{
panic!
(
"Provided engine option must be [
\"
universal
\"
|
\"
dylib
\"
]"
);
}
//
if !(args.compiler == "singlepass"
//
|| args.compiler == "cranelift"
//
|| args.compiler == "llvm") {
//
panic!("Provided compiler option must be [\"singlepass\"|\"cranelift\"|\"llvm\"]");
//
}
//
if !(args.engine == "universal"
//
|| args.engine == "dylib") {
//
panic!("Provided engine option must be [\"universal\"|\"dylib\"]");
//
}
// Instantiate the compiler and engine into a store
let
config_options
=
(
&
args
.compiler
[
..
],
&
args
.engine
[
..
]);
let
store
=
match
config_options
{
(
"singlepass"
,
engine
)
=>
{
let
mut
compiler
=
Singlepass
::
new
();
compiler
.enable_stack_check
(
args
.should_optimize
)
.canonicalize_nans
(
args
.should_optimize
);
match
engine
{
"universal"
=>
Store
::
new
(
&
Universal
::
new
(
compiler
)
.engine
()),
"dylib"
=>
Store
::
new
(
&
Dylib
::
new
(
compiler
)
.engine
()),
_
=>
panic!
(
"engine did not match any known option"
),
}
},
(
"cranelift"
,
engine
)
=>
{
let
mut
compiler
=
Cranelift
::
new
();
compiler
.canonicalize_nans
(
args
.should_optimize
)
.opt_level
(
if
args
.should_optimize
{
CraneliftOptLevel
::
SpeedAndSize
}
else
{
CraneliftOptLevel
::
None
});
match
engine
{
"universal"
=>
Store
::
new
(
&
Universal
::
new
(
compiler
)
.engine
()),
"dylib"
=>
Store
::
new
(
&
Dylib
::
new
(
compiler
)
.engine
()),
_
=>
panic!
(
"engine did not match any known option"
),
}
},
(
"llvm"
,
engine
)
=>
{
let
mut
compiler
=
LLVM
::
new
();
compiler
.opt_level
(
if
args
.should_optimize
{
LLVMOptLevel
::
Aggressive
}
else
{
LLVMOptLevel
::
None
})
.canonicalize_nans
(
args
.should_optimize
);
match
engine
{
"universal"
=>
Store
::
new
(
&
Universal
::
new
(
compiler
)
.engine
()),
"dylib"
=>
Store
::
new
(
&
Dylib
::
new
(
compiler
)
.engine
()),
_
=>
panic!
(
"engine did not match any known option"
),
}
},
(
_
,
_
)
=>
panic!
(
"compiler did not match any known option"
),
};
//
let config_options = (&args.compiler[..], &args.engine[..]);
//
let store = match config_options {
//
("singlepass", engine) => {
//
let mut compiler = Singlepass::new();
//
compiler
//
.enable_stack_check(args.should_optimize)
//
.canonicalize_nans(args.should_optimize);
//
//
match engine {
//
"universal" => Store::new(&Universal::new(compiler).engine()),
//
"dylib" => Store::new(&Dylib::new(compiler).engine()),
//
_ => panic!("engine did not match any known option"),
//
}
//
},
//
//
("cranelift", engine) => {
//
let mut compiler = Cranelift::new();
//
compiler
//
.canonicalize_nans(args.should_optimize)
//
.opt_level(
//
if args.should_optimize {
//
CraneliftOptLevel::SpeedAndSize
//
} else {
//
CraneliftOptLevel::None
//
});
//
//
match engine {
//
"universal" => Store::new(&Universal::new(compiler).engine()),
//
"dylib" => Store::new(&Dylib::new(compiler).engine()),
//
_ => panic!("engine did not match any known option"),
//
}
//
},
//
//
("llvm", engine) => {
//
let mut compiler = LLVM::new();
//
compiler
//
.opt_level(
//
if args.should_optimize {
//
LLVMOptLevel::Aggressive
//
} else {
//
LLVMOptLevel::None
//
})
//
.canonicalize_nans(args.should_optimize);
//
//
match engine {
//
"universal" => Store::new(&Universal::new(compiler).engine()),
//
"dylib" => Store::new(&Dylib::new(compiler).engine()),
//
_ => panic!("engine did not match any known option"),
//
}
//
},
//
//
(_, _) => panic!("compiler did not match any known option"),
//
};
// Get the wasm program to test
let
wasm_bytes
=
fs
::
read
(
args
.program
)
?
;
// Compile the Wasm module.
let
module
=
Module
::
new
(
&
store
,
wasm_bytes
)
?
;
let
engine
=
Engine
::
default
();
let
module
=
Module
::
new
(
&
engine
,
wasm_bytes
)
?
;
// Wasmer interoperability:
// Arc<...> - In order to allow the wasm code to interact with a data-structure on the rist side of things, we have to be able
...
...
@@ -113,7 +116,6 @@ fn main() -> anyhow::Result<()> {
// Make a crc digest
let
shared_digest
:
Arc
<
Mutex
<
Option
<
crc
::
Digest
<
u32
>>>>
=
Arc
::
new
(
Mutex
::
new
(
Some
(
CRC_ALGORITHM
.digest
())));
#[derive(wasmer::WasmerEnv,
Clone)]
struct
Env
<
'a
>
{
digest
:
Arc
<
Mutex
<
Option
<
crc
::
Digest
<
'a
,
u32
>>>>
,
}
...
...
@@ -127,44 +129,54 @@ fn main() -> anyhow::Result<()> {
owned_digest
.finalize
()
}
// Create a function to pass to wasm
let
add_to_crc_func
=
Function
::
new_native_with_env
(
&
store
,
Env
{
digest
:
shared_digest
.clone
()
},
// These clones clone the Arc, not the underlying data
add_to_crc
let
mut
store
=
Store
::
new
(
&
engine
,
Env
{
digest
:
shared_digest
.clone
()
}
);
// let add_to_crc_wasm_func = Function::new_native(
// Create a function to pass to wasm
// let add_to_crc_func = Function::new_native_with_env(
// &store,
// add_to_crc_func
// Env { digest: shared_digest.clone() }, // These clones clone the Arc, not the underlying data
// add_to_crc
// );
let
add_to_crc_func
=
Func
::
wrap
(
&
store
,
|
mut
caller
:
Caller
<
'_
,
Env
>
,
val
:
u32
|
{
add_to_crc
(
caller
.data
(),
val
);
});
// Create an import object with the crc function from the crc library.
let
import_object
=
imports!
{
"env"
=>
{
"addToCrc"
=>
add_to_crc_func
// as &From<wasmer::Function>,
},
};
// let import_object = imports! {
// "env" => {
// "addToCrc" => add_to_crc_func// as &From<wasmer::Function>,
// },
// };
let
import_object
=
[
add_to_crc_func
.into
()];
// Instantiate the Wasm module.
let
instance
=
Instance
::
new
(
&
module
,
&
import_object
)
?
;
let
instance
=
Instance
::
new
(
&
mut
store
,
&
module
,
&
import_object
)
?
;
// Get handles for the exports
let
main_func
:
NativeFunc
<
(),
i32
>
=
instance
.exports
.get_native_function
(
"_main"
)
?
;
let
crc_globals_func
:
NativeFunc
<
(),
()
>
=
instance
.exports
.get_native_function
(
"_crc_globals"
)
?
;
let
memory
=
instance
.exports
.get_memory
(
"_memory"
)
?
;
// let main_func: NativeFunc<(), i32> = instance.exports.get_native_function("_main")?;
// let crc_globals_func: NativeFunc<(), ()> = instance.exports.get_native_function("_crc_globals")?;
// let memory = instance.exports.get_memory("_memory")?;
let
main_func
=
instance
.get_typed_func
::
<
(),
i32
,
_
>
(
&
store
,
"_main"
)
?
;
let
crc_globals_func
=
instance
.get_typed_func
::
<
(),
(),
_
>
(
&
store
,
"_crc_globals"
)
?
;
let
memory
=
instance
.get_memory
(
&
store
,
"_memory"
)
?
;
// Call main and add the result to the crc
add_to_crc
(
&
Env
{
digest
:
shared_digest
.clone
()
},
main_func
.call
()
?
.try_into
()
?
);
let
main_result
:
i32
=
main_func
.call
(
&
mut
store
,
())
?
;
add_to_crc
(
&
Env
{
digest
:
shared_digest
.clone
()
},
main_result
.into
());
// Call the crc globals function to have wasm add all of it's globals to the crc
crc_globals_func
.call
()
?
;
crc_globals_func
.call
(
&
store
,
()
)
?
;
// Add the contents of memory to the crc
// Get the pointer and size in bytes
let
mem_ptr
:
*
mut
i32
=
memory
.data_ptr
()
as
*
mut
i32
;
let
mem_size
=
(
memory
.data_size
()
/
4
)
as
isize
;
//
bytes to i32s
let
mem_ptr
:
*
mut
i32
=
memory
.data_ptr
(
&
store
)
as
*
mut
i32
;
let
mem_size
=
(
memory
.data_size
(
&
store
)
/
4
)
as
isize
;
//bytes to i32s
for
address
in
0
..
mem_size
{
let
mem_value
:
u32
;
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment