From 25fdda6134787bf53b69e6913c6ed2d4796b2f03 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Fri, 8 Feb 2019 19:34:55 +0100 Subject: [PATCH] [meta] Move source generation responsibility into the meta crate itself; --- cranelift/codegen/build.rs | 85 ++++++++------------------- cranelift/codegen/meta/src/isa/mod.rs | 42 ++++++------- cranelift/codegen/meta/src/lib.rs | 64 +++++++++++++++++++- 3 files changed, 102 insertions(+), 89 deletions(-) diff --git a/cranelift/codegen/build.rs b/cranelift/codegen/build.rs index c4b1a12de6..6aeaff6834 100644 --- a/cranelift/codegen/build.rs +++ b/cranelift/codegen/build.rs @@ -20,7 +20,6 @@ use cranelift_codegen_meta as meta; -use crate::meta::isa::Isa; use std::env; use std::process; use std::time::Instant; @@ -30,29 +29,31 @@ fn main() { let out_dir = env::var("OUT_DIR").expect("The OUT_DIR environment variable must be set"); let target_triple = env::var("TARGET").expect("The TARGET environment variable must be set"); - let cranelift_targets = env::var("CRANELIFT_TARGETS").ok(); - let cranelift_targets = cranelift_targets.as_ref().map(|s| s.as_ref()); - let python = identify_python(); // Configure isa targets cfg. - match isa_targets(cranelift_targets, &target_triple) { - Ok(isa_targets) => { - for isa in &isa_targets { - println!("cargo:rustc-cfg=build_{}", isa.to_string()); - } - } - Err(err) => { - eprintln!("Error: {}", err); - process::exit(1); - } + let cranelift_targets = env::var("CRANELIFT_TARGETS").ok(); + let cranelift_targets = cranelift_targets + .as_ref() + .map(|s| s.as_ref()) + .filter(|s: &&str| s.len() > 0); + + let isas = match cranelift_targets { + Some("native") => meta::isa_from_arch(&target_triple.split('-').next().unwrap()), + Some(targets) => meta::isas_from_targets(targets.split(',').collect::>()), + None => meta::all_isas(), + } + .expect("Error when identifying CRANELIFT_TARGETS and TARGET"); + + for isa in &isas { + println!("cargo:rustc-cfg=build_{}", isa.to_string()); } let cur_dir = env::current_dir().expect("Can't access current working directory"); let crate_dir = cur_dir.as_path(); - // Make sure we rebuild if this build script changes. - // I guess that won't happen if you have non-UTF8 bytes in your path names. - // The `build.py` script prints out its own dependencies. + // Make sure we rebuild if this build script changes (will not happen with + // if the path to this file contains non-UTF8 bytes). The `build.py` script + // prints out its own dependencies. println!( "cargo:rerun-if-changed={}", crate_dir.join("build.rs").to_str().unwrap() @@ -65,6 +66,7 @@ fn main() { // Launch build script with Python. We'll just find python in the path. // Use -B to disable .pyc files, because they cause trouble for vendoring // scripts, and this is a build step that isn't run very often anyway. + let python = identify_python(); let status = process::Command::new(python) .current_dir(crate_dir) .arg("-B") @@ -83,12 +85,15 @@ fn main() { // emitted by the `meta` crate. // ------------------------------------------------------------------------ - if let Err(err) = generate_meta(&out_dir) { + if let Err(err) = meta::generate(&isas, &out_dir) { eprintln!("Error: {}", err); process::exit(1); } if let Ok(_) = env::var("CRANELIFT_VERBOSE") { + for isa in &isas { + println!("cargo:warning=Includes support for {} ISA", isa.to_string()); + } println!( "cargo:warning=Build step took {:?}.", Instant::now() - start_time @@ -97,20 +102,6 @@ fn main() { } } -fn generate_meta(out_dir: &str) -> Result<(), meta::error::Error> { - let shared_settings = meta::gen_settings::generate_common("new_settings.rs", &out_dir)?; - let isas = meta::isa::define_all(&shared_settings); - - meta::gen_types::generate("types.rs", &out_dir)?; - - for isa in &isas { - meta::gen_registers::generate(&isa, "registers", &out_dir)?; - meta::gen_settings::generate(&isa, "new_settings", &out_dir)?; - } - - Ok(()) -} - fn identify_python() -> &'static str { for python in &["python", "python3", "python2.7"] { if process::Command::new(python) @@ -123,33 +114,3 @@ fn identify_python() -> &'static str { } panic!("The Cranelift build requires Python (version 2.7 or version 3)"); } - -/// Returns isa targets to configure conditional compilation. -fn isa_targets(cranelift_targets: Option<&str>, target_triple: &str) -> Result, String> { - match cranelift_targets { - Some("native") => Isa::from_arch(target_triple.split('-').next().unwrap()) - .map(|isa| vec![isa]) - .ok_or_else(|| { - format!( - "no supported isa found for target triple `{}`", - target_triple - ) - }), - Some(targets) => { - let unknown_isa_targets = targets - .split(',') - .filter(|target| Isa::new(target).is_none()) - .collect::>(); - let isa_targets = targets.split(',').flat_map(Isa::new).collect::>(); - match (unknown_isa_targets.is_empty(), isa_targets.is_empty()) { - (true, true) => Ok(Isa::all().to_vec()), - (true, _) => Ok(isa_targets), - (_, _) => Err(format!( - "unknown isa targets: `{}`", - unknown_isa_targets.join(", ") - )), - } - } - None => Ok(Isa::all().to_vec()), - } -} diff --git a/cranelift/codegen/meta/src/isa/mod.rs b/cranelift/codegen/meta/src/isa/mod.rs index eaa359b801..c06326689b 100644 --- a/cranelift/codegen/meta/src/isa/mod.rs +++ b/cranelift/codegen/meta/src/isa/mod.rs @@ -18,7 +18,7 @@ pub enum Isa { impl Isa { /// Creates isa target using name. - pub fn new(name: &str) -> Option { + pub fn from_name(name: &str) -> Option { Isa::all() .iter() .cloned() @@ -27,28 +27,20 @@ impl Isa { } /// Creates isa target from arch. - pub fn from_arch(arch: &str) -> Option { - Isa::all() - .iter() - .cloned() - .filter(|isa| isa.is_arch_applicable(arch)) - .next() + pub fn from_arch(arch: &str) -> Option { + match arch { + "riscv" => Some(Isa::Riscv), + "aarch64" => Some(Isa::Arm64), + x if ["x86_64", "i386", "i586", "i686"].contains(&x) => Some(Isa::X86), + x if x.starts_with("arm") || arch.starts_with("thumb") => Some(Isa::Arm32), + _ => None, + } } /// Returns all supported isa targets. pub fn all() -> [Isa; 4] { [Isa::Riscv, Isa::X86, Isa::Arm32, Isa::Arm64] } - - /// Checks if arch is applicable for the isa target. - fn is_arch_applicable(&self, arch: &str) -> bool { - match *self { - Isa::Riscv => arch == "riscv", - Isa::X86 => ["x86_64", "i386", "i586", "i686"].contains(&arch), - Isa::Arm32 => arch.starts_with("arm") || arch.starts_with("thumb"), - Isa::Arm64 => arch == "aarch64", - } - } } impl fmt::Display for Isa { @@ -62,11 +54,13 @@ impl fmt::Display for Isa { } } -pub fn define_all(shared_settings: &SettingGroup) -> Vec { - vec![ - riscv::define(shared_settings), - arm32::define(shared_settings), - arm64::define(shared_settings), - x86::define(shared_settings), - ] +pub fn define(isas: &Vec, shared_settings: &SettingGroup) -> Vec { + isas.iter() + .map(|isa| match isa { + Isa::Riscv => riscv::define(shared_settings), + Isa::X86 => x86::define(shared_settings), + Isa::Arm32 => arm32::define(shared_settings), + Isa::Arm64 => arm64::define(shared_settings), + }) + .collect() } diff --git a/cranelift/codegen/meta/src/lib.rs b/cranelift/codegen/meta/src/lib.rs index d35d8cddcc..f7f15b8d09 100644 --- a/cranelift/codegen/meta/src/lib.rs +++ b/cranelift/codegen/meta/src/lib.rs @@ -2,12 +2,70 @@ mod cdsl; pub mod error; -pub mod gen_registers; -pub mod gen_settings; -pub mod gen_types; pub mod isa; +mod gen_registers; +mod gen_settings; +mod gen_types; + mod base; mod constant_hash; mod srcgen; mod unique_table; + +pub fn isa_from_arch(arch: &str) -> Result, String> { + isa::Isa::from_arch(arch) + .ok_or_else(|| format!("no supported isa found for arch `{}`", arch)) + .and_then(|isa| Ok(vec![isa])) +} + +pub fn isas_from_targets(targets: Vec<&str>) -> Result, String> { + type R<'a> = Vec<(&'a str, Option)>; + + let (known, unknown): (R, R) = targets + .into_iter() + .map(|target| (target, isa::Isa::from_name(target))) + .partition(|(_, opt_isa)| opt_isa.is_some()); + + if !unknown.is_empty() { + let unknown_targets = unknown + .into_iter() + .map(|(target, _)| target) + .collect::>() + .join(", "); + return Err(format!("unknown isa targets: {}", unknown_targets)); + } + + let isas = if known.is_empty() { + isa::Isa::all().to_vec() + } else { + known + .into_iter() + .map(|(_, opt_isa)| opt_isa.unwrap()) + .collect() + }; + + Ok(isas) +} + +pub fn all_isas() -> Result, String> { + isas_from_targets(vec![]) +} + +/// Generates all the Rust source files used in Cranelift from the meta-language. +pub fn generate(isas: &Vec, out_dir: &str) -> Result<(), error::Error> { + // Common definitions. + let shared_settings = gen_settings::generate_common("new_settings.rs", &out_dir)?; + + gen_types::generate("types.rs", &out_dir)?; + + // Per ISA definitions. + let isas = isa::define(isas, &shared_settings); + + for isa in isas { + gen_registers::generate(&isa, "registers", &out_dir)?; + gen_settings::generate(&isa, "new_settings", &out_dir)?; + } + + Ok(()) +}