1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
mod cache;
mod func_env;
mod libcalls;
mod module;
mod module_env;
mod relocation;
mod resolver;
mod signal;
mod trampoline;

use cranelift_codegen::{
    isa,
    settings::{self, Configurable},
};
use target_lexicon::Triple;

use wasmer_runtime_core::cache::{Artifact, Error as CacheError};
use wasmer_runtime_core::{
    backend::{Compiler, Token},
    error::{CompileError, CompileResult},
    module::ModuleInner,
};

#[macro_use]
extern crate serde_derive;

extern crate rayon;
extern crate serde;

use wasmparser::{self, WasmDecoder};

pub struct CraneliftCompiler {}

impl CraneliftCompiler {
    pub fn new() -> Self {
        Self {}
    }
}

impl Compiler for CraneliftCompiler {
    /// Compiles wasm binary to a wasmer module.
    fn compile(&self, wasm: &[u8], _: Token) -> CompileResult<ModuleInner> {
        validate(wasm)?;

        let isa = get_isa();

        let mut module = module::Module::new(wasm);
        let module_env = module_env::ModuleEnv::new(&mut module, &*isa);

        let func_bodies = module_env.translate(wasm)?;

        module.compile(&*isa, func_bodies)
    }

    /// Create a wasmer Module from an already-compiled cache.

    unsafe fn from_cache(&self, cache: Artifact, _: Token) -> Result<ModuleInner, CacheError> {
        module::Module::from_cache(cache)
    }

    //
    // fn compile_to_backend_cache_data(
    //     &self,
    //     wasm: &[u8],
    //     _: Token,
    // ) -> CompileResult<(Box<ModuleInfo>, Vec<u8>, Memory)> {
    //     validate(wasm)?;

    //     let isa = get_isa();

    //     let mut module = module::Module::new(wasm);
    //     let module_env = module_env::ModuleEnv::new(&mut module, &*isa);

    //     let func_bodies = module_env.translate(wasm)?;

    //     let (info, backend_cache, compiled_code) = module
    //         .compile_to_backend_cache(&*isa, func_bodies)
    //         .map_err(|e| CompileError::InternalError {
    //             msg: format!("{:?}", e),
    //         })?;

    //     let buffer =
    //         backend_cache
    //             .into_backend_data()
    //             .map_err(|e| CompileError::InternalError {
    //                 msg: format!("{:?}", e),
    //             })?;

    //     Ok((Box::new(info), buffer, compiled_code))
    // }
}

fn get_isa() -> Box<isa::TargetIsa> {
    let flags = {
        let mut builder = settings::builder();
        builder.set("opt_level", "best").unwrap();

        if cfg!(not(test)) {
            builder.set("enable_verifier", "false").unwrap();
        }

        let flags = settings::Flags::new(builder);
        debug_assert_eq!(flags.opt_level(), settings::OptLevel::Best);
        flags
    };
    isa::lookup(Triple::host()).unwrap().finish(flags)
}

fn validate(bytes: &[u8]) -> CompileResult<()> {
    let mut parser = wasmparser::ValidatingParser::new(bytes, None);
    loop {
        let state = parser.read();
        match *state {
            wasmparser::ParserState::EndWasm => break Ok(()),
            wasmparser::ParserState::Error(err) => Err(CompileError::ValidationError {
                msg: err.message.to_string(),
            })?,
            _ => {}
        }
    }
}

/// The current version of this crate
pub const VERSION: &str = env!("CARGO_PKG_VERSION");