Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 2 additions & 152 deletions cranelift/codegen/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,161 +136,11 @@ fn main() {
.unwrap();
}

/// Strip the current directory from the file paths, because `islec`
/// includes them in the generated source, and this helps us maintain
/// deterministic builds that don't include those local file paths.
fn make_isle_source_path_relative(
cur_dir: &std::path::PathBuf,
filename: std::path::PathBuf,
) -> std::path::PathBuf {
if let Ok(suffix) = filename.strip_prefix(&cur_dir) {
suffix.to_path_buf()
} else {
filename
}
}

/// A list of compilations (transformations from ISLE source to
/// generated Rust source) that exist in the repository.
///
/// This list is used either to regenerate the Rust source in-tree (if
/// the `rebuild-isle` feature is enabled), or to verify that the ISLE
/// source in-tree corresponds to the ISLE source that was last used
/// to rebuild the Rust source (if the `rebuild-isle` feature is not
/// enabled).
#[derive(Clone, Debug)]
struct IsleCompilations {
items: Vec<IsleCompilation>,
}

#[derive(Clone, Debug)]
struct IsleCompilation {
output: std::path::PathBuf,
inputs: Vec<std::path::PathBuf>,
untracked_inputs: Vec<std::path::PathBuf>,
}

/// Construct the list of compilations (transformations from ISLE
/// source to generated Rust source) that exist in the repository.
fn get_isle_compilations(
crate_dir: &std::path::Path,
out_dir: &std::path::Path,
) -> Result<IsleCompilations, std::io::Error> {
let cur_dir = std::env::current_dir()?;

// Preludes.
let clif_lower_isle = out_dir.join("clif_lower.isle");
let clif_opt_isle = out_dir.join("clif_opt.isle");
let prelude_isle =
make_isle_source_path_relative(&cur_dir, crate_dir.join("src").join("prelude.isle"));
let prelude_opt_isle =
make_isle_source_path_relative(&cur_dir, crate_dir.join("src").join("prelude_opt.isle"));
let prelude_lower_isle =
make_isle_source_path_relative(&cur_dir, crate_dir.join("src").join("prelude_lower.isle"));
let inst_specs = make_isle_source_path_relative(&cur_dir, crate_dir.join("src").join("inst_specs.isle"));

// Directory for mid-end optimizations.
let src_opts = make_isle_source_path_relative(&cur_dir, crate_dir.join("src").join("opts"));
// Directories for lowering backends.
let src_isa_x64 =
make_isle_source_path_relative(&cur_dir, crate_dir.join("src").join("isa").join("x64"));
let src_isa_aarch64 =
make_isle_source_path_relative(&cur_dir, crate_dir.join("src").join("isa").join("aarch64"));
let src_isa_s390x =
make_isle_source_path_relative(&cur_dir, crate_dir.join("src").join("isa").join("s390x"));

let src_isa_risc_v =
make_isle_source_path_relative(&cur_dir, crate_dir.join("src").join("isa").join("riscv64"));
// This is a set of ISLE compilation units.
//
// The format of each entry is:
//
// (output Rust code file, input ISLE source files)
//
// There should be one entry for each backend that uses ISLE for lowering,
// and if/when we replace our peephole optimization passes with ISLE, there
// should be an entry for each of those as well.
//
// N.B.: add any new compilation outputs to
// `scripts/force-rebuild-isle.sh` if they do not fit the pattern
// `cranelift/codegen/src/isa/*/lower/isle/generated_code.rs`!
Ok(IsleCompilations {
items: vec![
// The mid-end optimization rules.
IsleCompilation {
output: out_dir.join("isle_opt.rs"),
inputs: vec![
prelude_isle.clone(),
prelude_opt_isle,
src_opts.join("arithmetic.isle"),
src_opts.join("bitops.isle"),
src_opts.join("cprop.isle"),
src_opts.join("extends.isle"),
src_opts.join("icmp.isle"),
src_opts.join("remat.isle"),
src_opts.join("selects.isle"),
src_opts.join("shifts.isle"),
src_opts.join("vector.isle"),
],
untracked_inputs: vec![clif_opt_isle],
},
// The x86-64 instruction selector.
IsleCompilation {
output: out_dir.join("isle_x64.rs"),
inputs: vec![
prelude_isle.clone(),
prelude_lower_isle.clone(),
src_isa_x64.join("inst.isle"),
src_isa_x64.join("lower.isle"),
],
untracked_inputs: vec![clif_lower_isle.clone()],
},
// The aarch64 instruction selector.
IsleCompilation {
output: out_dir.join("isle_aarch64.rs"),
inputs: vec![
prelude_isle.clone(),
prelude_lower_isle.clone(),
src_isa_aarch64.join("inst.isle"),
src_isa_aarch64.join("inst_neon.isle"),
inst_specs.clone(),
src_isa_aarch64.join("lower.isle"),
src_isa_aarch64.join("lower_dynamic_neon.isle"),
],
untracked_inputs: vec![clif_lower_isle.clone()],
},
// The s390x instruction selector.
IsleCompilation {
output: out_dir.join("isle_s390x.rs"),
inputs: vec![
prelude_isle.clone(),
prelude_lower_isle.clone(),
src_isa_s390x.join("inst.isle"),
src_isa_s390x.join("lower.isle"),
],
untracked_inputs: vec![clif_lower_isle.clone()],
},
// The risc-v instruction selector.
IsleCompilation {
output: out_dir.join("isle_riscv64.rs"),
inputs: vec![
prelude_isle.clone(),
prelude_lower_isle.clone(),
src_isa_risc_v.join("inst.isle"),
src_isa_risc_v.join("inst_vector.isle"),
src_isa_risc_v.join("lower.isle"),
],
untracked_inputs: vec![clif_lower_isle.clone()],
},
],
})
}

