diff --git a/cranelift/src/libcretonne/types.rs b/cranelift/src/libcretonne/types.rs index 88a2b6cad2..6c8fb90d90 100644 --- a/cranelift/src/libcretonne/types.rs +++ b/cranelift/src/libcretonne/types.rs @@ -3,6 +3,12 @@ use std::fmt::{self, Display, Formatter, Write}; +// ====--------------------------------------------------------------------------------------====// +// +// Value types +// +// ====--------------------------------------------------------------------------------------====// + /// The type of an SSA value. /// /// The `VOID` type is only used for instructions that produce no value. It can't be part of a SIMD @@ -177,6 +183,107 @@ impl Display for Type { } } +// ====--------------------------------------------------------------------------------------====// +// +// Function signatures +// +// ====--------------------------------------------------------------------------------------====// + +/// Function argument extension options. +/// +/// On some architectures, small integer function arguments are extended to the width of a +/// general-purpose register. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum ArgumentExtension { + /// No extension, high bits are indeterminate. + None, + /// Unsigned extension: high bits in register are 0. + Uext, + /// Signed extension: high bits in register replicate sign bit. + Sext, +} + +/// Function argument or return value type. +/// +/// This describes the value type being passed to or from a function along with flags that affect +/// how the argument is passed. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub struct ArgumentType { + pub value_type: Type, + pub extension: ArgumentExtension, + /// Place this argument in a register if possible. + pub inreg: bool, +} + +/// Function signature. +/// +/// The function signature describes the types of arguments and return values along with other +/// details that are needed to call a function correctly. +pub struct Signature { + pub argument_types: Vec, + pub return_types: Vec, +} + +impl ArgumentType { + pub fn new(vt: Type) -> ArgumentType { + ArgumentType { + value_type: vt, + extension: ArgumentExtension::None, + inreg: false, + } + } +} + +impl Display for ArgumentType { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + try!(write!(f, "{}", self.value_type)); + match self.extension { + ArgumentExtension::None => {} + ArgumentExtension::Uext => try!(write!(f, " uext")), + ArgumentExtension::Sext => try!(write!(f, " sext")), + } + if self.inreg { + try!(write!(f, " inreg")); + } + Ok(()) + } +} + +impl Signature { + pub fn new() -> Signature { + Signature { + argument_types: Vec::new(), + return_types: Vec::new(), + } + } +} + +fn write_list(f: &mut Formatter, args: &Vec) -> fmt::Result { + match args.split_first() { + None => {} + Some((first, rest)) => { + try!(write!(f, "{}", first)); + for arg in rest { + try!(write!(f, ", {}", arg)); + } + } + } + Ok(()) +} + +impl Display for Signature { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + try!(write!(f, "(")); + try!(write_list(f, &self.argument_types)); + try!(write!(f, ")")); + if !self.return_types.is_empty() { + try!(write!(f, " -> ")); + try!(write_list(f, &self.return_types)); + } + Ok(()) + } +} + #[cfg(test)] mod tests { use super::*; @@ -248,4 +355,28 @@ mod tests { assert_eq!(format!("{}", I8.by(64)), "i8x64"); assert_eq!(format!("{}", F64.by(2)), "f64x2"); } + + #[test] + fn argument_type() { + let mut t = ArgumentType::new(I32); + assert_eq!(format!("{}", t), "i32"); + t.extension = ArgumentExtension::Uext; + assert_eq!(format!("{}", t), "i32 uext"); + t.inreg = true; + assert_eq!(format!("{}", t), "i32 uext inreg"); + } + + #[test] + fn signatures() { + let mut sig = Signature::new(); + assert_eq!(format!("{}", sig), "()"); + sig.argument_types.push(ArgumentType::new(I32)); + assert_eq!(format!("{}", sig), "(i32)"); + sig.return_types.push(ArgumentType::new(F32)); + assert_eq!(format!("{}", sig), "(i32) -> f32"); + sig.argument_types.push(ArgumentType::new(I32.by(4))); + assert_eq!(format!("{}", sig), "(i32, i32x4) -> f32"); + sig.return_types.push(ArgumentType::new(B8)); + assert_eq!(format!("{}", sig), "(i32, i32x4) -> f32, b8"); + } }