From c05527a5e6421c999c0c368b8e7b447153eea562 Mon Sep 17 00:00:00 2001 From: data-pup Date: Mon, 28 May 2018 15:16:22 -0400 Subject: [PATCH 01/26] Added initial Rust codegen-meta implementation. --- lib/codegen-meta/Cargo.toml | 18 ++ lib/codegen-meta/src/base/mod.rs | 3 + lib/codegen-meta/src/base/types.rs | 262 ++++++++++++++++ lib/codegen-meta/src/cdsl/mod.rs | 77 +++++ lib/codegen-meta/src/cdsl/types.rs | 408 +++++++++++++++++++++++++ lib/codegen-meta/src/error.rs | 47 +++ lib/codegen-meta/src/gen_build_deps.rs | 48 +++ lib/codegen-meta/src/gen_types.rs | 68 +++++ lib/codegen-meta/src/lib.rs | 7 + lib/codegen-meta/src/srcgen.rs | 315 +++++++++++++++++++ lib/codegen/Cargo.toml | 4 + lib/codegen/build.rs | 27 +- 12 files changed, 1283 insertions(+), 1 deletion(-) create mode 100644 lib/codegen-meta/Cargo.toml create mode 100644 lib/codegen-meta/src/base/mod.rs create mode 100644 lib/codegen-meta/src/base/types.rs create mode 100644 lib/codegen-meta/src/cdsl/mod.rs create mode 100644 lib/codegen-meta/src/cdsl/types.rs create mode 100644 lib/codegen-meta/src/error.rs create mode 100644 lib/codegen-meta/src/gen_build_deps.rs create mode 100644 lib/codegen-meta/src/gen_types.rs create mode 100644 lib/codegen-meta/src/lib.rs create mode 100644 lib/codegen-meta/src/srcgen.rs diff --git a/lib/codegen-meta/Cargo.toml b/lib/codegen-meta/Cargo.toml new file mode 100644 index 000000000..e81883a2f --- /dev/null +++ b/lib/codegen-meta/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "cranelift-codegen-meta" +authors = ["The Cranelift Project Developers"] +version = "0.15.0" +description = "DSL for cranelift-codegen code generator library" +license = "Apache-2.0" +documentation = "https://cranelift.readthedocs.io/" +repository = "https://github.com/CraneStation/cranelift" +keywords = ["compile", "compiler", "jit"] + +[dependencies] +# It is a goal of the cranelift-codegen crate to have minimal external dependencies. +# Please don't add any unless they are essential to the task of creating binary +# machine code. + +[badges] +maintenance = { status = "experimental" } +travis-ci = { repository = "CraneStation/cranelift" } diff --git a/lib/codegen-meta/src/base/mod.rs b/lib/codegen-meta/src/base/mod.rs new file mode 100644 index 000000000..a72bc6bc0 --- /dev/null +++ b/lib/codegen-meta/src/base/mod.rs @@ -0,0 +1,3 @@ +//! Definitions for the base Cretonne language. + +pub mod types; diff --git a/lib/codegen-meta/src/base/types.rs b/lib/codegen-meta/src/base/types.rs new file mode 100644 index 000000000..c6f1ad160 --- /dev/null +++ b/lib/codegen-meta/src/base/types.rs @@ -0,0 +1,262 @@ +//! This module predefines all the Cretonne scalar types. + +use std::fmt; + +// Numbering scheme for value types: +// +// 0: Void +// 0x01-0x6f: Special types +// 0x70-0x7f: Lane types +// 0x80-0xff: Vector types +// +// Vector types are encoded with the lane type in the low 4 bits and log2(lanes) +// in the high 4 bits, giving a range of 2-256 lanes. +static LANE_BASE: u8 = 0x70; + +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +pub enum Bool { + /// 1-bit bool. + B1 = 1, + /// 8-bit bool. + B8 = 8, + /// 16-bit bool. + B16 = 16, + /// 32-bit bool. + B32 = 32, + /// 64-bit bool. + B64 = 64, +} + +impl Bool { + /// Get the number of a boolean variant. + pub fn number(self) -> u8 { + let offset = match self { + Bool::B1 => 0, + Bool::B8 => 1, + Bool::B16 => 2, + Bool::B32 => 3, + Bool::B64 => 4, + }; + + LANE_BASE + offset + } +} + +pub struct BoolIterator { + index: usize, +} + +impl BoolIterator { + pub fn new() -> Self { + Self { index: 0 } + } +} + +impl Iterator for BoolIterator { + type Item = Bool; + fn next(&mut self) -> Option { + let res = match self.index { + 0 => Some(Bool::B1), + 1 => Some(Bool::B8), + 2 => Some(Bool::B16), + 3 => Some(Bool::B32), + 4 => Some(Bool::B64), + _ => None, + }; + self.index += 1; + res + } +} + +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +pub enum Int { + /// 8-bit int. + I8 = 8, + /// 16-bit int. + I16 = 16, + /// 32-bit int. + I32 = 32, + /// 64-bit int. + I64 = 64, +} + +impl Int { + /// Get the number of an integer variant. + pub fn number(self) -> u8 { + let offset = 5 + match self { + Int::I8 => 0, + Int::I16 => 1, + Int::I32 => 2, + Int::I64 => 3, + }; + + LANE_BASE + offset + } +} + +pub struct IntIterator { + index: usize, +} + +impl IntIterator { + pub fn new() -> Self { + Self { index: 0 } + } +} + +impl Iterator for IntIterator { + type Item = Int; + fn next(&mut self) -> Option { + let res = match self.index { + 0 => Some(Int::I8), + 1 => Some(Int::I16), + 2 => Some(Int::I32), + 3 => Some(Int::I64), + _ => None, + }; + self.index += 1; + res + } +} + +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +pub enum Float { + F32 = 32, + F64 = 64, +} + +impl Float { + /// Get the number of a float variant. + pub fn number(self) -> u8 { + let offset = 9 + match self { + Float::F32 => 0, + Float::F64 => 1, + }; + + LANE_BASE + offset + } +} + +/// Iterator through the variants of the Float enum. +pub struct FloatIterator { + index: usize, +} + +impl FloatIterator { + pub fn new() -> Self { + Self { index: 0 } + } +} + +impl Iterator for FloatIterator { + type Item = Float; + fn next(&mut self) -> Option { + let res = match self.index { + 0 => Some(Float::F32), + 1 => Some(Float::F64), + _ => None, + }; + self.index += 1; + res + } +} + +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +/// A type representing CPU flags. +/// +/// Flags can't be stored in memory. +pub enum Flag { + /// CPU flags from an integer comparison. + IFlags, + /// CPU flags from a floating point comparison. + FFlags, +} + +impl Flag { + /// Get the number of a flag variant. + pub fn number(self) -> u8 { + match self { + Flag::IFlags => 1, + Flag::FFlags => 2, + } + } +} + +impl fmt::Display for Flag { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "{}", + match self { + Flag::IFlags => "iflags", + Flag::FFlags => "fflags", + } + ) + } +} + +/// Iterator through the variants of the Flag enum. +pub struct FlagIterator { + index: usize, +} + +impl FlagIterator { + pub fn new() -> Self { + Self { index: 0 } + } +} + +impl Iterator for FlagIterator { + type Item = Flag; + fn next(&mut self) -> Option { + let res = match self.index { + 0 => Some(Flag::IFlags), + 1 => Some(Flag::FFlags), + _ => None, + }; + self.index += 1; + res + } +} + +#[cfg(test)] +mod iter_tests { + use super::*; + + #[test] + fn bool_iter_works() { + let mut bool_iter = BoolIterator::new(); + assert_eq!(bool_iter.next(), Some(Bool::B1)); + assert_eq!(bool_iter.next(), Some(Bool::B8)); + assert_eq!(bool_iter.next(), Some(Bool::B16)); + assert_eq!(bool_iter.next(), Some(Bool::B32)); + assert_eq!(bool_iter.next(), Some(Bool::B64)); + assert_eq!(bool_iter.next(), None); + } + + #[test] + fn int_iter_works() { + let mut int_iter = IntIterator::new(); + assert_eq!(int_iter.next(), Some(Int::I8)); + assert_eq!(int_iter.next(), Some(Int::I16)); + assert_eq!(int_iter.next(), Some(Int::I32)); + assert_eq!(int_iter.next(), Some(Int::I64)); + assert_eq!(int_iter.next(), None); + } + + #[test] + fn float_iter_works() { + let mut float_iter = FloatIterator::new(); + assert_eq!(float_iter.next(), Some(Float::F32)); + assert_eq!(float_iter.next(), Some(Float::F64)); + assert_eq!(float_iter.next(), None); + } + + #[test] + fn flag_iter_works() { + let mut flag_iter = FlagIterator::new(); + assert_eq!(flag_iter.next(), Some(Flag::IFlags)); + assert_eq!(flag_iter.next(), Some(Flag::FFlags)); + assert_eq!(flag_iter.next(), None); + } +} diff --git a/lib/codegen-meta/src/cdsl/mod.rs b/lib/codegen-meta/src/cdsl/mod.rs new file mode 100644 index 000000000..7926acfc7 --- /dev/null +++ b/lib/codegen-meta/src/cdsl/mod.rs @@ -0,0 +1,77 @@ +//! Cretonne DSL classes. +//! +//! This module defines the classes that are used to define Cretonne +//! instructions and other entitties. + +pub mod types; + +/// Convert the string `s` to CamelCase. +fn _camel_case(s: &str) -> String { + let mut output_chars = String::with_capacity(s.len()); + + let mut capitalize = true; + for curr_char in s.chars() { + if curr_char == '_' { + capitalize = true; + } else { + if capitalize { + output_chars.extend(curr_char.to_uppercase()); + } else { + output_chars.push(curr_char); + } + capitalize = false; + } + } + + output_chars +} + +/// Check if `x` is a power of two. +fn _is_power_of_two(x: u8) -> bool { + x > 0 && x & (x - 1) == 0 +} + +/// Compute the next power of two that is greater than `x`. +fn _next_power_of_two(x: u8) -> u8 { + let mut s = 1; + let mut res = x; + while res & (res + 1) != 0 { + res |= res >> s; + s *= 2; + } + + res + 1 +} + +#[cfg(test)] +mod tests { + use super::_camel_case as camel_case; + use super::_is_power_of_two as is_power_of_two; + use super::_next_power_of_two as next_power_of_two; + + #[test] + fn camel_case_works() { + assert_eq!(camel_case("x"), "X"); + assert_eq!(camel_case("camel_case"), "CamelCase"); + } + + #[test] + fn is_power_of_two_works() { + assert_eq!(is_power_of_two(1), true); + assert_eq!(is_power_of_two(2), true); + assert_eq!(is_power_of_two(4), true); + assert_eq!(is_power_of_two(8), true); + + assert_eq!(is_power_of_two(3), false); + assert_eq!(is_power_of_two(7), false); + } + + #[test] + fn next_power_of_two_works() { + assert_eq!(next_power_of_two(0), 1); + assert_eq!(next_power_of_two(1), 2); + assert_eq!(next_power_of_two(2), 4); + assert_eq!(next_power_of_two(3), 4); + assert_eq!(next_power_of_two(4), 8); + } +} diff --git a/lib/codegen-meta/src/cdsl/types.rs b/lib/codegen-meta/src/cdsl/types.rs new file mode 100644 index 000000000..8315440f6 --- /dev/null +++ b/lib/codegen-meta/src/cdsl/types.rs @@ -0,0 +1,408 @@ +//! Cretonne ValueType hierarchy + +// Temporary disabled: Unused at the moment. +// use std::collections::HashMap; + +use base::types as base_types; + +static _RUST_NAME_PREFIX: &'static str = "ir::types::"; + +// ValueType variants (i8, i32, ...) are provided in `base::types.rs`. + +/// A concrete SSA value type. +/// +/// All SSA values have a type that is described by an instance of `ValueType` +/// or one of its subclasses. +pub enum ValueType { + BV(BVType), + Lane(LaneType), + Special(SpecialType), + Vector(VectorType), +} + +impl ValueType { + /// Iterate through all of the lane types. + pub fn all_lane_types() -> LaneTypeIterator { + LaneTypeIterator::new() + } + + /// Iterate through all of the special types (neither lanes nor vectors). + pub fn all_special_types() -> SpecialTypeIterator { + SpecialTypeIterator::new() + } + + /// Return a string containing the documentation comment for this type. + pub fn doc(&self) -> String { + match self { + ValueType::BV(b) => b.doc(), + ValueType::Lane(l) => l.doc(), + ValueType::Special(s) => s.doc(), + ValueType::Vector(v) => v.doc(), + } + } + + /// Return the number of bits in a lane. + pub fn lane_bits(&self) -> u64 { + match self { + ValueType::BV(b) => b.lane_bits(), + ValueType::Lane(l) => l.lane_bits(), + ValueType::Special(s) => s.lane_bits(), + ValueType::Vector(v) => v.lane_bits(), + } + } + + /// Return the number of lanes. + pub fn lane_count(&self) -> u64 { + match self { + ValueType::Vector(v) => v.lane_count(), + _ => 1, + } + } + + /// Find the number of bytes that this type occupies in memory. + pub fn membytes(&self) -> u64 { + self.width() / 8 + } + + /// Get the name of this type. + pub fn name(&self) -> String { + match self { + ValueType::BV(b) => b.name(), + ValueType::Lane(l) => l.name(), + ValueType::Special(s) => s.name(), + ValueType::Vector(v) => v.name(), + } + } + + /// Find the unique number associated with this type. + pub fn number(&self) -> Option { + match self { + ValueType::BV(_) => None, + ValueType::Lane(l) => Some(l.number()), + ValueType::Special(s) => Some(s.number()), + ValueType::Vector(v) => Some(v.number()), + } + } + + /// Return the name of this type for other Rust source files. + pub fn _rust_name(&self) -> String { + format!("{}{}", _RUST_NAME_PREFIX, self.name().to_uppercase()) + } + + /// Return true iff: + /// 1. self and other have equal number of lanes + /// 2. each lane in self has at least as many bits as a lane in other + pub fn _wider_or_equal(&self, rhs: &ValueType) -> bool { + (self.lane_count() == rhs.lane_count()) && (self.lane_bits() >= rhs.lane_bits()) + } + + /// Return the total number of bits of an instance of this type. + pub fn width(&self) -> u64 { + self.lane_count() * self.lane_bits() + } +} + +/// Create a ValueType from a given bitvector type. +impl From for ValueType { + fn from(bv: BVType) -> Self { + ValueType::BV(bv) + } +} + +/// Create a ValueType from a given lane type. +impl From for ValueType { + fn from(lane: LaneType) -> Self { + ValueType::Lane(lane) + } +} + +/// Create a ValueType from a given special type. +impl From for ValueType { + fn from(spec: SpecialType) -> Self { + ValueType::Special(spec) + } +} + +/// Create a ValueType from a given vector type. +impl From for ValueType { + fn from(vector: VectorType) -> Self { + ValueType::Vector(vector) + } +} + +/// A concrete scalar type that can appear as a vector lane too. +#[derive(Debug, Clone, Copy)] +pub struct LaneType { + bits: u64, + tag: LaneTypeTag, +} + +impl LaneType { + /// Return a string containing the documentation comment for this lane type. + pub fn doc(&self) -> String { + match self.tag { + LaneTypeTag::BoolType(_) => format!("A boolean type with {} bits.", self.bits), + LaneTypeTag::FloatType(base_types::Float::F32) => String::from( + "A 32-bit floating point type represented in the IEEE 754-2008 + *binary32* interchange format. This corresponds to the :c:type:`float` + type in most C implementations.", + ), + LaneTypeTag::FloatType(base_types::Float::F64) => String::from( + "A 64-bit floating point type represented in the IEEE 754-2008 + *binary64* interchange format. This corresponds to the :c:type:`double` + type in most C implementations.", + ), + LaneTypeTag::IntType(_) if self.bits < 32 => format!( + "An integer type with {} bits. + WARNING: arithmetic on {}bit integers is incomplete", + self.bits, self.bits + ), + LaneTypeTag::IntType(_) => format!("An integer type with {} bits.", self.bits), + } + } + + /// Return the number of bits in a lane. + pub fn lane_bits(&self) -> u64 { + self.bits + } + + /// Get the name of this lane type. + pub fn name(&self) -> String { + match self.tag { + LaneTypeTag::BoolType(_) => format!("b{}", self.bits), + LaneTypeTag::FloatType(_) => format!("f{}", self.bits), + LaneTypeTag::IntType(_) => format!("i{}", self.bits), + } + } + + /// Find the unique number associated with this lane type. + pub fn number(&self) -> u8 { + match self.tag { + LaneTypeTag::BoolType(b) => b.number(), + LaneTypeTag::FloatType(f) => f.number(), + LaneTypeTag::IntType(i) => i.number(), + } + } +} + +/// Create a LaneType from a given bool variant. +impl From for LaneType { + fn from(b: base_types::Bool) -> Self { + let bits = b as u64; + let tag = LaneTypeTag::BoolType(b); + Self { bits, tag } + } +} + +/// Create a LaneType from a given float variant. +impl From for LaneType { + fn from(f: base_types::Float) -> Self { + let bits = f as u64; + let tag = LaneTypeTag::FloatType(f); + Self { bits, tag } + } +} + +/// Create a LaneType from a given int variant. +impl From for LaneType { + fn from(i: base_types::Int) -> Self { + let bits = i as u64; + let tag = LaneTypeTag::IntType(i); + Self { bits, tag } + } +} + +/// Tags used to specify the kinds of elements in a lane type. +#[derive(Debug, Clone, Copy)] +pub enum LaneTypeTag { + BoolType(base_types::Bool), + FloatType(base_types::Float), + IntType(base_types::Int), +} + +/// An iterator for different lane types. +pub struct LaneTypeIterator { + bool_iter: base_types::BoolIterator, + int_iter: base_types::IntIterator, + float_iter: base_types::FloatIterator, +} + +impl LaneTypeIterator { + /// Create a new lane type iterator. + fn new() -> Self { + Self { + bool_iter: base_types::BoolIterator::new(), + int_iter: base_types::IntIterator::new(), + float_iter: base_types::FloatIterator::new(), + } + } +} + +impl Iterator for LaneTypeIterator { + type Item = LaneType; + fn next(&mut self) -> Option { + if let b @ Some(_) = self.bool_iter.next() { + b.map(LaneType::from) + } else if let i @ Some(_) = self.int_iter.next() { + i.map(LaneType::from) + } else if let f @ Some(_) = self.float_iter.next() { + f.map(LaneType::from) + } else { + None + } + } +} + +/// A concrete SIMD vector type. +/// +/// A vector type has a lane type which is an instance of `LaneType`, +/// and a positive number of lanes. +pub struct VectorType { + base: LaneType, + lanes: u64, +} + +impl VectorType { + /// Initialize a new integer type with `n` bits. + pub fn new(base: LaneType, lanes: u64) -> VectorType { + VectorType { base, lanes } + } + + pub fn doc(&self) -> String { + format!( + "A SIMD vector with {} lanes containing a `{}` each.", + self.lanes, + self.base.name() + ) + } + + /// Get the name of this type. + pub fn name(&self) -> String { + format!("{}X{}", self.base.name(), self.lanes,) + } + + /// Find the unique number associated with this type. + pub fn number(&self) -> u8 { + let b = f64::from(self.base.number()); + let l = (self.lanes as f64).log2(); + let num = 16_f64 * l + b; + num as u8 + } + + /// Return the number of bits in a lane. + pub fn lane_bits(&self) -> u64 { + self.base.lane_bits() + } + + /// Return the number of lanes. + pub fn lane_count(&self) -> u64 { + self.lanes + } +} + +/// A flat bitvector type. Used for semantics description only. +pub struct BVType { + bits: u64, +} + +impl BVType { + /// Initialize a new bitvector type with `n` bits. + pub fn _new(bits: u64) -> Self { + Self { bits } + } + + /// Return a string containing the documentation comment for this bitvector type. + pub fn doc(&self) -> String { + format!("A bitvector type with {} bits.", self.bits) + } + + /// Return the number of bits in a lane. + pub fn lane_bits(&self) -> u64 { + self.bits + } + + /// Get the name of this bitvector type. + pub fn name(&self) -> String { + format!("bv{}", self.bits) + } +} + +/// A concrete scalar type that is neither a vector nor a lane type. +/// +/// Special types cannot be used to form vectors. +pub struct SpecialType { + tag: SpecialTypeTag, +} + +impl SpecialType { + pub fn doc(&self) -> String { + match self.tag { + SpecialTypeTag::Flag(base_types::Flag::IFlags) => String::from( + "CPU flags representing the result of an integer comparison. These flags + can be tested with an :type:`intcc` condition code.", + ), + SpecialTypeTag::Flag(base_types::Flag::FFlags) => String::from( + "CPU flags representing the result of a floating point comparison. These + flags can be tested with a :type:`floatcc` condition code.", + ), + } + } + + pub fn lane_bits(&self) -> u64 { + match self.tag { + SpecialTypeTag::Flag(_) => 0, + } + } + + pub fn name(&self) -> String { + self.tag.name() + } + + pub fn number(&self) -> u8 { + self.tag.number() + } +} + +pub enum SpecialTypeTag { + Flag(base_types::Flag), +} + +impl SpecialTypeTag { + pub fn name(&self) -> String { + match self { + SpecialTypeTag::Flag(f) => format!("{}", f), + } + } + + pub fn number(&self) -> u8 { + match self { + SpecialTypeTag::Flag(f) => f.number(), + } + } +} + +pub struct SpecialTypeIterator { + flag_iter: base_types::FlagIterator, +} + +impl SpecialTypeIterator { + fn new() -> Self { + Self { + flag_iter: base_types::FlagIterator::new(), + } + } +} + +impl Iterator for SpecialTypeIterator { + type Item = ValueType; + fn next(&mut self) -> Option { + if let Some(f) = self.flag_iter.next() { + let next = SpecialType { + tag: SpecialTypeTag::Flag(f), + }; + Some(ValueType::Special(next)) + } else { + None + } + } +} diff --git a/lib/codegen-meta/src/error.rs b/lib/codegen-meta/src/error.rs new file mode 100644 index 000000000..4c313732d --- /dev/null +++ b/lib/codegen-meta/src/error.rs @@ -0,0 +1,47 @@ +use std::fmt; +use std::io; + +/// An error that occurred when the cranelift_codegen_meta crate was generating +/// source files for the cranelift_codegen crate. +#[derive(Debug)] +pub struct Error { + inner: Box, +} + +impl Error { + /// Create a new error object with the given message. + pub fn with_msg>(msg: S) -> Error { + Error { + inner: Box::new(ErrorInner::Msg(msg.into())), + } + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.inner) + } +} + +impl From for Error { + fn from(e: io::Error) -> Self { + Error { + inner: Box::new(ErrorInner::IoError(e)), + } + } +} + +#[derive(Debug)] +enum ErrorInner { + Msg(String), + IoError(io::Error), +} + +impl fmt::Display for ErrorInner { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + ErrorInner::Msg(s) => write!(f, "{}", s), + ErrorInner::IoError(e) => write!(f, "{}", e), + } + } +} diff --git a/lib/codegen-meta/src/gen_build_deps.rs b/lib/codegen-meta/src/gen_build_deps.rs new file mode 100644 index 000000000..a267bc664 --- /dev/null +++ b/lib/codegen-meta/src/gen_build_deps.rs @@ -0,0 +1,48 @@ +//! Generate build dependencies for Cargo. +//! +//! The `build.rs` script is invoked by cargo when building lib/codegen to +//! generate Rust code from the instruction descriptions. Cargo needs to know when +//! it is necessary to rerun the build script. +//! +//! If the build script outputs lines of the form: +//! cargo:rerun-if-changed=/path/to/file +//! +//! cargo will rerun the build script when those files have changed since the last +//! build. + +use error; + +use std::fs; +use std::path; + +/// Recursively find all interesting source files and directories in the +/// directory tree starting at `dir`. Yield a path to each file. +fn source_files(dir: &path::PathBuf) -> Result, error::Error> { + let mut files = Vec::new(); + if dir.is_dir() { + for entry in fs::read_dir(&dir)? { + let entry = entry?; + let path = entry.path(); + if path.is_dir() { + let mut child_dir_files = source_files(&path)?; + files.append(&mut child_dir_files); + } else if let Some(ext) = path.extension() { + if ext == "rs" { + files.push(path.to_str().unwrap().to_string()); + } + } + } + } + Ok(files) +} + +/// Generate the lines of `cargo:rerun-if-changed` output, for each Rust source +/// file inside of the cranelift-codegen-meta crate. +pub fn generate(meta_dir: &path::PathBuf) -> Result<(), error::Error> { + println!("Dependencies from Rust meta language directory:"); + source_files(&meta_dir)? + .into_iter() + .for_each(|p| println!("cargo:rerun-if-changed={}", p)); + + Ok(()) +} diff --git a/lib/codegen-meta/src/gen_types.rs b/lib/codegen-meta/src/gen_types.rs new file mode 100644 index 000000000..a60034530 --- /dev/null +++ b/lib/codegen-meta/src/gen_types.rs @@ -0,0 +1,68 @@ +//! Generate sources with type info. +//! +//! This generates a `types.rs` file which is included in +//! `lib/codegen/ir/types.rs`. The file provides constant definitions for the +//! most commonly used types, including all of the scalar types. +//! +//! This ensures that Python and Rust use the same type numbering. + +use cdsl::types as cdsl_types; +use error; +use srcgen; + +/// Emit a constant definition of a single value type. +fn emit_type(ty: &cdsl_types::ValueType, fmt: &mut srcgen::Formatter) -> Result<(), error::Error> { + let name = ty.name().to_uppercase(); + let number = ty.number().ok_or_else(|| { + error::Error::with_msg(format!( + "Could not emit type `{}` which has no number.", + name + )) + })?; + + let definition = format!("pub const {}: Type = Type({:#x});\n", name, number); + + fmt.doc_comment(&ty.doc()); + fmt.line(&definition); + + Ok(()) +} + +/// Emit definition for all vector types with `bits` total size. +fn emit_vectors(bits: u64, fmt: &mut srcgen::Formatter) -> Result<(), error::Error> { + let vec_size: u64 = bits / 8; + cdsl_types::ValueType::all_lane_types() + .map(|ty| (ty, cdsl_types::ValueType::from(ty).membytes())) + .filter(|(_, lane_size)| *lane_size != 0 && *lane_size < vec_size) + .map(|(ty, lane_size)| (ty, vec_size / lane_size)) + .map(|(ty, lanes)| cdsl_types::VectorType::new(ty, lanes)) + .try_for_each(|vec| emit_type(&cdsl_types::ValueType::from(vec), fmt))?; + + Ok(()) +} + +/// Emit types using the given formatter object. +fn emit_types(fmt: &mut srcgen::Formatter) -> Result<(), error::Error> { + // Emit all of the special types, such as types for CPU flags. + cdsl_types::ValueType::all_special_types().try_for_each(|spec| emit_type(&spec, fmt))?; + + // Emit all of the lane types, such integers, floats, and booleans. + cdsl_types::ValueType::all_lane_types() + .map(cdsl_types::ValueType::from) + .try_for_each(|ty| emit_type(&ty, fmt))?; + + // Emit vector definitions for common SIMD sizes. + [64_u64, 128, 256, 512] + .into_iter() + .try_for_each(|&b| emit_vectors(b, fmt))?; + + Ok(()) +} + +/// Generate the types file. +pub fn generate(filename: &str, out_dir: &str) -> Result<(), error::Error> { + let mut fmt = srcgen::Formatter::new(); + emit_types(&mut fmt)?; + fmt.update_file(filename, out_dir)?; + Ok(()) +} diff --git a/lib/codegen-meta/src/lib.rs b/lib/codegen-meta/src/lib.rs new file mode 100644 index 000000000..7a199be9f --- /dev/null +++ b/lib/codegen-meta/src/lib.rs @@ -0,0 +1,7 @@ +pub mod error; +pub mod gen_build_deps; +pub mod gen_types; + +mod base; +mod cdsl; +mod srcgen; diff --git a/lib/codegen-meta/src/srcgen.rs b/lib/codegen-meta/src/srcgen.rs new file mode 100644 index 000000000..ef8bde89c --- /dev/null +++ b/lib/codegen-meta/src/srcgen.rs @@ -0,0 +1,315 @@ +//! Source code generator. +//! +//! The `srcgen` module contains generic helper routines and classes for +//! generating source code. + +use std::collections::{BTreeMap, HashSet}; +use std::fs; +use std::io::Write; +use std::path; + +use error; + +static SHIFTWIDTH: usize = 4; + +struct _IndentedScope { + fmt: Formatter, + after: Option, +} + +impl _IndentedScope { + fn _enter(&mut self) { + self.fmt._indent_push(); + } + + fn _exit(&mut self) { + self.fmt._indent_pop(); + if let Some(ref s) = self.after { + self.fmt.line(&s); + } + } +} + +pub struct Formatter { + indent: usize, + lines: Vec, +} + +impl Formatter { + /// Source code formatter class. Used to collect source code to be written + /// to a file, and keep track of indentation. + pub fn new() -> Formatter { + Formatter { + indent: 0, + lines: Vec::new(), + } + } + + /// Increase current indentation level by one. + pub fn _indent_push(&mut self) { + self.indent += 1; + } + + /// Decrease indentation by one level. + pub fn _indent_pop(&mut self) { + assert!(self.indent > 0, "Already at top level indentation"); + self.indent -= 1; + } + + /// Get the current whitespace indentation in the form of a String. + fn get_indent(&self) -> String { + if self.indent == 0 { + String::new() + } else { + format!("{:-1$}", " ", self.indent * SHIFTWIDTH) + } + } + + /// Get a string containing whitespace outdented one level. Used for + /// lines of code that are inside a single indented block. + fn _get_outdent(&mut self) -> String { + self._indent_push(); + let s = self.get_indent(); + self._indent_pop(); + s + } + + /// Add an indented line. + pub fn line(&mut self, contents: &str) { + let indented_line = format!("{}{}\n", self.get_indent(), contents); + self.lines.push(indented_line); + } + + /// Emit a line outdented one level. + pub fn _outdented_line(&mut self, s: &str) { + let new_line = format!("{}{}", self._get_outdent(), s); + self.lines.push(new_line); + } + + /// Write `self.lines` to a file. + pub fn update_file(&self, filename: &str, directory: &str) -> Result<(), error::Error> { + #[cfg(target_family = "windows")] + let path_str = format!("{}\\{}", directory, filename); + #[cfg(not(target_family = "windows"))] + let path_str = format!("{}/{}", directory, filename); + + let path = path::Path::new(&path_str); + let mut f = fs::File::create(path)?; + + for l in self.lines.iter().map(|l| l.as_bytes()) { + f.write_all(l)?; + } + + Ok(()) + } + + /// Return a scope object for use with a `with` statement. + /// The optional `before` and `after` parameters are surrounding lines + /// which are *not* indented. + fn _indented(&self, _before: Option<&str>, _after: Option<&str>) -> _IndentedScope { + unimplemented!(); + } + + /// Add one or more lines after stripping common indentation. + pub fn _multi_line(&mut self, s: &str) { + parse_multiline(s).into_iter().for_each(|l| self.line(&l)); + } + + /// Add a comment line. + pub fn _comment(&mut self, s: &str) { + let commented_line = format!("// {}", s); + self.line(&commented_line); + } + + /// Add a (multi-line) documentation comment. + pub fn doc_comment(&mut self, contents: &str) { + parse_multiline(contents) + .iter() + .map(|l| format!("/// {}", l)) + .for_each(|s| self.line(s.as_str())); + } + + /// Add a match expression. + fn _add_match(&mut self, _m: &_Match) { + unimplemented!(); + } +} + +/// Compute the indentation of s, or None of an empty line. +fn _indent(s: &str) -> Option { + if s.is_empty() { + None + } else { + let t = s.trim_left(); + Some(s.len() - t.len()) + } +} + +/// Given a multi-line string, split it into a sequence of lines after +/// stripping a common indentation. This is useful for strings defined with +/// doc strings. +fn parse_multiline(s: &str) -> Vec { + // Convert tabs into spaces. + let expanded_tab = format!("{:-1$}", " ", SHIFTWIDTH); + let lines: Vec = s.lines().map(|l| l.replace("\t", &expanded_tab)).collect(); + + // Determine minimum indentation, ignoring the first line. + let indent = lines + .iter() + .skip(1) + .map(|l| l.len() - l.trim_left().len()) + .filter(|&i| i > 0) + .min(); + + // Strip off leading blank lines. + let mut lines_iter = lines.iter().skip_while(|l| l.is_empty()); + let mut trimmed = Vec::with_capacity(lines.len()); + + // Remove indentation (first line is special) + if let Some(s) = lines_iter.next().map(|l| l.trim()).map(|l| l.to_string()) { + trimmed.push(s); + } + + // Remove trailing whitespace from other lines. + let mut other_lines = if let Some(indent) = indent { + lines_iter + .map(|l| &l[indent..]) + .map(|l| l.trim_right()) + .map(|l| l.to_string()) + .collect::>() + } else { + lines_iter + .map(|l| l.trim_right()) + .map(|l| l.to_string()) + .collect::>() + }; + + trimmed.append(&mut other_lines); + + // Strip off trailing blank lines. + while let Some(s) = trimmed.pop() { + if s.is_empty() { + continue; + } else { + trimmed.push(s); + break; + } + } + + trimmed +} + +/// Match formatting class. +/// +/// Match objects collect all the information needed to emit a Rust `match` +/// expression, automatically deduplicating overlapping identical arms. +/// +/// Note that this class is ignorant of Rust types, and considers two fields +/// with the same name to be equivalent. +struct _Match<'a> { + _expr: &'a str, + arms: BTreeMap<(Vec<&'a str>, &'a str), HashSet<&'a str>>, +} + +impl<'a> _Match<'a> { + /// Create a new match statemeht on `expr`. + fn _new(expr: &'a str) -> Self { + Self { + _expr: expr, + arms: BTreeMap::new(), + } + } + + /// Add an arm to the Match statement. + fn _arm(&mut self, name: &'a str, fields: Vec<&'a str>, body: &'a str) { + // let key = (fields, body); + let match_arm = self.arms.entry((fields, body)).or_insert_with(HashSet::new); + match_arm.insert(name); + } +} + +#[cfg(test)] +mod srcgen_tests { + use super::_Match; + use super::parse_multiline; + use super::Formatter; + + #[test] + fn adding_arms_works() { + let mut m = _Match::_new("x"); + m._arm("Orange", vec!["a", "b"], "some body"); + m._arm("Yellow", vec!["a", "b"], "some body"); + m._arm("Green", vec!["a", "b"], "different body"); + m._arm("Blue", vec!["x", "y"], "some body"); + assert_eq!(m.arms.len(), 3); + } + + #[test] + fn parse_multiline_works() { + let input = "\n hello\n world\n"; + let expected = vec!["hello", "world"]; + let output = parse_multiline(input); + assert_eq!(output, expected); + } + + #[test] + fn formatter_basic_example_works() { + let mut fmt = Formatter::new(); + fmt.line("Hello line 1"); + fmt._indent_push(); + fmt._comment("Nested comment"); + fmt._indent_pop(); + fmt.line("Back home again"); + let expected_lines = vec![ + "Hello line 1\n", + " // Nested comment\n", + "Back home again\n", + ]; + assert_eq!(fmt.lines, expected_lines); + } + + #[test] + fn get_indent_works() { + let mut fmt = Formatter::new(); + let expected_results = vec!["", " ", " ", ""]; + + let actual_results = Vec::with_capacity(4); + (0..3).for_each(|_| { + fmt.get_indent(); + fmt._indent_push(); + }); + (0..3).for_each(|_| fmt._indent_pop()); + fmt.get_indent(); + + actual_results + .into_iter() + .zip(expected_results.into_iter()) + .for_each(|(actual, expected): (String, &str)| assert_eq!(&actual, expected)); + } + + #[test] + fn fmt_can_add_type_to_lines() { + let mut fmt = Formatter::new(); + fmt.line(&format!("pub const {}: Type = Type({:#x});", "example", 0,)); + let expected_lines = vec!["pub const example: Type = Type(0x0);\n"]; + assert_eq!(fmt.lines, expected_lines); + } + + #[test] + fn fmt_can_add_indented_line() { + let mut fmt = Formatter::new(); + fmt.line("hello"); + fmt._indent_push(); + fmt.line("world"); + let expected_lines = vec!["hello\n", " world\n"]; + assert_eq!(fmt.lines, expected_lines); + } + + #[test] + fn fmt_can_add_doc_comments() { + let mut fmt = Formatter::new(); + fmt.doc_comment("documentation\nis\ngood"); + let expected_lines = vec!["/// documentation\n", "/// is\n", "/// good\n"]; + assert_eq!(fmt.lines, expected_lines); + } +} diff --git a/lib/codegen/Cargo.toml b/lib/codegen/Cargo.toml index aa445322f..8afcc447d 100644 --- a/lib/codegen/Cargo.toml +++ b/lib/codegen/Cargo.toml @@ -12,6 +12,7 @@ build = "build.rs" [dependencies] cranelift-entity = { path = "../entity", version = "0.15.0", default-features = false } +cranelift-codegen-meta = { path = "../codegen-meta", version = "0.15.0" } failure = { version = "0.1.1", default-features = false, features = ["derive"] } failure_derive = { version = "0.1.1", default-features = false } hashmap_core = { version = "0.1.8", optional = true } @@ -21,6 +22,9 @@ target-lexicon = { version = "0.0.3", default-features = false } # machine code. Integration tests that need external dependencies can be # accomodated in `tests`. +[build-dependencies] +cranelift-codegen-meta = { path = "../codegen-meta", version = "0.15.0" } + [features] # The "std" feature enables use of libstd. The "core" feature enables use # of some minimal std-like replacement libraries. At least one of these two diff --git a/lib/codegen/build.rs b/lib/codegen/build.rs index b5a2f5b43..f9ba9b8e4 100644 --- a/lib/codegen/build.rs +++ b/lib/codegen/build.rs @@ -18,6 +18,8 @@ // The build script expects to be run from the directory where this build.rs file lives. The // current directory is used to find the sources. +extern crate cranelift_codegen_meta as meta; + use std::env; use std::process; @@ -66,12 +68,35 @@ fn main() { .arg("-B") .arg(build_script) .arg("--out-dir") - .arg(out_dir) + .arg(out_dir.clone()) .status() .expect("Failed to launch second-level build script; is python installed?"); if !status.success() { process::exit(status.code().unwrap()); } + + // DEVELOPMENT: + // ------------------------------------------------------------------------ + // Now that the Python build process is complete, generate files that are + // emitted by the `cretonne_codegen_meta` crate. + // ------------------------------------------------------------------------ + + // Identify the directory of the Rust codegen-meta external crate. + let rust_meta_dir = crate_dir + .parent() + .map(|d| d.join("codegen-meta")) + .unwrap_or_else(|| { + eprintln!("Error: Could not find path to lib/codegen-meta crate."); + process::exit(1); + }); + + if let Err(err) = meta::gen_types::generate("new_types.rs", &out_dir) { + eprintln!("Error: {}", err); + process::exit(1); + } else if let Err(err) = meta::gen_build_deps::generate(&rust_meta_dir) { + eprintln!("Error: {}", err); + process::exit(1); + } } fn identify_python() -> &'static str { From 4e3205a189827fb8f71d2e9c6d30fe8f4c95449b Mon Sep 17 00:00:00 2001 From: data-pup Date: Tue, 17 Jul 2018 07:26:24 -0400 Subject: [PATCH 02/26] Replace 'Cretonne' in comments. --- lib/codegen-meta/src/base/mod.rs | 2 +- lib/codegen-meta/src/base/types.rs | 2 +- lib/codegen-meta/src/cdsl/mod.rs | 4 ++-- lib/codegen-meta/src/cdsl/types.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/codegen-meta/src/base/mod.rs b/lib/codegen-meta/src/base/mod.rs index a72bc6bc0..a75614d9c 100644 --- a/lib/codegen-meta/src/base/mod.rs +++ b/lib/codegen-meta/src/base/mod.rs @@ -1,3 +1,3 @@ -//! Definitions for the base Cretonne language. +//! Definitions for the base Cranelift language. pub mod types; diff --git a/lib/codegen-meta/src/base/types.rs b/lib/codegen-meta/src/base/types.rs index c6f1ad160..0598eea0c 100644 --- a/lib/codegen-meta/src/base/types.rs +++ b/lib/codegen-meta/src/base/types.rs @@ -1,4 +1,4 @@ -//! This module predefines all the Cretonne scalar types. +//! This module predefines all the Cranelift scalar types. use std::fmt; diff --git a/lib/codegen-meta/src/cdsl/mod.rs b/lib/codegen-meta/src/cdsl/mod.rs index 7926acfc7..d1297fcff 100644 --- a/lib/codegen-meta/src/cdsl/mod.rs +++ b/lib/codegen-meta/src/cdsl/mod.rs @@ -1,6 +1,6 @@ -//! Cretonne DSL classes. +//! Cranelift DSL classes. //! -//! This module defines the classes that are used to define Cretonne +//! This module defines the classes that are used to define Cranelift //! instructions and other entitties. pub mod types; diff --git a/lib/codegen-meta/src/cdsl/types.rs b/lib/codegen-meta/src/cdsl/types.rs index 8315440f6..8e597e251 100644 --- a/lib/codegen-meta/src/cdsl/types.rs +++ b/lib/codegen-meta/src/cdsl/types.rs @@ -1,4 +1,4 @@ -//! Cretonne ValueType hierarchy +//! Cranelift ValueType hierarchy // Temporary disabled: Unused at the moment. // use std::collections::HashMap; From 565516b63a523085a45b54b740ac57f5a24dfe0d Mon Sep 17 00:00:00 2001 From: data-pup Date: Tue, 17 Jul 2018 07:29:36 -0400 Subject: [PATCH 03/26] Prevent iterator overflow. --- lib/codegen-meta/src/base/types.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/codegen-meta/src/base/types.rs b/lib/codegen-meta/src/base/types.rs index 0598eea0c..60171f288 100644 --- a/lib/codegen-meta/src/base/types.rs +++ b/lib/codegen-meta/src/base/types.rs @@ -43,7 +43,7 @@ impl Bool { } pub struct BoolIterator { - index: usize, + index: u8, } impl BoolIterator { @@ -61,7 +61,7 @@ impl Iterator for BoolIterator { 2 => Some(Bool::B16), 3 => Some(Bool::B32), 4 => Some(Bool::B64), - _ => None, + _ => return None, }; self.index += 1; res @@ -95,7 +95,7 @@ impl Int { } pub struct IntIterator { - index: usize, + index: u8, } impl IntIterator { @@ -112,7 +112,7 @@ impl Iterator for IntIterator { 1 => Some(Int::I16), 2 => Some(Int::I32), 3 => Some(Int::I64), - _ => None, + _ => return None, }; self.index += 1; res @@ -139,7 +139,7 @@ impl Float { /// Iterator through the variants of the Float enum. pub struct FloatIterator { - index: usize, + index: u8, } impl FloatIterator { @@ -154,7 +154,7 @@ impl Iterator for FloatIterator { let res = match self.index { 0 => Some(Float::F32), 1 => Some(Float::F64), - _ => None, + _ => return None, }; self.index += 1; res @@ -197,7 +197,7 @@ impl fmt::Display for Flag { /// Iterator through the variants of the Flag enum. pub struct FlagIterator { - index: usize, + index: u8, } impl FlagIterator { @@ -212,7 +212,7 @@ impl Iterator for FlagIterator { let res = match self.index { 0 => Some(Flag::IFlags), 1 => Some(Flag::FFlags), - _ => None, + _ => return None, }; self.index += 1; res From 4944d8c49f2d52cf574416327fb9f737855b482b Mon Sep 17 00:00:00 2001 From: data-pup Date: Tue, 17 Jul 2018 08:30:49 -0400 Subject: [PATCH 04/26] 1.25.0 compatibility changes. --- lib/codegen-meta/src/base/types.rs | 15 +-------- lib/codegen-meta/src/cdsl/types.rs | 49 +++++++++++++++--------------- lib/codegen-meta/src/error.rs | 4 +-- lib/codegen-meta/src/gen_types.rs | 24 +++++++++------ 4 files changed, 41 insertions(+), 51 deletions(-) diff --git a/lib/codegen-meta/src/base/types.rs b/lib/codegen-meta/src/base/types.rs index 60171f288..9ba323f44 100644 --- a/lib/codegen-meta/src/base/types.rs +++ b/lib/codegen-meta/src/base/types.rs @@ -161,10 +161,10 @@ impl Iterator for FloatIterator { } } -#[derive(Debug, Clone, Copy, Eq, PartialEq)] /// A type representing CPU flags. /// /// Flags can't be stored in memory. +#[derive(Debug, Clone, Copy, Eq, PartialEq)] pub enum Flag { /// CPU flags from an integer comparison. IFlags, @@ -182,19 +182,6 @@ impl Flag { } } -impl fmt::Display for Flag { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "{}", - match self { - Flag::IFlags => "iflags", - Flag::FFlags => "fflags", - } - ) - } -} - /// Iterator through the variants of the Flag enum. pub struct FlagIterator { index: u8, diff --git a/lib/codegen-meta/src/cdsl/types.rs b/lib/codegen-meta/src/cdsl/types.rs index 8e597e251..6c83e921a 100644 --- a/lib/codegen-meta/src/cdsl/types.rs +++ b/lib/codegen-meta/src/cdsl/types.rs @@ -34,27 +34,27 @@ impl ValueType { /// Return a string containing the documentation comment for this type. pub fn doc(&self) -> String { match self { - ValueType::BV(b) => b.doc(), - ValueType::Lane(l) => l.doc(), - ValueType::Special(s) => s.doc(), - ValueType::Vector(v) => v.doc(), + &ValueType::BV(ref b) => b.doc(), + &ValueType::Lane(l) => l.doc(), + &ValueType::Special(s) => s.doc(), + &ValueType::Vector(ref v) => v.doc(), } } /// Return the number of bits in a lane. pub fn lane_bits(&self) -> u64 { match self { - ValueType::BV(b) => b.lane_bits(), - ValueType::Lane(l) => l.lane_bits(), - ValueType::Special(s) => s.lane_bits(), - ValueType::Vector(v) => v.lane_bits(), + &ValueType::BV(ref b) => b.lane_bits(), + &ValueType::Lane(l) => l.lane_bits(), + &ValueType::Special(s) => s.lane_bits(), + &ValueType::Vector(ref v) => v.lane_bits(), } } /// Return the number of lanes. pub fn lane_count(&self) -> u64 { match self { - ValueType::Vector(v) => v.lane_count(), + &ValueType::Vector(ref v) => v.lane_count(), _ => 1, } } @@ -67,20 +67,20 @@ impl ValueType { /// Get the name of this type. pub fn name(&self) -> String { match self { - ValueType::BV(b) => b.name(), - ValueType::Lane(l) => l.name(), - ValueType::Special(s) => s.name(), - ValueType::Vector(v) => v.name(), + &ValueType::BV(ref b) => b.name(), + &ValueType::Lane(l) => l.name(), + &ValueType::Special(s) => s.name(), + &ValueType::Vector(ref v) => v.name(), } } /// Find the unique number associated with this type. pub fn number(&self) -> Option { match self { - ValueType::BV(_) => None, - ValueType::Lane(l) => Some(l.number()), - ValueType::Special(s) => Some(s.number()), - ValueType::Vector(v) => Some(v.number()), + &ValueType::BV(_) => None, + &ValueType::Lane(l) => Some(l.number()), + &ValueType::Special(s) => Some(s.number()), + &ValueType::Vector(ref v) => Some(v.number()), } } @@ -330,6 +330,7 @@ impl BVType { /// A concrete scalar type that is neither a vector nor a lane type. /// /// Special types cannot be used to form vectors. +#[derive(Debug, Clone, Copy)] pub struct SpecialType { tag: SpecialTypeTag, } @@ -355,7 +356,10 @@ impl SpecialType { } pub fn name(&self) -> String { - self.tag.name() + match self.tag { + SpecialTypeTag::Flag(base_types::Flag::IFlags) => "iflags".to_string(), + SpecialTypeTag::Flag(base_types::Flag::FFlags) => "fflags".to_string(), + } } pub fn number(&self) -> u8 { @@ -363,19 +367,14 @@ impl SpecialType { } } +#[derive(Debug, Clone, Copy)] pub enum SpecialTypeTag { Flag(base_types::Flag), } impl SpecialTypeTag { - pub fn name(&self) -> String { - match self { - SpecialTypeTag::Flag(f) => format!("{}", f), - } - } - pub fn number(&self) -> u8 { - match self { + match *self { SpecialTypeTag::Flag(f) => f.number(), } } diff --git a/lib/codegen-meta/src/error.rs b/lib/codegen-meta/src/error.rs index 4c313732d..595a5c355 100644 --- a/lib/codegen-meta/src/error.rs +++ b/lib/codegen-meta/src/error.rs @@ -40,8 +40,8 @@ enum ErrorInner { impl fmt::Display for ErrorInner { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - ErrorInner::Msg(s) => write!(f, "{}", s), - ErrorInner::IoError(e) => write!(f, "{}", e), + &ErrorInner::Msg(ref s) => write!(f, "{}", s), + &ErrorInner::IoError(ref e) => write!(f, "{}", e), } } } diff --git a/lib/codegen-meta/src/gen_types.rs b/lib/codegen-meta/src/gen_types.rs index a60034530..215d2bce4 100644 --- a/lib/codegen-meta/src/gen_types.rs +++ b/lib/codegen-meta/src/gen_types.rs @@ -31,12 +31,14 @@ fn emit_type(ty: &cdsl_types::ValueType, fmt: &mut srcgen::Formatter) -> Result< /// Emit definition for all vector types with `bits` total size. fn emit_vectors(bits: u64, fmt: &mut srcgen::Formatter) -> Result<(), error::Error> { let vec_size: u64 = bits / 8; - cdsl_types::ValueType::all_lane_types() + for vec in cdsl_types::ValueType::all_lane_types() .map(|ty| (ty, cdsl_types::ValueType::from(ty).membytes())) - .filter(|(_, lane_size)| *lane_size != 0 && *lane_size < vec_size) + .filter(|&(_, lane_size)| lane_size != 0 && lane_size < vec_size) .map(|(ty, lane_size)| (ty, vec_size / lane_size)) .map(|(ty, lanes)| cdsl_types::VectorType::new(ty, lanes)) - .try_for_each(|vec| emit_type(&cdsl_types::ValueType::from(vec), fmt))?; + { + emit_type(&cdsl_types::ValueType::from(vec), fmt)?; + } Ok(()) } @@ -44,17 +46,19 @@ fn emit_vectors(bits: u64, fmt: &mut srcgen::Formatter) -> Result<(), error::Err /// Emit types using the given formatter object. fn emit_types(fmt: &mut srcgen::Formatter) -> Result<(), error::Error> { // Emit all of the special types, such as types for CPU flags. - cdsl_types::ValueType::all_special_types().try_for_each(|spec| emit_type(&spec, fmt))?; + for spec in cdsl_types::ValueType::all_special_types() { + emit_type(&spec, fmt)?; + } // Emit all of the lane types, such integers, floats, and booleans. - cdsl_types::ValueType::all_lane_types() - .map(cdsl_types::ValueType::from) - .try_for_each(|ty| emit_type(&ty, fmt))?; + for ty in cdsl_types::ValueType::all_lane_types().map(cdsl_types::ValueType::from) { + emit_type(&ty, fmt)?; + } // Emit vector definitions for common SIMD sizes. - [64_u64, 128, 256, 512] - .into_iter() - .try_for_each(|&b| emit_vectors(b, fmt))?; + for vec_size in [64_u64, 128, 256, 512].iter() { + emit_vectors(*vec_size, fmt)?; + } Ok(()) } From 69f34e0a531335441fdb2c311c1d5672337e2f4a Mon Sep 17 00:00:00 2001 From: data-pup Date: Tue, 17 Jul 2018 08:58:59 -0400 Subject: [PATCH 05/26] Implemented debug traits for type variants. --- lib/codegen-meta/src/base/types.rs | 2 -- lib/codegen-meta/src/cdsl/types.rs | 57 +++++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/lib/codegen-meta/src/base/types.rs b/lib/codegen-meta/src/base/types.rs index 9ba323f44..7ec9d2906 100644 --- a/lib/codegen-meta/src/base/types.rs +++ b/lib/codegen-meta/src/base/types.rs @@ -1,7 +1,5 @@ //! This module predefines all the Cranelift scalar types. -use std::fmt; - // Numbering scheme for value types: // // 0: Void diff --git a/lib/codegen-meta/src/cdsl/types.rs b/lib/codegen-meta/src/cdsl/types.rs index 6c83e921a..e549adf36 100644 --- a/lib/codegen-meta/src/cdsl/types.rs +++ b/lib/codegen-meta/src/cdsl/types.rs @@ -3,6 +3,8 @@ // Temporary disabled: Unused at the moment. // use std::collections::HashMap; +use std::fmt; + use base::types as base_types; static _RUST_NAME_PREFIX: &'static str = "ir::types::"; @@ -102,6 +104,27 @@ impl ValueType { } } +impl fmt::Debug for ValueType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "{}", + match self { + &ValueType::BV(ref b) => format!("{:?}", b), + &ValueType::Lane(l) => format!("{:?}", l), + &ValueType::Special(s) => format!("{:?}", s), + &ValueType::Vector(ref v) => format!("{:?}", v), + } + ) + } +} + +impl fmt::Display for ValueType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.name()) + } +} + /// Create a ValueType from a given bitvector type. impl From for ValueType { fn from(bv: BVType) -> Self { @@ -131,7 +154,7 @@ impl From for ValueType { } /// A concrete scalar type that can appear as a vector lane too. -#[derive(Debug, Clone, Copy)] +#[derive(Clone, Copy)] pub struct LaneType { bits: u64, tag: LaneTypeTag, @@ -185,6 +208,21 @@ impl LaneType { } } +impl fmt::Debug for LaneType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let inner_msg = format!("bits={}", self.lane_bits()); + write!( + f, + "{}", + match self.tag { + LaneTypeTag::BoolType(_) => format!("BoolType({})", inner_msg), + LaneTypeTag::FloatType(_) => format!("FloatType({})", inner_msg), + LaneTypeTag::IntType(_) => format!("IntType({})", inner_msg), + } + ) + } +} + /// Create a LaneType from a given bool variant. impl From for LaneType { fn from(b: base_types::Bool) -> Self { @@ -300,6 +338,17 @@ impl VectorType { } } +impl fmt::Debug for VectorType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "VectorType(base={}, lanes={})", + self.base.name(), + self.lane_count() + ) + } +} + /// A flat bitvector type. Used for semantics description only. pub struct BVType { bits: u64, @@ -327,6 +376,12 @@ impl BVType { } } +impl fmt::Debug for BVType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "BVType(bits={})", self.lane_bits()) + } +} + /// A concrete scalar type that is neither a vector nor a lane type. /// /// Special types cannot be used to form vectors. From 61378a84d8740e30f1db6fb94f200b34217fe458 Mon Sep 17 00:00:00 2001 From: data-pup Date: Tue, 17 Jul 2018 09:02:34 -0400 Subject: [PATCH 06/26] Added consistent comments. --- lib/codegen-meta/src/cdsl/types.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/codegen-meta/src/cdsl/types.rs b/lib/codegen-meta/src/cdsl/types.rs index e549adf36..7190973d4 100644 --- a/lib/codegen-meta/src/cdsl/types.rs +++ b/lib/codegen-meta/src/cdsl/types.rs @@ -306,6 +306,7 @@ impl VectorType { VectorType { base, lanes } } + /// Return a string containing the documentation comment for this vector type. pub fn doc(&self) -> String { format!( "A SIMD vector with {} lanes containing a `{}` each.", @@ -314,12 +315,12 @@ impl VectorType { ) } - /// Get the name of this type. + /// Get the name of this vector type. pub fn name(&self) -> String { format!("{}X{}", self.base.name(), self.lanes,) } - /// Find the unique number associated with this type. + /// Find the unique number associated with this vector type. pub fn number(&self) -> u8 { let b = f64::from(self.base.number()); let l = (self.lanes as f64).log2(); @@ -391,6 +392,7 @@ pub struct SpecialType { } impl SpecialType { + /// Return a string containing the documentation comment for this special type. pub fn doc(&self) -> String { match self.tag { SpecialTypeTag::Flag(base_types::Flag::IFlags) => String::from( @@ -404,12 +406,14 @@ impl SpecialType { } } + /// Return the number of bits in a lane. pub fn lane_bits(&self) -> u64 { match self.tag { SpecialTypeTag::Flag(_) => 0, } } + /// Get the name of this special type. pub fn name(&self) -> String { match self.tag { SpecialTypeTag::Flag(base_types::Flag::IFlags) => "iflags".to_string(), @@ -417,6 +421,7 @@ impl SpecialType { } } + /// Find the unique number associated with this special type. pub fn number(&self) -> u8 { self.tag.number() } From 194ec5e78e1f666e77bc68b8b96d9d3dab102079 Mon Sep 17 00:00:00 2001 From: data-pup Date: Tue, 17 Jul 2018 09:06:06 -0400 Subject: [PATCH 07/26] Cleaned up a loop via clippy fix. --- lib/codegen-meta/src/gen_types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codegen-meta/src/gen_types.rs b/lib/codegen-meta/src/gen_types.rs index 215d2bce4..520120ffa 100644 --- a/lib/codegen-meta/src/gen_types.rs +++ b/lib/codegen-meta/src/gen_types.rs @@ -56,7 +56,7 @@ fn emit_types(fmt: &mut srcgen::Formatter) -> Result<(), error::Error> { } // Emit vector definitions for common SIMD sizes. - for vec_size in [64_u64, 128, 256, 512].iter() { + for vec_size in &[64_u64, 128, 256, 512] { emit_vectors(*vec_size, fmt)?; } From 2f42b13b1ad93047c49e535f05e58fa8123f09a6 Mon Sep 17 00:00:00 2001 From: data-pup Date: Tue, 17 Jul 2018 15:43:16 -0400 Subject: [PATCH 08/26] Added new license to codegen-meta Cargo.toml --- lib/codegen-meta/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codegen-meta/Cargo.toml b/lib/codegen-meta/Cargo.toml index e81883a2f..1a702ed04 100644 --- a/lib/codegen-meta/Cargo.toml +++ b/lib/codegen-meta/Cargo.toml @@ -3,7 +3,7 @@ name = "cranelift-codegen-meta" authors = ["The Cranelift Project Developers"] version = "0.15.0" description = "DSL for cranelift-codegen code generator library" -license = "Apache-2.0" +license = "Apache-2.0 WITH LLVM-exception" documentation = "https://cranelift.readthedocs.io/" repository = "https://github.com/CraneStation/cranelift" keywords = ["compile", "compiler", "jit"] From 9d90806c04614982d51d6640b27e38d6877de75b Mon Sep 17 00:00:00 2001 From: data-pup Date: Tue, 17 Jul 2018 15:43:44 -0400 Subject: [PATCH 09/26] Edited lane type iterator `next` method. --- lib/codegen-meta/src/cdsl/types.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/codegen-meta/src/cdsl/types.rs b/lib/codegen-meta/src/cdsl/types.rs index 7190973d4..d60fcc2d7 100644 --- a/lib/codegen-meta/src/cdsl/types.rs +++ b/lib/codegen-meta/src/cdsl/types.rs @@ -279,12 +279,12 @@ impl LaneTypeIterator { impl Iterator for LaneTypeIterator { type Item = LaneType; fn next(&mut self) -> Option { - if let b @ Some(_) = self.bool_iter.next() { - b.map(LaneType::from) - } else if let i @ Some(_) = self.int_iter.next() { - i.map(LaneType::from) - } else if let f @ Some(_) = self.float_iter.next() { - f.map(LaneType::from) + if let Some(b) = self.bool_iter.next() { + Some(LaneType::from(b)) + } else if let Some(i) = self.int_iter.next() { + Some(LaneType::from(i)) + } else if let Some(f) = self.float_iter.next() { + Some(LaneType::from(f)) } else { None } From 8842b28029e7ed98e85de1802c7a4af3650203ed Mon Sep 17 00:00:00 2001 From: data-pup Date: Tue, 17 Jul 2018 15:56:13 -0400 Subject: [PATCH 10/26] Removed functions that are not needed in Rust, and edited desc. --- lib/codegen-meta/Cargo.toml | 2 +- lib/codegen-meta/src/cdsl/mod.rs | 39 -------------------------------- 2 files changed, 1 insertion(+), 40 deletions(-) diff --git a/lib/codegen-meta/Cargo.toml b/lib/codegen-meta/Cargo.toml index 1a702ed04..9d75e91ce 100644 --- a/lib/codegen-meta/Cargo.toml +++ b/lib/codegen-meta/Cargo.toml @@ -2,7 +2,7 @@ name = "cranelift-codegen-meta" authors = ["The Cranelift Project Developers"] version = "0.15.0" -description = "DSL for cranelift-codegen code generator library" +description = "Metaprogram for cranelift-codegen code generator library" license = "Apache-2.0 WITH LLVM-exception" documentation = "https://cranelift.readthedocs.io/" repository = "https://github.com/CraneStation/cranelift" diff --git a/lib/codegen-meta/src/cdsl/mod.rs b/lib/codegen-meta/src/cdsl/mod.rs index d1297fcff..8f087a7c3 100644 --- a/lib/codegen-meta/src/cdsl/mod.rs +++ b/lib/codegen-meta/src/cdsl/mod.rs @@ -26,52 +26,13 @@ fn _camel_case(s: &str) -> String { output_chars } -/// Check if `x` is a power of two. -fn _is_power_of_two(x: u8) -> bool { - x > 0 && x & (x - 1) == 0 -} - -/// Compute the next power of two that is greater than `x`. -fn _next_power_of_two(x: u8) -> u8 { - let mut s = 1; - let mut res = x; - while res & (res + 1) != 0 { - res |= res >> s; - s *= 2; - } - - res + 1 -} - #[cfg(test)] mod tests { use super::_camel_case as camel_case; - use super::_is_power_of_two as is_power_of_two; - use super::_next_power_of_two as next_power_of_two; #[test] fn camel_case_works() { assert_eq!(camel_case("x"), "X"); assert_eq!(camel_case("camel_case"), "CamelCase"); } - - #[test] - fn is_power_of_two_works() { - assert_eq!(is_power_of_two(1), true); - assert_eq!(is_power_of_two(2), true); - assert_eq!(is_power_of_two(4), true); - assert_eq!(is_power_of_two(8), true); - - assert_eq!(is_power_of_two(3), false); - assert_eq!(is_power_of_two(7), false); - } - - #[test] - fn next_power_of_two_works() { - assert_eq!(next_power_of_two(0), 1); - assert_eq!(next_power_of_two(1), 2); - assert_eq!(next_power_of_two(2), 4); - assert_eq!(next_power_of_two(3), 4); - assert_eq!(next_power_of_two(4), 8); - } } From b9a1835735ea14cdfa1817e9a2b1ed2ef42da4bf Mon Sep 17 00:00:00 2001 From: data-pup Date: Tue, 17 Jul 2018 17:33:09 -0400 Subject: [PATCH 11/26] Debug trait derived for valuetype. --- lib/codegen-meta/src/cdsl/types.rs | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/lib/codegen-meta/src/cdsl/types.rs b/lib/codegen-meta/src/cdsl/types.rs index d60fcc2d7..f107c27ab 100644 --- a/lib/codegen-meta/src/cdsl/types.rs +++ b/lib/codegen-meta/src/cdsl/types.rs @@ -15,6 +15,7 @@ static _RUST_NAME_PREFIX: &'static str = "ir::types::"; /// /// All SSA values have a type that is described by an instance of `ValueType` /// or one of its subclasses. +#[derive(Debug)] pub enum ValueType { BV(BVType), Lane(LaneType), @@ -104,21 +105,6 @@ impl ValueType { } } -impl fmt::Debug for ValueType { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "{}", - match self { - &ValueType::BV(ref b) => format!("{:?}", b), - &ValueType::Lane(l) => format!("{:?}", l), - &ValueType::Special(s) => format!("{:?}", s), - &ValueType::Vector(ref v) => format!("{:?}", v), - } - ) - } -} - impl fmt::Display for ValueType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.name()) From ebed1c9e18fa92f6699744fbe3e9511062694ef4 Mon Sep 17 00:00:00 2001 From: data-pup Date: Tue, 17 Jul 2018 17:43:05 -0400 Subject: [PATCH 12/26] Added comments for iterator types in the base types submodule. --- lib/codegen-meta/src/base/types.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/codegen-meta/src/base/types.rs b/lib/codegen-meta/src/base/types.rs index 7ec9d2906..86c749cb2 100644 --- a/lib/codegen-meta/src/base/types.rs +++ b/lib/codegen-meta/src/base/types.rs @@ -40,6 +40,7 @@ impl Bool { } } +/// This provides an iterator through all of the supported bool variants. pub struct BoolIterator { index: u8, } @@ -92,6 +93,7 @@ impl Int { } } +/// This provides an iterator through all of the supported int variants. pub struct IntIterator { index: u8, } @@ -146,6 +148,7 @@ impl FloatIterator { } } +/// This provides an iterator through all of the supported float variants. impl Iterator for FloatIterator { type Item = Float; fn next(&mut self) -> Option { From 7c39c339c203a60bb53a59ca420777b6cceb7707 Mon Sep 17 00:00:00 2001 From: data-pup Date: Tue, 17 Jul 2018 17:53:34 -0400 Subject: [PATCH 13/26] Numbering is now handled in the cdsl/types.rs file. --- lib/codegen-meta/src/base/types.rs | 52 ------------------------------ lib/codegen-meta/src/cdsl/types.rs | 28 +++++++++++++--- 2 files changed, 24 insertions(+), 56 deletions(-) diff --git a/lib/codegen-meta/src/base/types.rs b/lib/codegen-meta/src/base/types.rs index 86c749cb2..793424a93 100644 --- a/lib/codegen-meta/src/base/types.rs +++ b/lib/codegen-meta/src/base/types.rs @@ -1,16 +1,5 @@ //! This module predefines all the Cranelift scalar types. -// Numbering scheme for value types: -// -// 0: Void -// 0x01-0x6f: Special types -// 0x70-0x7f: Lane types -// 0x80-0xff: Vector types -// -// Vector types are encoded with the lane type in the low 4 bits and log2(lanes) -// in the high 4 bits, giving a range of 2-256 lanes. -static LANE_BASE: u8 = 0x70; - #[derive(Debug, Clone, Copy, Eq, PartialEq)] pub enum Bool { /// 1-bit bool. @@ -25,21 +14,6 @@ pub enum Bool { B64 = 64, } -impl Bool { - /// Get the number of a boolean variant. - pub fn number(self) -> u8 { - let offset = match self { - Bool::B1 => 0, - Bool::B8 => 1, - Bool::B16 => 2, - Bool::B32 => 3, - Bool::B64 => 4, - }; - - LANE_BASE + offset - } -} - /// This provides an iterator through all of the supported bool variants. pub struct BoolIterator { index: u8, @@ -79,20 +53,6 @@ pub enum Int { I64 = 64, } -impl Int { - /// Get the number of an integer variant. - pub fn number(self) -> u8 { - let offset = 5 + match self { - Int::I8 => 0, - Int::I16 => 1, - Int::I32 => 2, - Int::I64 => 3, - }; - - LANE_BASE + offset - } -} - /// This provides an iterator through all of the supported int variants. pub struct IntIterator { index: u8, @@ -125,18 +85,6 @@ pub enum Float { F64 = 64, } -impl Float { - /// Get the number of a float variant. - pub fn number(self) -> u8 { - let offset = 9 + match self { - Float::F32 => 0, - Float::F64 => 1, - }; - - LANE_BASE + offset - } -} - /// Iterator through the variants of the Float enum. pub struct FloatIterator { index: u8, diff --git a/lib/codegen-meta/src/cdsl/types.rs b/lib/codegen-meta/src/cdsl/types.rs index f107c27ab..3fc5e6ad8 100644 --- a/lib/codegen-meta/src/cdsl/types.rs +++ b/lib/codegen-meta/src/cdsl/types.rs @@ -7,6 +7,18 @@ use std::fmt; use base::types as base_types; +// Numbering scheme for value types: +// +// 0: Void +// 0x01-0x6f: Special types +// 0x70-0x7f: Lane types +// 0x80-0xff: Vector types +// +// Vector types are encoded with the lane type in the low 4 bits and log2(lanes) +// in the high 4 bits, giving a range of 2-256 lanes. +static LANE_BASE: u8 = 0x70; + +// Rust name prefix used for the `rust_name` method. static _RUST_NAME_PREFIX: &'static str = "ir::types::"; // ValueType variants (i8, i32, ...) are provided in `base::types.rs`. @@ -186,10 +198,18 @@ impl LaneType { /// Find the unique number associated with this lane type. pub fn number(&self) -> u8 { - match self.tag { - LaneTypeTag::BoolType(b) => b.number(), - LaneTypeTag::FloatType(f) => f.number(), - LaneTypeTag::IntType(i) => i.number(), + LANE_BASE + match self.tag { + LaneTypeTag::BoolType(base_types::Bool::B1) => 0, + LaneTypeTag::BoolType(base_types::Bool::B8) => 1, + LaneTypeTag::BoolType(base_types::Bool::B16) => 2, + LaneTypeTag::BoolType(base_types::Bool::B32) => 3, + LaneTypeTag::BoolType(base_types::Bool::B64) => 4, + LaneTypeTag::IntType(base_types::Int::I8) => 5, + LaneTypeTag::IntType(base_types::Int::I16) => 6, + LaneTypeTag::IntType(base_types::Int::I32) => 7, + LaneTypeTag::IntType(base_types::Int::I64) => 8, + LaneTypeTag::FloatType(base_types::Float::F32) => 9, + LaneTypeTag::FloatType(base_types::Float::F64) => 10, } } } From bba565b66269a5fccd462493396bfe5ed96881dc Mon Sep 17 00:00:00 2001 From: data-pup Date: Tue, 17 Jul 2018 18:46:31 -0400 Subject: [PATCH 14/26] Moved type number logic into cdsl/types. --- lib/codegen-meta/src/cdsl/types.rs | 87 ++++++++++++++---------------- 1 file changed, 39 insertions(+), 48 deletions(-) diff --git a/lib/codegen-meta/src/cdsl/types.rs b/lib/codegen-meta/src/cdsl/types.rs index 3fc5e6ad8..3637652e8 100644 --- a/lib/codegen-meta/src/cdsl/types.rs +++ b/lib/codegen-meta/src/cdsl/types.rs @@ -153,63 +153,68 @@ impl From for ValueType { /// A concrete scalar type that can appear as a vector lane too. #[derive(Clone, Copy)] -pub struct LaneType { - bits: u64, - tag: LaneTypeTag, +pub enum LaneType { + BoolType(base_types::Bool), + FloatType(base_types::Float), + IntType(base_types::Int), } impl LaneType { /// Return a string containing the documentation comment for this lane type. pub fn doc(&self) -> String { - match self.tag { - LaneTypeTag::BoolType(_) => format!("A boolean type with {} bits.", self.bits), - LaneTypeTag::FloatType(base_types::Float::F32) => String::from( + match self { + LaneType::BoolType(_) => format!("A boolean type with {} bits.", self.lane_bits()), + LaneType::FloatType(base_types::Float::F32) => String::from( "A 32-bit floating point type represented in the IEEE 754-2008 *binary32* interchange format. This corresponds to the :c:type:`float` type in most C implementations.", ), - LaneTypeTag::FloatType(base_types::Float::F64) => String::from( + LaneType::FloatType(base_types::Float::F64) => String::from( "A 64-bit floating point type represented in the IEEE 754-2008 *binary64* interchange format. This corresponds to the :c:type:`double` type in most C implementations.", ), - LaneTypeTag::IntType(_) if self.bits < 32 => format!( + LaneType::IntType(_) if self.lane_bits() < 32 => format!( "An integer type with {} bits. WARNING: arithmetic on {}bit integers is incomplete", - self.bits, self.bits + self.lane_bits(), self.lane_bits() ), - LaneTypeTag::IntType(_) => format!("An integer type with {} bits.", self.bits), + LaneType::IntType(_) => format!("An integer type with {} bits.", self.lane_bits()), } } /// Return the number of bits in a lane. pub fn lane_bits(&self) -> u64 { - self.bits + match self { + LaneType::BoolType(b) => *b as u64, + LaneType::FloatType(f) => *f as u64, + LaneType::IntType(i) => *i as u64, + } } /// Get the name of this lane type. pub fn name(&self) -> String { - match self.tag { - LaneTypeTag::BoolType(_) => format!("b{}", self.bits), - LaneTypeTag::FloatType(_) => format!("f{}", self.bits), - LaneTypeTag::IntType(_) => format!("i{}", self.bits), + match self { + LaneType::BoolType(_) => format!("b{}", self.lane_bits()), + LaneType::FloatType(_) => format!("f{}", self.lane_bits()), + LaneType::IntType(_) => format!("i{}", self.lane_bits()), } } /// Find the unique number associated with this lane type. pub fn number(&self) -> u8 { - LANE_BASE + match self.tag { - LaneTypeTag::BoolType(base_types::Bool::B1) => 0, - LaneTypeTag::BoolType(base_types::Bool::B8) => 1, - LaneTypeTag::BoolType(base_types::Bool::B16) => 2, - LaneTypeTag::BoolType(base_types::Bool::B32) => 3, - LaneTypeTag::BoolType(base_types::Bool::B64) => 4, - LaneTypeTag::IntType(base_types::Int::I8) => 5, - LaneTypeTag::IntType(base_types::Int::I16) => 6, - LaneTypeTag::IntType(base_types::Int::I32) => 7, - LaneTypeTag::IntType(base_types::Int::I64) => 8, - LaneTypeTag::FloatType(base_types::Float::F32) => 9, - LaneTypeTag::FloatType(base_types::Float::F64) => 10, + LANE_BASE + match self { + LaneType::BoolType(base_types::Bool::B1) => 0, + LaneType::BoolType(base_types::Bool::B8) => 1, + LaneType::BoolType(base_types::Bool::B16) => 2, + LaneType::BoolType(base_types::Bool::B32) => 3, + LaneType::BoolType(base_types::Bool::B64) => 4, + LaneType::IntType(base_types::Int::I8) => 5, + LaneType::IntType(base_types::Int::I16) => 6, + LaneType::IntType(base_types::Int::I32) => 7, + LaneType::IntType(base_types::Int::I64) => 8, + LaneType::FloatType(base_types::Float::F32) => 9, + LaneType::FloatType(base_types::Float::F64) => 10, } } } @@ -220,10 +225,10 @@ impl fmt::Debug for LaneType { write!( f, "{}", - match self.tag { - LaneTypeTag::BoolType(_) => format!("BoolType({})", inner_msg), - LaneTypeTag::FloatType(_) => format!("FloatType({})", inner_msg), - LaneTypeTag::IntType(_) => format!("IntType({})", inner_msg), + match self { + LaneType::BoolType(_) => format!("BoolType({})", inner_msg), + LaneType::FloatType(_) => format!("FloatType({})", inner_msg), + LaneType::IntType(_) => format!("IntType({})", inner_msg), } ) } @@ -232,38 +237,24 @@ impl fmt::Debug for LaneType { /// Create a LaneType from a given bool variant. impl From for LaneType { fn from(b: base_types::Bool) -> Self { - let bits = b as u64; - let tag = LaneTypeTag::BoolType(b); - Self { bits, tag } + LaneType::BoolType(b) } } /// Create a LaneType from a given float variant. impl From for LaneType { fn from(f: base_types::Float) -> Self { - let bits = f as u64; - let tag = LaneTypeTag::FloatType(f); - Self { bits, tag } + LaneType::FloatType(f) } } /// Create a LaneType from a given int variant. impl From for LaneType { fn from(i: base_types::Int) -> Self { - let bits = i as u64; - let tag = LaneTypeTag::IntType(i); - Self { bits, tag } + LaneType::IntType(i) } } -/// Tags used to specify the kinds of elements in a lane type. -#[derive(Debug, Clone, Copy)] -pub enum LaneTypeTag { - BoolType(base_types::Bool), - FloatType(base_types::Float), - IntType(base_types::Int), -} - /// An iterator for different lane types. pub struct LaneTypeIterator { bool_iter: base_types::BoolIterator, From f842b0764b07c9ccd8376732d873ac0dd4005d96 Mon Sep 17 00:00:00 2001 From: data-pup Date: Tue, 17 Jul 2018 19:05:12 -0400 Subject: [PATCH 15/26] Repeating the lane change cleanup. --- lib/codegen-meta/src/base/types.rs | 10 ------ lib/codegen-meta/src/cdsl/types.rs | 51 +++++++++++++++--------------- lib/codegen-meta/src/gen_types.rs | 4 ++- 3 files changed, 29 insertions(+), 36 deletions(-) diff --git a/lib/codegen-meta/src/base/types.rs b/lib/codegen-meta/src/base/types.rs index 793424a93..7ce42b197 100644 --- a/lib/codegen-meta/src/base/types.rs +++ b/lib/codegen-meta/src/base/types.rs @@ -121,16 +121,6 @@ pub enum Flag { FFlags, } -impl Flag { - /// Get the number of a flag variant. - pub fn number(self) -> u8 { - match self { - Flag::IFlags => 1, - Flag::FFlags => 2, - } - } -} - /// Iterator through the variants of the Flag enum. pub struct FlagIterator { index: u8, diff --git a/lib/codegen-meta/src/cdsl/types.rs b/lib/codegen-meta/src/cdsl/types.rs index 3637652e8..5bc6b68e4 100644 --- a/lib/codegen-meta/src/cdsl/types.rs +++ b/lib/codegen-meta/src/cdsl/types.rs @@ -383,20 +383,20 @@ impl fmt::Debug for BVType { /// A concrete scalar type that is neither a vector nor a lane type. /// /// Special types cannot be used to form vectors. -#[derive(Debug, Clone, Copy)] -pub struct SpecialType { - tag: SpecialTypeTag, +#[derive(Clone, Copy)] +pub enum SpecialType { + Flag(base_types::Flag), } impl SpecialType { /// Return a string containing the documentation comment for this special type. pub fn doc(&self) -> String { - match self.tag { - SpecialTypeTag::Flag(base_types::Flag::IFlags) => String::from( + match self { + SpecialType::Flag(base_types::Flag::IFlags) => String::from( "CPU flags representing the result of an integer comparison. These flags can be tested with an :type:`intcc` condition code.", ), - SpecialTypeTag::Flag(base_types::Flag::FFlags) => String::from( + SpecialType::Flag(base_types::Flag::FFlags) => String::from( "CPU flags representing the result of a floating point comparison. These flags can be tested with a :type:`floatcc` condition code.", ), @@ -405,35 +405,39 @@ impl SpecialType { /// Return the number of bits in a lane. pub fn lane_bits(&self) -> u64 { - match self.tag { - SpecialTypeTag::Flag(_) => 0, + match self { + SpecialType::Flag(_) => 0, } } /// Get the name of this special type. pub fn name(&self) -> String { - match self.tag { - SpecialTypeTag::Flag(base_types::Flag::IFlags) => "iflags".to_string(), - SpecialTypeTag::Flag(base_types::Flag::FFlags) => "fflags".to_string(), + match self { + SpecialType::Flag(base_types::Flag::IFlags) => "iflags".to_string(), + SpecialType::Flag(base_types::Flag::FFlags) => "fflags".to_string(), } } /// Find the unique number associated with this special type. pub fn number(&self) -> u8 { - self.tag.number() + match self { + SpecialType::Flag(base_types::Flag::IFlags) => 1, + SpecialType::Flag(base_types::Flag::FFlags) => 2, + } } } -#[derive(Debug, Clone, Copy)] -pub enum SpecialTypeTag { - Flag(base_types::Flag), +impl fmt::Debug for SpecialType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", match self { + SpecialType::Flag(_) => format!("FlagsType({})", self.name()), + }) + } } -impl SpecialTypeTag { - pub fn number(&self) -> u8 { - match *self { - SpecialTypeTag::Flag(f) => f.number(), - } +impl From for SpecialType { + fn from(f: base_types::Flag) -> Self { + SpecialType::Flag(f) } } @@ -450,13 +454,10 @@ impl SpecialTypeIterator { } impl Iterator for SpecialTypeIterator { - type Item = ValueType; + type Item = SpecialType; fn next(&mut self) -> Option { if let Some(f) = self.flag_iter.next() { - let next = SpecialType { - tag: SpecialTypeTag::Flag(f), - }; - Some(ValueType::Special(next)) + Some(SpecialType::from(f)) } else { None } diff --git a/lib/codegen-meta/src/gen_types.rs b/lib/codegen-meta/src/gen_types.rs index 520120ffa..3c6de4ae6 100644 --- a/lib/codegen-meta/src/gen_types.rs +++ b/lib/codegen-meta/src/gen_types.rs @@ -46,7 +46,9 @@ fn emit_vectors(bits: u64, fmt: &mut srcgen::Formatter) -> Result<(), error::Err /// Emit types using the given formatter object. fn emit_types(fmt: &mut srcgen::Formatter) -> Result<(), error::Error> { // Emit all of the special types, such as types for CPU flags. - for spec in cdsl_types::ValueType::all_special_types() { + for spec in cdsl_types::ValueType::all_special_types() + .map(|ty| cdsl_types::ValueType::from(ty)) + { emit_type(&spec, fmt)?; } From a62db2e4ba53306283285ab4bd75963a554dcfdd Mon Sep 17 00:00:00 2001 From: data-pup Date: Tue, 17 Jul 2018 19:08:02 -0400 Subject: [PATCH 16/26] Removed codegen-meta crate from codegen deps. --- lib/codegen/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/codegen/Cargo.toml b/lib/codegen/Cargo.toml index 8afcc447d..18477baea 100644 --- a/lib/codegen/Cargo.toml +++ b/lib/codegen/Cargo.toml @@ -12,7 +12,6 @@ build = "build.rs" [dependencies] cranelift-entity = { path = "../entity", version = "0.15.0", default-features = false } -cranelift-codegen-meta = { path = "../codegen-meta", version = "0.15.0" } failure = { version = "0.1.1", default-features = false, features = ["derive"] } failure_derive = { version = "0.1.1", default-features = false } hashmap_core = { version = "0.1.8", optional = true } From 07e2919845c6ca1dfc388e450a9173b77bae86dd Mon Sep 17 00:00:00 2001 From: data-pup Date: Tue, 17 Jul 2018 19:08:33 -0400 Subject: [PATCH 17/26] Typo fix. --- lib/codegen-meta/src/srcgen.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codegen-meta/src/srcgen.rs b/lib/codegen-meta/src/srcgen.rs index ef8bde89c..26bce8c7a 100644 --- a/lib/codegen-meta/src/srcgen.rs +++ b/lib/codegen-meta/src/srcgen.rs @@ -212,7 +212,7 @@ struct _Match<'a> { } impl<'a> _Match<'a> { - /// Create a new match statemeht on `expr`. + /// Create a new match statement on `expr`. fn _new(expr: &'a str) -> Self { Self { _expr: expr, From 1a8f003d8461fc9dd44915b45765be0f79379497 Mon Sep 17 00:00:00 2001 From: data-pup Date: Tue, 17 Jul 2018 19:12:12 -0400 Subject: [PATCH 18/26] Addressing a patch note. --- lib/codegen-meta/src/srcgen.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/codegen-meta/src/srcgen.rs b/lib/codegen-meta/src/srcgen.rs index 26bce8c7a..53a4dc5f7 100644 --- a/lib/codegen-meta/src/srcgen.rs +++ b/lib/codegen-meta/src/srcgen.rs @@ -205,7 +205,8 @@ fn parse_multiline(s: &str) -> Vec { /// expression, automatically deduplicating overlapping identical arms. /// /// Note that this class is ignorant of Rust types, and considers two fields -/// with the same name to be equivalent. +/// with the same name to be equivalent. A BTreeMap is used to represent the +/// arms in order to make the order deterministic. struct _Match<'a> { _expr: &'a str, arms: BTreeMap<(Vec<&'a str>, &'a str), HashSet<&'a str>>, From 1d121c5a210a08159a3cb004b593b0c824244cd0 Mon Sep 17 00:00:00 2001 From: data-pup Date: Tue, 17 Jul 2018 19:12:23 -0400 Subject: [PATCH 19/26] Addressing patch note. --- lib/codegen-meta/src/cdsl/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codegen-meta/src/cdsl/types.rs b/lib/codegen-meta/src/cdsl/types.rs index 5bc6b68e4..39783ae05 100644 --- a/lib/codegen-meta/src/cdsl/types.rs +++ b/lib/codegen-meta/src/cdsl/types.rs @@ -99,7 +99,7 @@ impl ValueType { } } - /// Return the name of this type for other Rust source files. + /// Return the name of this type for generated Rust source files. pub fn _rust_name(&self) -> String { format!("{}{}", _RUST_NAME_PREFIX, self.name().to_uppercase()) } From 2c1232db52cb22ea42ce7550142db5d2baf587e2 Mon Sep 17 00:00:00 2001 From: data-pup Date: Tue, 17 Jul 2018 19:12:57 -0400 Subject: [PATCH 20/26] Lowercase in vector names. --- lib/codegen-meta/src/cdsl/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/codegen-meta/src/cdsl/types.rs b/lib/codegen-meta/src/cdsl/types.rs index 39783ae05..f7001f6c3 100644 --- a/lib/codegen-meta/src/cdsl/types.rs +++ b/lib/codegen-meta/src/cdsl/types.rs @@ -314,7 +314,7 @@ impl VectorType { /// Get the name of this vector type. pub fn name(&self) -> String { - format!("{}X{}", self.base.name(), self.lanes,) + format!("{}x{}", self.base.name(), self.lanes,) } /// Find the unique number associated with this vector type. From d8e94235333611955ad63cc91f2ba669d34e00d1 Mon Sep 17 00:00:00 2001 From: data-pup Date: Tue, 17 Jul 2018 19:14:12 -0400 Subject: [PATCH 21/26] Fixing a comment bug. --- lib/codegen-meta/src/gen_types.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/codegen-meta/src/gen_types.rs b/lib/codegen-meta/src/gen_types.rs index 3c6de4ae6..dcd6ae8c2 100644 --- a/lib/codegen-meta/src/gen_types.rs +++ b/lib/codegen-meta/src/gen_types.rs @@ -4,7 +4,8 @@ //! `lib/codegen/ir/types.rs`. The file provides constant definitions for the //! most commonly used types, including all of the scalar types. //! -//! This ensures that Python and Rust use the same type numbering. +//! This ensures that the metaprogram and the generated program see the same +//! type numbering. use cdsl::types as cdsl_types; use error; From 73b6da6de8edaa47c02f8a8eedeb7b3ca4d66e5e Mon Sep 17 00:00:00 2001 From: data-pup Date: Tue, 17 Jul 2018 19:16:00 -0400 Subject: [PATCH 22/26] Added a copy of the license file. --- lib/codegen-meta/LICENSE | 219 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 219 insertions(+) create mode 100644 lib/codegen-meta/LICENSE diff --git a/lib/codegen-meta/LICENSE b/lib/codegen-meta/LICENSE new file mode 100644 index 000000000..be1d7c438 --- /dev/null +++ b/lib/codegen-meta/LICENSE @@ -0,0 +1,219 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +--- LLVM Exceptions to the Apache 2.0 License ---- + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into an Object form of such source code, you +may redistribute such embedded portions in such Object form without complying +with the conditions of Sections 4(a), 4(b) and 4(d) of the License. + +In addition, if you combine or link compiled forms of this Software with +software that is licensed under the GPLv2 ("Combined Software") and if a +court of competent jurisdiction determines that the patent provision (Section +3), the indemnity provision (Section 9) or other Section of the License +conflicts with the conditions of the GPLv2, you may retroactively and +prospectively choose to deem waived or otherwise exclude such Section(s) of +the License, but only in their entirety and only with respect to the Combined +Software. From 352a85953adb1beef5d14c7eaa4b1b49628ffa32 Mon Sep 17 00:00:00 2001 From: data-pup Date: Tue, 17 Jul 2018 19:16:24 -0400 Subject: [PATCH 23/26] Formatting changes. --- lib/codegen-meta/src/cdsl/types.rs | 13 +++++++++---- lib/codegen-meta/src/gen_types.rs | 3 +-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/codegen-meta/src/cdsl/types.rs b/lib/codegen-meta/src/cdsl/types.rs index f7001f6c3..ea64e9394 100644 --- a/lib/codegen-meta/src/cdsl/types.rs +++ b/lib/codegen-meta/src/cdsl/types.rs @@ -177,7 +177,8 @@ impl LaneType { LaneType::IntType(_) if self.lane_bits() < 32 => format!( "An integer type with {} bits. WARNING: arithmetic on {}bit integers is incomplete", - self.lane_bits(), self.lane_bits() + self.lane_bits(), + self.lane_bits() ), LaneType::IntType(_) => format!("An integer type with {} bits.", self.lane_bits()), } @@ -429,9 +430,13 @@ impl SpecialType { impl fmt::Debug for SpecialType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", match self { - SpecialType::Flag(_) => format!("FlagsType({})", self.name()), - }) + write!( + f, + "{}", + match self { + SpecialType::Flag(_) => format!("FlagsType({})", self.name()), + } + ) } } diff --git a/lib/codegen-meta/src/gen_types.rs b/lib/codegen-meta/src/gen_types.rs index dcd6ae8c2..1055f0de0 100644 --- a/lib/codegen-meta/src/gen_types.rs +++ b/lib/codegen-meta/src/gen_types.rs @@ -47,8 +47,7 @@ fn emit_vectors(bits: u64, fmt: &mut srcgen::Formatter) -> Result<(), error::Err /// Emit types using the given formatter object. fn emit_types(fmt: &mut srcgen::Formatter) -> Result<(), error::Error> { // Emit all of the special types, such as types for CPU flags. - for spec in cdsl_types::ValueType::all_special_types() - .map(|ty| cdsl_types::ValueType::from(ty)) + for spec in cdsl_types::ValueType::all_special_types().map(|ty| cdsl_types::ValueType::from(ty)) { emit_type(&spec, fmt)?; } From 551b419c7294f26d1e9f4478aabb3cbd6cb4c7ac Mon Sep 17 00:00:00 2001 From: data-pup Date: Tue, 17 Jul 2018 19:36:51 -0400 Subject: [PATCH 24/26] Cleaned up the vector type numbering. --- lib/codegen-meta/src/cdsl/types.rs | 31 ++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/lib/codegen-meta/src/cdsl/types.rs b/lib/codegen-meta/src/cdsl/types.rs index ea64e9394..b9ec9125e 100644 --- a/lib/codegen-meta/src/cdsl/types.rs +++ b/lib/codegen-meta/src/cdsl/types.rs @@ -308,24 +308,11 @@ impl VectorType { pub fn doc(&self) -> String { format!( "A SIMD vector with {} lanes containing a `{}` each.", - self.lanes, + self.lane_count(), self.base.name() ) } - /// Get the name of this vector type. - pub fn name(&self) -> String { - format!("{}x{}", self.base.name(), self.lanes,) - } - - /// Find the unique number associated with this vector type. - pub fn number(&self) -> u8 { - let b = f64::from(self.base.number()); - let l = (self.lanes as f64).log2(); - let num = 16_f64 * l + b; - num as u8 - } - /// Return the number of bits in a lane. pub fn lane_bits(&self) -> u64 { self.base.lane_bits() @@ -335,6 +322,22 @@ impl VectorType { pub fn lane_count(&self) -> u64 { self.lanes } + + /// Get the name of this vector type. + pub fn name(&self) -> String { + format!("{}x{}", self.base.name(), self.lane_count()) + } + + /// Find the unique number associated with this vector type. + /// + /// Vector types are encoded with the lane type in the low 4 bits and + /// log2(lanes) in the high 4 bits, giving a range of 2-256 lanes. + pub fn number(&self) -> u8 { + let lanes_log_2: u32 = 63 - self.lane_count().leading_zeros(); + let base_num = u32::from(self.base.number()); + let num = (lanes_log_2 << 4) + base_num; + num as u8 + } } impl fmt::Debug for VectorType { From 9534beda47452aefafae1fa6c93b5b846d60bd48 Mon Sep 17 00:00:00 2001 From: data-pup Date: Wed, 18 Jul 2018 11:28:18 -0400 Subject: [PATCH 25/26] 1.25 compatibility. --- lib/codegen-meta/src/cdsl/types.rs | 66 +++++++++++++++--------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/lib/codegen-meta/src/cdsl/types.rs b/lib/codegen-meta/src/cdsl/types.rs index b9ec9125e..71177c0ce 100644 --- a/lib/codegen-meta/src/cdsl/types.rs +++ b/lib/codegen-meta/src/cdsl/types.rs @@ -163,59 +163,59 @@ impl LaneType { /// Return a string containing the documentation comment for this lane type. pub fn doc(&self) -> String { match self { - LaneType::BoolType(_) => format!("A boolean type with {} bits.", self.lane_bits()), - LaneType::FloatType(base_types::Float::F32) => String::from( + &LaneType::BoolType(_) => format!("A boolean type with {} bits.", self.lane_bits()), + &LaneType::FloatType(base_types::Float::F32) => String::from( "A 32-bit floating point type represented in the IEEE 754-2008 *binary32* interchange format. This corresponds to the :c:type:`float` type in most C implementations.", ), - LaneType::FloatType(base_types::Float::F64) => String::from( + &LaneType::FloatType(base_types::Float::F64) => String::from( "A 64-bit floating point type represented in the IEEE 754-2008 *binary64* interchange format. This corresponds to the :c:type:`double` type in most C implementations.", ), - LaneType::IntType(_) if self.lane_bits() < 32 => format!( + &LaneType::IntType(_) if self.lane_bits() < 32 => format!( "An integer type with {} bits. WARNING: arithmetic on {}bit integers is incomplete", self.lane_bits(), self.lane_bits() ), - LaneType::IntType(_) => format!("An integer type with {} bits.", self.lane_bits()), + &LaneType::IntType(_) => format!("An integer type with {} bits.", self.lane_bits()), } } /// Return the number of bits in a lane. pub fn lane_bits(&self) -> u64 { match self { - LaneType::BoolType(b) => *b as u64, - LaneType::FloatType(f) => *f as u64, - LaneType::IntType(i) => *i as u64, + &LaneType::BoolType(ref b) => *b as u64, + &LaneType::FloatType(ref f) => *f as u64, + &LaneType::IntType(ref i) => *i as u64, } } /// Get the name of this lane type. pub fn name(&self) -> String { match self { - LaneType::BoolType(_) => format!("b{}", self.lane_bits()), - LaneType::FloatType(_) => format!("f{}", self.lane_bits()), - LaneType::IntType(_) => format!("i{}", self.lane_bits()), + &LaneType::BoolType(_) => format!("b{}", self.lane_bits()), + &LaneType::FloatType(_) => format!("f{}", self.lane_bits()), + &LaneType::IntType(_) => format!("i{}", self.lane_bits()), } } /// Find the unique number associated with this lane type. pub fn number(&self) -> u8 { LANE_BASE + match self { - LaneType::BoolType(base_types::Bool::B1) => 0, - LaneType::BoolType(base_types::Bool::B8) => 1, - LaneType::BoolType(base_types::Bool::B16) => 2, - LaneType::BoolType(base_types::Bool::B32) => 3, - LaneType::BoolType(base_types::Bool::B64) => 4, - LaneType::IntType(base_types::Int::I8) => 5, - LaneType::IntType(base_types::Int::I16) => 6, - LaneType::IntType(base_types::Int::I32) => 7, - LaneType::IntType(base_types::Int::I64) => 8, - LaneType::FloatType(base_types::Float::F32) => 9, - LaneType::FloatType(base_types::Float::F64) => 10, + &LaneType::BoolType(base_types::Bool::B1) => 0, + &LaneType::BoolType(base_types::Bool::B8) => 1, + &LaneType::BoolType(base_types::Bool::B16) => 2, + &LaneType::BoolType(base_types::Bool::B32) => 3, + &LaneType::BoolType(base_types::Bool::B64) => 4, + &LaneType::IntType(base_types::Int::I8) => 5, + &LaneType::IntType(base_types::Int::I16) => 6, + &LaneType::IntType(base_types::Int::I32) => 7, + &LaneType::IntType(base_types::Int::I64) => 8, + &LaneType::FloatType(base_types::Float::F32) => 9, + &LaneType::FloatType(base_types::Float::F64) => 10, } } } @@ -227,9 +227,9 @@ impl fmt::Debug for LaneType { f, "{}", match self { - LaneType::BoolType(_) => format!("BoolType({})", inner_msg), - LaneType::FloatType(_) => format!("FloatType({})", inner_msg), - LaneType::IntType(_) => format!("IntType({})", inner_msg), + &LaneType::BoolType(_) => format!("BoolType({})", inner_msg), + &LaneType::FloatType(_) => format!("FloatType({})", inner_msg), + &LaneType::IntType(_) => format!("IntType({})", inner_msg), } ) } @@ -396,11 +396,11 @@ impl SpecialType { /// Return a string containing the documentation comment for this special type. pub fn doc(&self) -> String { match self { - SpecialType::Flag(base_types::Flag::IFlags) => String::from( + &SpecialType::Flag(base_types::Flag::IFlags) => String::from( "CPU flags representing the result of an integer comparison. These flags can be tested with an :type:`intcc` condition code.", ), - SpecialType::Flag(base_types::Flag::FFlags) => String::from( + &SpecialType::Flag(base_types::Flag::FFlags) => String::from( "CPU flags representing the result of a floating point comparison. These flags can be tested with a :type:`floatcc` condition code.", ), @@ -410,23 +410,23 @@ impl SpecialType { /// Return the number of bits in a lane. pub fn lane_bits(&self) -> u64 { match self { - SpecialType::Flag(_) => 0, + &SpecialType::Flag(_) => 0, } } /// Get the name of this special type. pub fn name(&self) -> String { match self { - SpecialType::Flag(base_types::Flag::IFlags) => "iflags".to_string(), - SpecialType::Flag(base_types::Flag::FFlags) => "fflags".to_string(), + &SpecialType::Flag(base_types::Flag::IFlags) => "iflags".to_string(), + &SpecialType::Flag(base_types::Flag::FFlags) => "fflags".to_string(), } } /// Find the unique number associated with this special type. pub fn number(&self) -> u8 { match self { - SpecialType::Flag(base_types::Flag::IFlags) => 1, - SpecialType::Flag(base_types::Flag::FFlags) => 2, + &SpecialType::Flag(base_types::Flag::IFlags) => 1, + &SpecialType::Flag(base_types::Flag::FFlags) => 2, } } } @@ -437,7 +437,7 @@ impl fmt::Debug for SpecialType { f, "{}", match self { - SpecialType::Flag(_) => format!("FlagsType({})", self.name()), + &SpecialType::Flag(_) => format!("FlagsType({})", self.name()), } ) } From 46d4bb1d59da94515cb803ff75a115d322291d04 Mon Sep 17 00:00:00 2001 From: data-pup Date: Thu, 19 Jul 2018 09:53:59 -0400 Subject: [PATCH 26/26] Fixed pattern match arms. --- lib/codegen-meta/src/cdsl/types.rs | 130 ++++++++++++++--------------- lib/codegen-meta/src/error.rs | 6 +- 2 files changed, 68 insertions(+), 68 deletions(-) diff --git a/lib/codegen-meta/src/cdsl/types.rs b/lib/codegen-meta/src/cdsl/types.rs index 71177c0ce..90438e917 100644 --- a/lib/codegen-meta/src/cdsl/types.rs +++ b/lib/codegen-meta/src/cdsl/types.rs @@ -48,28 +48,28 @@ impl ValueType { /// Return a string containing the documentation comment for this type. pub fn doc(&self) -> String { - match self { - &ValueType::BV(ref b) => b.doc(), - &ValueType::Lane(l) => l.doc(), - &ValueType::Special(s) => s.doc(), - &ValueType::Vector(ref v) => v.doc(), + match *self { + ValueType::BV(ref b) => b.doc(), + ValueType::Lane(l) => l.doc(), + ValueType::Special(s) => s.doc(), + ValueType::Vector(ref v) => v.doc(), } } /// Return the number of bits in a lane. pub fn lane_bits(&self) -> u64 { - match self { - &ValueType::BV(ref b) => b.lane_bits(), - &ValueType::Lane(l) => l.lane_bits(), - &ValueType::Special(s) => s.lane_bits(), - &ValueType::Vector(ref v) => v.lane_bits(), + match *self { + ValueType::BV(ref b) => b.lane_bits(), + ValueType::Lane(l) => l.lane_bits(), + ValueType::Special(s) => s.lane_bits(), + ValueType::Vector(ref v) => v.lane_bits(), } } /// Return the number of lanes. pub fn lane_count(&self) -> u64 { - match self { - &ValueType::Vector(ref v) => v.lane_count(), + match *self { + ValueType::Vector(ref v) => v.lane_count(), _ => 1, } } @@ -81,21 +81,21 @@ impl ValueType { /// Get the name of this type. pub fn name(&self) -> String { - match self { - &ValueType::BV(ref b) => b.name(), - &ValueType::Lane(l) => l.name(), - &ValueType::Special(s) => s.name(), - &ValueType::Vector(ref v) => v.name(), + match *self { + ValueType::BV(ref b) => b.name(), + ValueType::Lane(l) => l.name(), + ValueType::Special(s) => s.name(), + ValueType::Vector(ref v) => v.name(), } } /// Find the unique number associated with this type. pub fn number(&self) -> Option { - match self { - &ValueType::BV(_) => None, - &ValueType::Lane(l) => Some(l.number()), - &ValueType::Special(s) => Some(s.number()), - &ValueType::Vector(ref v) => Some(v.number()), + match *self { + ValueType::BV(_) => None, + ValueType::Lane(l) => Some(l.number()), + ValueType::Special(s) => Some(s.number()), + ValueType::Vector(ref v) => Some(v.number()), } } @@ -162,60 +162,60 @@ pub enum LaneType { impl LaneType { /// Return a string containing the documentation comment for this lane type. pub fn doc(&self) -> String { - match self { - &LaneType::BoolType(_) => format!("A boolean type with {} bits.", self.lane_bits()), - &LaneType::FloatType(base_types::Float::F32) => String::from( + match *self { + LaneType::BoolType(_) => format!("A boolean type with {} bits.", self.lane_bits()), + LaneType::FloatType(base_types::Float::F32) => String::from( "A 32-bit floating point type represented in the IEEE 754-2008 *binary32* interchange format. This corresponds to the :c:type:`float` type in most C implementations.", ), - &LaneType::FloatType(base_types::Float::F64) => String::from( + LaneType::FloatType(base_types::Float::F64) => String::from( "A 64-bit floating point type represented in the IEEE 754-2008 *binary64* interchange format. This corresponds to the :c:type:`double` type in most C implementations.", ), - &LaneType::IntType(_) if self.lane_bits() < 32 => format!( + LaneType::IntType(_) if self.lane_bits() < 32 => format!( "An integer type with {} bits. WARNING: arithmetic on {}bit integers is incomplete", self.lane_bits(), self.lane_bits() ), - &LaneType::IntType(_) => format!("An integer type with {} bits.", self.lane_bits()), + LaneType::IntType(_) => format!("An integer type with {} bits.", self.lane_bits()), } } /// Return the number of bits in a lane. pub fn lane_bits(&self) -> u64 { - match self { - &LaneType::BoolType(ref b) => *b as u64, - &LaneType::FloatType(ref f) => *f as u64, - &LaneType::IntType(ref i) => *i as u64, + match *self { + LaneType::BoolType(ref b) => *b as u64, + LaneType::FloatType(ref f) => *f as u64, + LaneType::IntType(ref i) => *i as u64, } } /// Get the name of this lane type. pub fn name(&self) -> String { - match self { - &LaneType::BoolType(_) => format!("b{}", self.lane_bits()), - &LaneType::FloatType(_) => format!("f{}", self.lane_bits()), - &LaneType::IntType(_) => format!("i{}", self.lane_bits()), + match *self { + LaneType::BoolType(_) => format!("b{}", self.lane_bits()), + LaneType::FloatType(_) => format!("f{}", self.lane_bits()), + LaneType::IntType(_) => format!("i{}", self.lane_bits()), } } /// Find the unique number associated with this lane type. pub fn number(&self) -> u8 { - LANE_BASE + match self { - &LaneType::BoolType(base_types::Bool::B1) => 0, - &LaneType::BoolType(base_types::Bool::B8) => 1, - &LaneType::BoolType(base_types::Bool::B16) => 2, - &LaneType::BoolType(base_types::Bool::B32) => 3, - &LaneType::BoolType(base_types::Bool::B64) => 4, - &LaneType::IntType(base_types::Int::I8) => 5, - &LaneType::IntType(base_types::Int::I16) => 6, - &LaneType::IntType(base_types::Int::I32) => 7, - &LaneType::IntType(base_types::Int::I64) => 8, - &LaneType::FloatType(base_types::Float::F32) => 9, - &LaneType::FloatType(base_types::Float::F64) => 10, + LANE_BASE + match *self { + LaneType::BoolType(base_types::Bool::B1) => 0, + LaneType::BoolType(base_types::Bool::B8) => 1, + LaneType::BoolType(base_types::Bool::B16) => 2, + LaneType::BoolType(base_types::Bool::B32) => 3, + LaneType::BoolType(base_types::Bool::B64) => 4, + LaneType::IntType(base_types::Int::I8) => 5, + LaneType::IntType(base_types::Int::I16) => 6, + LaneType::IntType(base_types::Int::I32) => 7, + LaneType::IntType(base_types::Int::I64) => 8, + LaneType::FloatType(base_types::Float::F32) => 9, + LaneType::FloatType(base_types::Float::F64) => 10, } } } @@ -226,10 +226,10 @@ impl fmt::Debug for LaneType { write!( f, "{}", - match self { - &LaneType::BoolType(_) => format!("BoolType({})", inner_msg), - &LaneType::FloatType(_) => format!("FloatType({})", inner_msg), - &LaneType::IntType(_) => format!("IntType({})", inner_msg), + match *self { + LaneType::BoolType(_) => format!("BoolType({})", inner_msg), + LaneType::FloatType(_) => format!("FloatType({})", inner_msg), + LaneType::IntType(_) => format!("IntType({})", inner_msg), } ) } @@ -395,12 +395,12 @@ pub enum SpecialType { impl SpecialType { /// Return a string containing the documentation comment for this special type. pub fn doc(&self) -> String { - match self { - &SpecialType::Flag(base_types::Flag::IFlags) => String::from( + match *self { + SpecialType::Flag(base_types::Flag::IFlags) => String::from( "CPU flags representing the result of an integer comparison. These flags can be tested with an :type:`intcc` condition code.", ), - &SpecialType::Flag(base_types::Flag::FFlags) => String::from( + SpecialType::Flag(base_types::Flag::FFlags) => String::from( "CPU flags representing the result of a floating point comparison. These flags can be tested with a :type:`floatcc` condition code.", ), @@ -409,24 +409,24 @@ impl SpecialType { /// Return the number of bits in a lane. pub fn lane_bits(&self) -> u64 { - match self { - &SpecialType::Flag(_) => 0, + match *self { + SpecialType::Flag(_) => 0, } } /// Get the name of this special type. pub fn name(&self) -> String { - match self { - &SpecialType::Flag(base_types::Flag::IFlags) => "iflags".to_string(), - &SpecialType::Flag(base_types::Flag::FFlags) => "fflags".to_string(), + match *self { + SpecialType::Flag(base_types::Flag::IFlags) => "iflags".to_string(), + SpecialType::Flag(base_types::Flag::FFlags) => "fflags".to_string(), } } /// Find the unique number associated with this special type. pub fn number(&self) -> u8 { - match self { - &SpecialType::Flag(base_types::Flag::IFlags) => 1, - &SpecialType::Flag(base_types::Flag::FFlags) => 2, + match *self { + SpecialType::Flag(base_types::Flag::IFlags) => 1, + SpecialType::Flag(base_types::Flag::FFlags) => 2, } } } @@ -436,8 +436,8 @@ impl fmt::Debug for SpecialType { write!( f, "{}", - match self { - &SpecialType::Flag(_) => format!("FlagsType({})", self.name()), + match *self { + SpecialType::Flag(_) => format!("FlagsType({})", self.name()), } ) } diff --git a/lib/codegen-meta/src/error.rs b/lib/codegen-meta/src/error.rs index 595a5c355..316e69bbc 100644 --- a/lib/codegen-meta/src/error.rs +++ b/lib/codegen-meta/src/error.rs @@ -39,9 +39,9 @@ enum ErrorInner { impl fmt::Display for ErrorInner { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - &ErrorInner::Msg(ref s) => write!(f, "{}", s), - &ErrorInner::IoError(ref e) => write!(f, "{}", e), + match *self { + ErrorInner::Msg(ref s) => write!(f, "{}", s), + ErrorInner::IoError(ref e) => write!(f, "{}", e), } } }