Skip to content

Commit

Permalink
compiler: add wasmer-artifact-load,wasmer-artifact-create,`static…
Browse files Browse the repository at this point in the history
…-artifact-load`,`static-artifact-create` feature flags
  • Loading branch information
epilys committed Aug 2, 2022
1 parent 430a7e2 commit 8b096a5
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 14 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion lib/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ wasmer-wasi-experimental-io-devices = { version = "=3.0.0-alpha.4", path = "../w
wasmer-wast = { version = "=3.0.0-alpha.4", path = "../../tests/lib/wast", optional = true }
wasmer-cache = { version = "=3.0.0-alpha.4", path = "../cache", optional = true }
wasmer-types = { version = "=3.0.0-alpha.4", path = "../types" }
wasmer-object = { version = "=3.0.0-alpha.4", path = "../object" }
wasmer-object = { version = "=3.0.0-alpha.4", path = "../object", optional = true }
wasmer-vfs = { version = "=3.0.0-alpha.4", path = "../vfs", default-features = false, features = ["host-fs"] }
atty = "0.2"
colored = "2.0"
Expand Down Expand Up @@ -66,6 +66,7 @@ default = [
"wasi",
"emscripten",
"compiler",
"wasmer-artifact-create",
]
cache = ["wasmer-cache"]
cache-blake3-pure = ["wasmer-cache/blake3-pure"]
Expand All @@ -77,6 +78,9 @@ compiler = [
"wasmer-compiler/translator",
"wasmer-compiler/compiler",
]
wasmer-artifact-create = ["compiler", "wasmer-compiler/wasmer-artifact-create", "wasmer-object"]
static-artifact-create = ["compiler", "wasmer-compiler/static-artifact-create", "wasmer-object"]

experimental-io-devices = [
"wasmer-wasi-experimental-io-devices",
"wasi"
Expand Down
6 changes: 3 additions & 3 deletions lib/cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use crate::commands::Binfmt;
#[cfg(feature = "compiler")]
use crate::commands::Compile;
#[cfg(feature = "compiler")]
#[cfg(any(feature = "static-artifact-create", feature = "wasmer-artifact-create"))]
use crate::commands::CreateExe;
#[cfg(feature = "wast")]
use crate::commands::Wast;
Expand Down Expand Up @@ -47,7 +47,7 @@ enum WasmerCLIOptions {
Compile(Compile),

/// Compile a WebAssembly binary into a native executable
#[cfg(feature = "compiler")]
#[cfg(any(feature = "static-artifact-create", feature = "wasmer-artifact-create"))]
#[structopt(name = "create-exe")]
CreateExe(CreateExe),

Expand Down Expand Up @@ -84,7 +84,7 @@ impl WasmerCLIOptions {
Self::Validate(validate) => validate.execute(),
#[cfg(feature = "compiler")]
Self::Compile(compile) => compile.execute(),
#[cfg(feature = "compiler")]
#[cfg(any(feature = "static-artifact-create", feature = "wasmer-artifact-create"))]
Self::CreateExe(create_exe) => create_exe.execute(),
Self::Config(config) => config.execute(),
Self::Inspect(inspect) => inspect.execute(),
Expand Down
4 changes: 2 additions & 2 deletions lib/cli/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ mod cache;
#[cfg(feature = "compiler")]
mod compile;
mod config;
#[cfg(feature = "compiler")]
#[cfg(any(feature = "static-artifact-create", feature = "wasmer-artifact-create"))]
mod create_exe;
mod inspect;
mod run;
Expand All @@ -18,7 +18,7 @@ mod wast;
pub use binfmt::*;
#[cfg(feature = "compiler")]
pub use compile::*;
#[cfg(feature = "compiler")]
#[cfg(any(feature = "static-artifact-create", feature = "wasmer-artifact-create"))]
pub use create_exe::*;
#[cfg(feature = "wast")]
pub use wast::*;
Expand Down
3 changes: 2 additions & 1 deletion lib/compiler/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ edition = "2018"

[dependencies]
wasmer-types = { path = "../types", version = "=3.0.0-alpha.4", default-features = false }
wasmer-object = { path = "../object", version = "=3.0.0-alpha.4", optional = true }
wasmparser = { version = "0.83", optional = true, default-features = false }
enumset = "1.0.2"
hashbrown = { version = "0.11", optional = true }
Expand Down Expand Up @@ -47,7 +48,7 @@ compiler = ["translator"]
wasmer-artifact-load = []
wasmer-artifact-create = []
static-artifact-load = []
static-artifact-create = []
static-artifact-create = ["wasmer-object"]
std = ["wasmer-types/std"]
core = ["hashbrown", "wasmer-types/core"]
enable-serde = ["serde", "serde_bytes", "wasmer-types/enable-serde"]
Expand Down
151 changes: 149 additions & 2 deletions lib/compiler/src/engine/artifact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,24 @@ use crate::engine::link::link_module;
use crate::ArtifactBuild;
use crate::ArtifactCreate;
use crate::Features;
#[cfg(feature = "compiler")]
use crate::ModuleEnvironment;
#[cfg(feature = "static-artifact-create")]
use crate::{FunctionBodyData, Compiler, ModuleTranslationState};
use crate::{
register_frame_info, resolve_imports, FunctionExtent, GlobalFrameInfoRegistration,
InstantiationError, RuntimeError, Tunables,
};
use crate::{Engine, EngineInner};
use crate::ModuleEnvironment;
use enumset::EnumSet;
use std::sync::Arc;
use std::sync::Mutex;
#[cfg(feature = "static-artifact-create")]
use wasmer_object::{emit_compilation, emit_data, get_object_for_target, Object};
use wasmer_types::entity::{BoxedSlice, PrimaryMap};
use wasmer_types::MetadataHeader;
#[cfg(feature = "static-artifact-create")]
#[cfg(feature = "compiler")]
use wasmer_types::{compilation::symbols::ModuleMetadata, CompileModuleInfo, Target};
use wasmer_types::{
CompileError, CpuFeature, DataInitializer, DeserializeError, FunctionIndex, LocalFunctionIndex,
MemoryIndex, ModuleInfo, OwnedDataInitializer, SerializableModule, SerializeError,
Expand Down Expand Up @@ -378,4 +384,145 @@ impl Artifact {
.finish_instantiation(trap_handler, &data_initializers)
.map_err(|trap| InstantiationError::Start(RuntimeError::from_trap(trap)))
}

#[cfg(feature = "static-artifact-create")]
/// Generate a compilation
fn generate_metadata<'data>(
&self,
data: &'data [u8],
compiler: &dyn Compiler,
tunables: &dyn Tunables,
) -> Result<
(
CompileModuleInfo,
PrimaryMap<LocalFunctionIndex, FunctionBodyData<'data>>,
Vec<DataInitializer<'data>>,
Option<ModuleTranslationState>,
),
CompileError,
> {
let environ = ModuleEnvironment::new();
let translation = environ.translate(data).map_err(CompileError::Wasm)?;
let features = self.features().clone();

// We try to apply the middleware first
use crate::translator::ModuleMiddlewareChain;
let mut module = translation.module;
let middlewares = compiler.get_middlewares();
middlewares.apply_on_module_info(&mut module);

let memory_styles: PrimaryMap<MemoryIndex, MemoryStyle> = module
.memories
.values()
.map(|memory_type| tunables.memory_style(memory_type))
.collect();
let table_styles: PrimaryMap<TableIndex, TableStyle> = module
.tables
.values()
.map(|table_type| tunables.table_style(table_type))
.collect();

let compile_info = CompileModuleInfo {
module,
features,
memory_styles,
table_styles,
};
Ok((
compile_info,
translation.function_body_inputs,
translation.data_initializers,
translation.module_translation_state,
))
}

/// Compile a module into an object file, which can be statically linked against.
///
/// The `prefixer` returns the a String to prefix each of the
/// functions in the static object generated by the
/// so we can assure no collisions.
#[cfg(feature = "static-artifact-create")]
pub fn generate_object<'data>(
&self,
compiler: &dyn Compiler,
data: &[u8],
prefixer: Option<Box<dyn Fn(&[u8]) -> String + Send>>,
target: &'data Target,
tunables: &dyn Tunables,
) -> Result<Object<'data>, CompileError> {
fn to_compile_error(err: impl std::error::Error) -> CompileError {
CompileError::Codegen(format!("{}", err))
}

#[allow(dead_code)]
const WASMER_METADATA_SYMBOL: &[u8] = b"WASMER_METADATA";

let (compile_info, function_body_inputs, data_initializers, module_translation) =
self.generate_metadata(data, compiler, tunables)?;

let data_initializers = data_initializers
.iter()
.map(OwnedDataInitializer::new)
.collect::<Vec<_>>()
.into_boxed_slice();

let target_triple = target.triple();

// TODO: we currently supply all-zero function body lengths.
// We don't know the lengths until they're compiled, yet we have to
// supply the metadata as an input to the compile.
let function_body_lengths = function_body_inputs
.keys()
.map(|_function_body| 0u64)
.collect::<PrimaryMap<LocalFunctionIndex, u64>>();

let mut metadata = ModuleMetadata {
compile_info,
prefix: prefixer.as_ref().map(|p| p(data)).unwrap_or_default(),
data_initializers,
function_body_lengths,
cpu_features: target.cpu_features().as_u64(),
};

/*
In the C file we need:
- imports
- exports
to construct an api::Module which is a Store (can be passed in via argument) and an
Arc<dyn Artifact> which means this struct which includes:
- CompileModuleInfo
- Features
- ModuleInfo
- MemoryIndex -> MemoryStyle
- TableIndex -> TableStyle
- LocalFunctionIndex -> FunctionBodyPtr // finished functions
- FunctionIndex -> FunctionBodyPtr // finished dynamic function trampolines
- SignatureIndex -> VMSharedSignatureindextureIndex // signatures
*/

let serialized_data = metadata.serialize().map_err(to_compile_error)?;
let mut metadata_binary = vec![];
metadata_binary.extend(MetadataHeader::new(serialized_data.len()).into_bytes());
metadata_binary.extend(serialized_data);

let (_compile_info, symbol_registry) = metadata.split();

let compilation = compiler.compile_module(
&target,
&metadata.compile_info,
module_translation.as_ref().unwrap(),
function_body_inputs,
)?;

let mut obj = get_object_for_target(&target_triple).map_err(to_compile_error)?;

emit_data(&mut obj, b"WASMER_MODULE_METADATA", &metadata_binary, 1)
.map_err(to_compile_error)?;

emit_compilation(&mut obj, compilation, &symbol_registry, &target_triple)
.map_err(to_compile_error)?;

Ok(obj)
}
}
4 changes: 0 additions & 4 deletions lib/object/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,5 @@ edition = "2018"

[dependencies]
wasmer-types = { path = "../types", version = "=3.0.0-alpha.4" }
wasmer-compiler = { path = "../compiler", version = "=3.0.0-alpha.4", default-features = false, features = [
"std",
"translator",
] }
object = { version = "0.28.3", default-features = false, features = ["write"] }
thiserror = "1.0"

0 comments on commit 8b096a5

Please sign in to comment.