pub fn build_isle(
crate_dir: &std::path::Path,
isle_dir: &std::path::Path,
) -> Result<(), Box<dyn std::error::Error + 'static>> {
let isle_compilations = get_isle_compilations(crate_dir, isle_dir)?;
let isle_compilations = meta::isle::get_isle_compilations(crate_dir, isle_dir)?;

let mut had_error = false;
for compilation in &isle_compilations.items {
Expand Down Expand Up @@ -325,7 +175,7 @@ pub fn build_isle(
///
/// NB: This must happen *after* the `cranelift-codegen-meta` functions, since
/// it consumes files generated by them.
fn run_compilation(compilation: &IsleCompilation) -> Result<(), Errors> {
fn run_compilation(compilation: &meta::isle::IsleCompilation) -> Result<(), Errors> {
use cranelift_isle as isle;

eprintln!("Rebuilding {}", compilation.output.display());
Expand Down
156 changes: 156 additions & 0 deletions cranelift/codegen/meta/src/isle.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
/// A list of compilations (transformations from ISLE source to
/// generated Rust source) that exist in the repository.
///
/// This list is used either to regenerate the Rust source in-tree (if
/// the `rebuild-isle` feature is enabled), or to verify that the ISLE
/// source in-tree corresponds to the ISLE source that was last used
/// to rebuild the Rust source (if the `rebuild-isle` feature is not
/// enabled).
#[derive(Clone, Debug)]
pub struct IsleCompilations {
pub items: Vec<IsleCompilation>,
}

#[derive(Clone, Debug)]
pub struct IsleCompilation {
pub name: String,
pub output: std::path::PathBuf,
pub inputs: Vec<std::path::PathBuf>,
pub untracked_inputs: Vec<std::path::PathBuf>,
}

/// Strip the current directory from the file paths, because `islec`
/// includes them in the generated source, and this helps us maintain
/// deterministic builds that don't include those local file paths.
fn make_isle_source_path_relative(
cur_dir: &std::path::PathBuf,
filename: std::path::PathBuf,
) -> std::path::PathBuf {
if let Ok(suffix) = filename.strip_prefix(&cur_dir) {
suffix.to_path_buf()
} else {
filename
}
}

/// Construct the list of compilations (transformations from ISLE
/// source to generated Rust source) that exist in the repository.
pub fn get_isle_compilations(
crate_dir: &std::path::Path,
out_dir: &std::path::Path,
) -> Result<IsleCompilations, std::io::Error> {
let cur_dir = std::env::current_dir()?;

// Preludes.
let clif_lower_isle = out_dir.join("clif_lower.isle");
let clif_opt_isle = out_dir.join("clif_opt.isle");
let prelude_isle =
make_isle_source_path_relative(&cur_dir, crate_dir.join("src").join("prelude.isle"));
let prelude_opt_isle =
make_isle_source_path_relative(&cur_dir, crate_dir.join("src").join("prelude_opt.isle"));
let prelude_lower_isle =
make_isle_source_path_relative(&cur_dir, crate_dir.join("src").join("prelude_lower.isle"));
let inst_specs =
make_isle_source_path_relative(&cur_dir, crate_dir.join("src").join("inst_specs.isle"));

// Directory for mid-end optimizations.
let src_opts = make_isle_source_path_relative(&cur_dir, crate_dir.join("src").join("opts"));
// Directories for lowering backends.
let src_isa_x64 =
make_isle_source_path_relative(&cur_dir, crate_dir.join("src").join("isa").join("x64"));
let src_isa_aarch64 =
make_isle_source_path_relative(&cur_dir, crate_dir.join("src").join("isa").join("aarch64"));
let src_isa_s390x =
make_isle_source_path_relative(&cur_dir, crate_dir.join("src").join("isa").join("s390x"));

let src_isa_risc_v =
make_isle_source_path_relative(&cur_dir, crate_dir.join("src").join("isa").join("riscv64"));
// This is a set of ISLE compilation units.
//
// The format of each entry is:
//
// (output Rust code file, input ISLE source files)
//
// There should be one entry for each backend that uses ISLE for lowering,
// and if/when we replace our peephole optimization passes with ISLE, there
// should be an entry for each of those as well.
//
// N.B.: add any new compilation outputs to
// `scripts/force-rebuild-isle.sh` if they do not fit the pattern
// `cranelift/codegen/src/isa/*/lower/isle/generated_code.rs`!
Ok(IsleCompilations {
items: vec![
// The mid-end optimization rules.
IsleCompilation {
name: "opt".to_string(),
output: out_dir.join("isle_opt.rs"),
inputs: vec![
prelude_isle.clone(),
prelude_opt_isle,
src_opts.join("arithmetic.isle"),
src_opts.join("bitops.isle"),
src_opts.join("cprop.isle"),
src_opts.join("extends.isle"),
src_opts.join("icmp.isle"),
src_opts.join("remat.isle"),
src_opts.join("selects.isle"),
src_opts.join("shifts.isle"),
src_opts.join("vector.isle"),
],
untracked_inputs: vec![clif_opt_isle],
},
// The x86-64 instruction selector.
IsleCompilation {
name: "x64".to_string(),
output: out_dir.join("isle_x64.rs"),
inputs: vec![
prelude_isle.clone(),
prelude_lower_isle.clone(),
src_isa_x64.join("inst.isle"),
src_isa_x64.join("lower.isle"),
],
untracked_inputs: vec![clif_lower_isle.clone()],
},
// The aarch64 instruction selector.
IsleCompilation {
name: "aarch64".to_string(),
output: out_dir.join("isle_aarch64.rs"),
inputs: vec![
prelude_isle.clone(),
prelude_lower_isle.clone(),
src_isa_aarch64.join("inst.isle"),
src_isa_aarch64.join("inst_neon.isle"),
inst_specs.clone(),
src_isa_aarch64.join("lower.isle"),
src_isa_aarch64.join("lower_dynamic_neon.isle"),
],
untracked_inputs: vec![clif_lower_isle.clone()],
},
// The s390x instruction selector.
IsleCompilation {
name: "s390x".to_string(),
output: out_dir.join("isle_s390x.rs"),
inputs: vec![
prelude_isle.clone(),
prelude_lower_isle.clone(),
src_isa_s390x.join("inst.isle"),
src_isa_s390x.join("lower.isle"),
],
untracked_inputs: vec![clif_lower_isle.clone()],
},
// The risc-v instruction selector.
IsleCompilation {
name: "riscv64".to_string(),
output: out_dir.join("isle_riscv64.rs"),
inputs: vec![
prelude_isle.clone(),
prelude_lower_isle.clone(),
src_isa_risc_v.join("inst.isle"),
src_isa_risc_v.join("inst_vector.isle"),
src_isa_risc_v.join("lower.isle"),
],
untracked_inputs: vec![clif_lower_isle.clone()],
},
],
})
}
1 change: 1 addition & 0 deletions cranelift/codegen/meta/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ mod srcgen;

pub mod error;
pub mod isa;
pub mod isle;

mod gen_inst;
mod gen_settings;
Expand Down
5 changes: 5 additions & 0 deletions cranelift/isle/veri/veri_engine/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Prototype verification tool for Cranelift's ISLE lowering rules.

use clap::{ArgAction, Parser};
use cranelift_codegen_meta as meta;
use std::env;
use std::path::PathBuf;
use veri_engine_lib::verify::verify_rules;
Expand Down Expand Up @@ -60,6 +61,10 @@ fn main() {
);
}

// Just confirm we can call get_isle_compilations from codegen meta here.
// TODO(mbm): use the right directories! use these!
let _isle_compilations = meta::isle::get_isle_compilations(&cur_dir, &cur_dir);

if args.aarch64 {
inputs.push(
cur_dir
Expand Down