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
125
126
127
128
129
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, CompilerConfig, 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],
        compiler_config: CompilerConfig,
        _: Token,
    ) -> CompileResult<ModuleInner> {
        validate(wasm)?;

        let isa = get_isa();

        let mut module = module::Module::new(&compiler_config);
        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");