diff --git a/cranelift/Cargo.toml b/cranelift/Cargo.toml index 6523a9d2da..c576d3990e 100644 --- a/cranelift/Cargo.toml +++ b/cranelift/Cargo.toml @@ -17,6 +17,7 @@ cretonne = { path = "lib/cretonne" } cretonne-reader = { path = "lib/reader" } cretonne-frontend = { path = "lib/frontend" } cretonne-wasm = { path = "lib/wasm" } +cretonne-native = { path = "lib/native" } filecheck = { path = "lib/filecheck" } docopt = "0.8.0" serde = "1.0.8" diff --git a/lib/native/Cargo.toml b/lib/native/Cargo.toml new file mode 100644 index 0000000000..0f66bc6037 --- /dev/null +++ b/lib/native/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "cretonne-native" +version = "0.0.0" +authors = ["The Cretonne Project Developers"] +publish = false +description = "Support for targetting the host with Cretonne" +repository = "https://github.com/stoklund/cretonne" +license = "Apache-2.0" + +[lib] +name = "cton_native" + +[dependencies] +cretonne = { path = "../cretonne" } + +[target.'cfg(any(target_arch = "x86", target_arch = "x86_64"))'.dependencies] +raw-cpuid = "3.0.0" diff --git a/lib/native/src/lib.rs b/lib/native/src/lib.rs new file mode 100644 index 0000000000..49cb173383 --- /dev/null +++ b/lib/native/src/lib.rs @@ -0,0 +1,88 @@ +//! Performs autodetection of the host for the purposes of running +//! Cretonne to generate code to run on the same machine. + +#![deny(missing_docs)] + +extern crate cretonne; + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +extern crate raw_cpuid; + +use cretonne::isa; +use cretonne::settings::{self, Configurable}; + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +use raw_cpuid::CpuId; + +/// Return `settings` and `isa` builders configured for the current host +/// machine, or `Err(())` if the host machine is not supported +/// in the current configuration. +pub fn builders() -> Result<(settings::Builder, isa::Builder), ()> { + let mut flag_builder = settings::builder(); + + // TODO: Add RISC-V support once Rust supports it. + + if cfg!(target_pointer_width = "64") { + flag_builder.enable("is_64bit").unwrap(); + } + + let name = if cfg!(any(target_arch = "x86", target_arch = "x86_64")) { + "intel" + } else if cfg!(target_arch = "arm") { + "arm32" + } else if cfg!(target_arch = "aarch64") { + "arm64" + } else { + return Err(()); + }; + + let mut isa_builder = isa::lookup(name).map_err(|err| match err { + isa::LookupError::Unknown => panic!(), + isa::LookupError::Unsupported => (()), + })?; + + if cfg!(any(target_arch = "x86", target_arch = "x86_64")) { + parse_x86_cpuid(&mut isa_builder); + } + + Ok((flag_builder, isa_builder)) +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +fn parse_x86_cpuid(isa_builder: &mut isa::Builder) { + let cpuid = CpuId::new(); + + if let Some(info) = cpuid.get_feature_info() { + if info.has_sse2() { + isa_builder.enable("has_sse2").unwrap(); + } + if info.has_sse3() { + isa_builder.enable("has_sse3").unwrap(); + } + if info.has_sse41() { + isa_builder.enable("has_sse41").unwrap(); + } + if info.has_sse42() { + isa_builder.enable("has_sse42").unwrap(); + } + if info.has_popcnt() { + isa_builder.enable("has_popcnt").unwrap(); + } + if info.has_avx() { + isa_builder.enable("has_avx").unwrap(); + } + } + if let Some(info) = cpuid.get_extended_feature_info() { + if info.has_bmi1() { + isa_builder.enable("has_bmi1").unwrap(); + } + if info.has_bmi2() { + isa_builder.enable("has_bmi2").unwrap(); + } + } + if let Some(info) = cpuid.get_extended_function_info() { + if info.has_lzcnt() { + isa_builder.enable("has_lzcnt").unwrap(); + } + } +}