diff --git a/Cargo.lock b/Cargo.lock index 330b3e629a4..b935fa3fcef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2595,6 +2595,7 @@ dependencies = [ "rayon", "serde", "smallvec", + "target-lexicon", "wasmer-compiler", "wasmer-types", "wasmer-vm", diff --git a/lib/compiler-singlepass/Cargo.toml b/lib/compiler-singlepass/Cargo.toml index c9083cbf6e6..4bab054c7d2 100644 --- a/lib/compiler-singlepass/Cargo.toml +++ b/lib/compiler-singlepass/Cargo.toml @@ -25,6 +25,9 @@ lazy_static = "1.4" byteorder = "1.3" smallvec = "1.5" +[dev-dependencies] +target-lexicon = { version = "0.11", default-features = false } + [badges] maintenance = { status = "actively-developed" } diff --git a/lib/compiler-singlepass/src/compiler.rs b/lib/compiler-singlepass/src/compiler.rs index c1f7b1974d0..1228fc46b20 100644 --- a/lib/compiler-singlepass/src/compiler.rs +++ b/lib/compiler-singlepass/src/compiler.rs @@ -11,11 +11,11 @@ use rayon::prelude::{IntoParallelIterator, IntoParallelRefIterator, ParallelIter use std::sync::Arc; use wasmer_compiler::wasmparser::BinaryReaderError; use wasmer_compiler::TrapInformation; -use wasmer_compiler::{Compilation, CompileError, CompiledFunction, Compiler, SectionIndex}; use wasmer_compiler::{ - CompileModuleInfo, CompilerConfig, MiddlewareBinaryReader, ModuleMiddlewareChain, - ModuleTranslationState, Target, + Architecture, CompileModuleInfo, CompilerConfig, MiddlewareBinaryReader, ModuleMiddlewareChain, + ModuleTranslationState, OperatingSystem, Target, }; +use wasmer_compiler::{Compilation, CompileError, CompiledFunction, Compiler, SectionIndex}; use wasmer_compiler::{FunctionBody, FunctionBodyData}; use wasmer_types::entity::{EntityRef, PrimaryMap}; use wasmer_types::{FunctionIndex, FunctionType, LocalFunctionIndex, MemoryIndex, TableIndex}; @@ -44,11 +44,19 @@ impl Compiler for SinglepassCompiler { /// associated relocations. fn compile_module( &self, - _target: &Target, + target: &Target, compile_info: &mut CompileModuleInfo, _module_translation: &ModuleTranslationState, function_body_inputs: PrimaryMap>, ) -> Result { + if target.triple().operating_system == OperatingSystem::Windows { + return Err(CompileError::UnsupportedTarget( + OperatingSystem::Windows.to_string(), + )); + } + if let Architecture::X86_32(arch) = target.triple().architecture { + return Err(CompileError::UnsupportedTarget(arch.to_string())); + } if compile_info.features.multi_value { return Err(CompileError::UnsupportedFeature("multivalue".to_string())); } @@ -163,3 +171,60 @@ impl ToCompileError for CodegenError { fn to_compile_error(x: T) -> CompileError { x.to_compile_error() } + +#[cfg(test)] +mod tests { + use super::*; + use std::str::FromStr; + use target_lexicon::triple; + use wasmer_compiler::{CpuFeature, Features, Triple}; + use wasmer_vm::{MemoryStyle, TableStyle}; + + fn dummy_compilation_ingredients<'a>() -> ( + CompileModuleInfo, + ModuleTranslationState, + PrimaryMap>, + ) { + let compile_info = CompileModuleInfo { + features: Features::new(), + module: Arc::new(ModuleInfo::new()), + memory_styles: PrimaryMap::::new(), + table_styles: PrimaryMap::::new(), + }; + let module_translation = ModuleTranslationState::new(); + let function_body_inputs = PrimaryMap::>::new(); + (compile_info, module_translation, function_body_inputs) + } + + #[test] + fn errors_for_unsupported_targets() { + let compiler = SinglepassCompiler::new(Singlepass::default()); + + // Compile for win64 + let win64 = Target::new(triple!("x86_64-pc-windows-msvc"), CpuFeature::for_host()); + let (mut info, translation, inputs) = dummy_compilation_ingredients(); + let result = compiler.compile_module(&win64, &mut info, &translation, inputs); + match result.unwrap_err() { + CompileError::UnsupportedTarget(name) => assert_eq!(name, "windows"), + error => panic!("Unexpected error: {:?}", error), + }; + + // Compile for 32bit Linux + let linux32 = Target::new(triple!("i686-unknown-linux-gnu"), CpuFeature::for_host()); + let (mut info, translation, inputs) = dummy_compilation_ingredients(); + let result = compiler.compile_module(&linux32, &mut info, &translation, inputs); + match result.unwrap_err() { + CompileError::UnsupportedTarget(name) => assert_eq!(name, "i686"), + error => panic!("Unexpected error: {:?}", error), + }; + + // Compile for win32 + let win32 = Target::new(triple!("i686-pc-windows-gnu"), CpuFeature::for_host()); + let (mut info, translation, inputs) = dummy_compilation_ingredients(); + let result = compiler.compile_module(&win32, &mut info, &translation, inputs); + match result.unwrap_err() { + CompileError::UnsupportedTarget(name) => assert_eq!(name, "windows"), // Windows should be checked before architecture + error => panic!("Unexpected error: {:?}", error), + }; + } +} diff --git a/lib/compiler/src/error.rs b/lib/compiler/src/error.rs index 88dcd6b7ddb..871adf3663f 100644 --- a/lib/compiler/src/error.rs +++ b/lib/compiler/src/error.rs @@ -32,6 +32,11 @@ pub enum CompileError { #[cfg_attr(feature = "std", error("Feature {0} is not yet supported"))] UnsupportedFeature(String), + /// The compiler cannot compile for the given target. + /// This can refer to the OS, the chipset or any other aspect of the target system. + #[cfg_attr(feature = "std", error("The target {0} is not yet supported (see https://docs.wasmer.io/ecosystem/wasmer/wasmer-features)"))] + UnsupportedTarget(String), + /// Insufficient resources available for execution. #[cfg_attr(feature = "std", error("Insufficient resources: {0}"))] Resource(String),