[meta] Move source generation responsibility into the meta crate itself;
This commit is contained in:
committed by
Dan Gohman
parent
afa4a749c5
commit
25fdda6134
@@ -20,7 +20,6 @@
|
|||||||
|
|
||||||
use cranelift_codegen_meta as meta;
|
use cranelift_codegen_meta as meta;
|
||||||
|
|
||||||
use crate::meta::isa::Isa;
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::process;
|
use std::process;
|
||||||
use std::time::Instant;
|
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 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 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.
|
// Configure isa targets cfg.
|
||||||
match isa_targets(cranelift_targets, &target_triple) {
|
let cranelift_targets = env::var("CRANELIFT_TARGETS").ok();
|
||||||
Ok(isa_targets) => {
|
let cranelift_targets = cranelift_targets
|
||||||
for isa in &isa_targets {
|
.as_ref()
|
||||||
println!("cargo:rustc-cfg=build_{}", isa.to_string());
|
.map(|s| s.as_ref())
|
||||||
}
|
.filter(|s: &&str| s.len() > 0);
|
||||||
}
|
|
||||||
Err(err) => {
|
let isas = match cranelift_targets {
|
||||||
eprintln!("Error: {}", err);
|
Some("native") => meta::isa_from_arch(&target_triple.split('-').next().unwrap()),
|
||||||
process::exit(1);
|
Some(targets) => meta::isas_from_targets(targets.split(',').collect::<Vec<_>>()),
|
||||||
}
|
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 cur_dir = env::current_dir().expect("Can't access current working directory");
|
||||||
let crate_dir = cur_dir.as_path();
|
let crate_dir = cur_dir.as_path();
|
||||||
|
|
||||||
// Make sure we rebuild if this build script changes.
|
// Make sure we rebuild if this build script changes (will not happen with
|
||||||
// I guess that won't happen if you have non-UTF8 bytes in your path names.
|
// if the path to this file contains non-UTF8 bytes). The `build.py` script
|
||||||
// The `build.py` script prints out its own dependencies.
|
// prints out its own dependencies.
|
||||||
println!(
|
println!(
|
||||||
"cargo:rerun-if-changed={}",
|
"cargo:rerun-if-changed={}",
|
||||||
crate_dir.join("build.rs").to_str().unwrap()
|
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.
|
// 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
|
// 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.
|
// scripts, and this is a build step that isn't run very often anyway.
|
||||||
|
let python = identify_python();
|
||||||
let status = process::Command::new(python)
|
let status = process::Command::new(python)
|
||||||
.current_dir(crate_dir)
|
.current_dir(crate_dir)
|
||||||
.arg("-B")
|
.arg("-B")
|
||||||
@@ -83,12 +85,15 @@ fn main() {
|
|||||||
// emitted by the `meta` crate.
|
// 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);
|
eprintln!("Error: {}", err);
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(_) = env::var("CRANELIFT_VERBOSE") {
|
if let Ok(_) = env::var("CRANELIFT_VERBOSE") {
|
||||||
|
for isa in &isas {
|
||||||
|
println!("cargo:warning=Includes support for {} ISA", isa.to_string());
|
||||||
|
}
|
||||||
println!(
|
println!(
|
||||||
"cargo:warning=Build step took {:?}.",
|
"cargo:warning=Build step took {:?}.",
|
||||||
Instant::now() - start_time
|
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 {
|
fn identify_python() -> &'static str {
|
||||||
for python in &["python", "python3", "python2.7"] {
|
for python in &["python", "python3", "python2.7"] {
|
||||||
if process::Command::new(python)
|
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)");
|
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<Vec<Isa>, 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::<Vec<_>>();
|
|
||||||
let isa_targets = targets.split(',').flat_map(Isa::new).collect::<Vec<_>>();
|
|
||||||
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()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ pub enum Isa {
|
|||||||
|
|
||||||
impl Isa {
|
impl Isa {
|
||||||
/// Creates isa target using name.
|
/// Creates isa target using name.
|
||||||
pub fn new(name: &str) -> Option<Self> {
|
pub fn from_name(name: &str) -> Option<Self> {
|
||||||
Isa::all()
|
Isa::all()
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
@@ -27,28 +27,20 @@ impl Isa {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Creates isa target from arch.
|
/// Creates isa target from arch.
|
||||||
pub fn from_arch(arch: &str) -> Option<Isa> {
|
pub fn from_arch(arch: &str) -> Option<Self> {
|
||||||
Isa::all()
|
match arch {
|
||||||
.iter()
|
"riscv" => Some(Isa::Riscv),
|
||||||
.cloned()
|
"aarch64" => Some(Isa::Arm64),
|
||||||
.filter(|isa| isa.is_arch_applicable(arch))
|
x if ["x86_64", "i386", "i586", "i686"].contains(&x) => Some(Isa::X86),
|
||||||
.next()
|
x if x.starts_with("arm") || arch.starts_with("thumb") => Some(Isa::Arm32),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns all supported isa targets.
|
/// Returns all supported isa targets.
|
||||||
pub fn all() -> [Isa; 4] {
|
pub fn all() -> [Isa; 4] {
|
||||||
[Isa::Riscv, Isa::X86, Isa::Arm32, Isa::Arm64]
|
[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 {
|
impl fmt::Display for Isa {
|
||||||
@@ -62,11 +54,13 @@ impl fmt::Display for Isa {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn define_all(shared_settings: &SettingGroup) -> Vec<TargetIsa> {
|
pub fn define(isas: &Vec<Isa>, shared_settings: &SettingGroup) -> Vec<TargetIsa> {
|
||||||
vec![
|
isas.iter()
|
||||||
riscv::define(shared_settings),
|
.map(|isa| match isa {
|
||||||
arm32::define(shared_settings),
|
Isa::Riscv => riscv::define(shared_settings),
|
||||||
arm64::define(shared_settings),
|
Isa::X86 => x86::define(shared_settings),
|
||||||
x86::define(shared_settings),
|
Isa::Arm32 => arm32::define(shared_settings),
|
||||||
]
|
Isa::Arm64 => arm64::define(shared_settings),
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,70 @@
|
|||||||
mod cdsl;
|
mod cdsl;
|
||||||
|
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod gen_registers;
|
|
||||||
pub mod gen_settings;
|
|
||||||
pub mod gen_types;
|
|
||||||
pub mod isa;
|
pub mod isa;
|
||||||
|
|
||||||
|
mod gen_registers;
|
||||||
|
mod gen_settings;
|
||||||
|
mod gen_types;
|
||||||
|
|
||||||
mod base;
|
mod base;
|
||||||
mod constant_hash;
|
mod constant_hash;
|
||||||
mod srcgen;
|
mod srcgen;
|
||||||
mod unique_table;
|
mod unique_table;
|
||||||
|
|
||||||
|
pub fn isa_from_arch(arch: &str) -> Result<Vec<isa::Isa>, 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<Vec<isa::Isa>, String> {
|
||||||
|
type R<'a> = Vec<(&'a str, Option<isa::Isa>)>;
|
||||||
|
|
||||||
|
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::<Vec<_>>()
|
||||||
|
.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<Vec<isa::Isa>, String> {
|
||||||
|
isas_from_targets(vec![])
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates all the Rust source files used in Cranelift from the meta-language.
|
||||||
|
pub fn generate(isas: &Vec<isa::Isa>, 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(())
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user