#llvm-ir #llvm #wasm-module #wasm #compiler #wasm-binary

wasmlite-parser

This crate parses WebAssembly modules and can generate LLVM IR based the data extracted from a module

1 unstable release

0.0.1 Feb 14, 2019

#24 in #llvm-ir


Used in 2 crates

Apache-2.0

56KB
1K SLoC

WASMLITE (WASM TO LLVM)

This project aims to provide the necessary tools for compiling wasm binary to LLVM IR which can further be compiled to machine-specific code.

This project is supposed to make it easy for languages compiling to wasm to take advantage of the LLVM infrastructure.

It also allows stripping of expensive wasm runtime elements for times when full wasm specification is not desired.

Lastly, it is a platform for learning about WebAssmbly, LLVM and how they can play well together.

POSSIBLE API (NOT FINAL)

COMPILATION PIPELINE
// Create compiler flags.
let compiler_flags = Some(CompilerOptions {
    optimization_level: 3,
    exclude_passes: vec![
        LLVMPass::InstCombine,
    ],
    runtime_ignores: vec![
        RuntimeProperty::SignatureChecks,
        RuntimeProperty::MemoryBoundsChecks,
    ],
    strategy: CompilationStrategy::Normal,
});

// Create wasm instance options.
let instance_options = Some(InstanceOptions {
    compiler_flags,
    abi: vec![ABI::LLVMMusl],
});

// JIT compile module in current process.
let (module, instance) = Runtime::instantiate(wasm_binary, imports, instance_options);

// Get the exported main function from instance.
let main = instance.get_func("main");

// Store array of items in wasm memory 0
let wasm_array = instance.set_array(&arguments);

// Call the function.
main.call(5, wasm_array);
COMPILATION TYPES AOT COMPILATIONS
// Create compiler flags.
let compiler_flags = Some(CompilerOptions {
    strategy: CompilationStrategy::AheadOfTime,
    ..
});

// Create wasm instance options.
let instance_options = Some(InstanceOptions { compiler_flags, .. });

// instance holds an in-memory object code of the entire wasm program.
// Possibly generates a dylib for known imports as well.
let (module, instantiate) = Runtime::instantiate(wasm_binary, imports, instance_options);

// Create executables.
let (imports_dylib, wasm_exe) = module.create_executables();
LAZY COMPILATION
// Create compiler flags.
let compiler_flags = Some(CompilerOptions {
    strategy: CompilationStrategy::LazyCompilation,
    ..
});

// Create wasm instance options.
let instance_options = Some(InstanceOptions { compiler_flags, .. });

// Functions are not compiled until their first call.
let (module, instance) = Runtime::instantiate(wasm_binary, imports, instance_options);
REPL-TYPE LAZY COMPILATION
// Create compiler flags.
let compiler_flags = Some(CompilerOptions {
    strategy: CompilationStrategy::REPL,
    ..
});

// Create wasm instance options.
let instance_options = Some(InstanceOptions { compiler_flags, .. });

// Lazily compiles the entire wasm instance.
let (module, instance) = Runtime::instantiate(wasm_binary, imports, instance_options);

// ???
let func = module.add_function(wasm_function_binary, instance);
let expression = module.add_expression(wasm_expression_binary, instance);

NON_GOAL

  • Have multiple backends

STRATEGY

  • Single-pass parsing, validation and codegen from wasm binary to LLVM IR

CURRENT SUPPORT

  • Parser

    • preamble
    • types
    • imports
    • internal memories, tables
    • elems, data, globals
    • functions body
    • exports
  • Codegen

  • Runtime

  • Compilation Strategies

  • Compilation Flags

  • An ABI

  • Other Features

TODO

Dependencies

~0.3–1MB
~21K SLoC