Move signatures into new ir::extfunc module.

This new module will gain more data types dealing with external function
calls.
This commit is contained in:
Jakob Stoklund Olesen
2016-10-12 13:35:18 -07:00
parent b258644d07
commit b42d85ae24
4 changed files with 142 additions and 131 deletions

View File

@@ -0,0 +1,135 @@
//! External function calls.
//!
//! To a Cretonne function, all functions are "external". Directly called functions must be
//! declared in the preamble, and all function calls must have a signature.
//!
//! This module declares the data types used to represent external functions and call signatures.
use std::fmt::{self, Display, Formatter};
use ir::Type;
/// 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.
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Signature {
pub argument_types: Vec<ArgumentType>,
pub return_types: Vec<ArgumentType>,
}
impl Signature {
pub fn new() -> Signature {
Signature {
argument_types: Vec::new(),
return_types: Vec::new(),
}
}
}
fn write_list(f: &mut Formatter, args: &Vec<ArgumentType>) -> 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(())
}
}
/// 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,
}
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(())
}
}
/// 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,
}
#[cfg(test)]
mod tests {
use super::*;
use ir::types::{I32, F32, B8};
#[test]
fn argument_type() {
let mut t = ArgumentType::new(I32);
assert_eq!(t.to_string(), "i32");
t.extension = ArgumentExtension::Uext;
assert_eq!(t.to_string(), "i32 uext");
t.inreg = true;
assert_eq!(t.to_string(), "i32 uext inreg");
}
#[test]
fn signatures() {
let mut sig = Signature::new();
assert_eq!(sig.to_string(), "()");
sig.argument_types.push(ArgumentType::new(I32));
assert_eq!(sig.to_string(), "(i32)");
sig.return_types.push(ArgumentType::new(F32));
assert_eq!(sig.to_string(), "(i32) -> f32");
sig.argument_types.push(ArgumentType::new(I32.by(4).unwrap()));
assert_eq!(sig.to_string(), "(i32, i32x4) -> f32");
sig.return_types.push(ArgumentType::new(B8));
assert_eq!(sig.to_string(), "(i32, i32x4) -> f32, b8");
}
}

View File

@@ -11,9 +11,11 @@ pub mod dfg;
pub mod layout;
pub mod function;
mod funcname;
mod extfunc;
pub use ir::funcname::FunctionName;
pub use ir::types::{Type, Signature};
pub use ir::extfunc::{Signature, ArgumentType, ArgumentExtension};
pub use ir::types::Type;
pub use ir::entities::{Ebb, Inst, Value, StackSlot, JumpTable};
pub use ir::instructions::{Opcode, InstructionData};
pub use ir::stackslot::StackSlotData;

View File

@@ -1,4 +1,3 @@
//! Common types for the Cretonne code generator.
use std::default::Default;
@@ -229,108 +228,6 @@ impl Default 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.
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Signature {
pub argument_types: Vec<ArgumentType>,
pub return_types: Vec<ArgumentType>,
}
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<ArgumentType>) -> 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::*;
@@ -442,28 +339,4 @@ mod tests {
assert_eq!(I8.by(512), None);
assert_eq!(VOID.by(4), None);
}
#[test]
fn argument_type() {
let mut t = ArgumentType::new(I32);
assert_eq!(t.to_string(), "i32");
t.extension = ArgumentExtension::Uext;
assert_eq!(t.to_string(), "i32 uext");
t.inreg = true;
assert_eq!(t.to_string(), "i32 uext inreg");
}
#[test]
fn signatures() {
let mut sig = Signature::new();
assert_eq!(sig.to_string(), "()");
sig.argument_types.push(ArgumentType::new(I32));
assert_eq!(sig.to_string(), "(i32)");
sig.return_types.push(ArgumentType::new(F32));
assert_eq!(sig.to_string(), "(i32) -> f32");
sig.argument_types.push(ArgumentType::new(I32.by(4).unwrap()));
assert_eq!(sig.to_string(), "(i32, i32x4) -> f32");
sig.return_types.push(ArgumentType::new(B8));
assert_eq!(sig.to_string(), "(i32, i32x4) -> f32, b8");
}
}

View File

@@ -9,8 +9,8 @@ use std::str::FromStr;
use std::u32;
use std::mem;
use cretonne::ir::{Function, Ebb, Opcode, Value, Type, FunctionName, StackSlotData, JumpTable,
JumpTableData};
use cretonne::ir::types::{VOID, Signature, ArgumentType, ArgumentExtension};
JumpTableData, Signature, ArgumentType, ArgumentExtension};
use cretonne::ir::types::VOID;
use cretonne::ir::immediates::{Imm64, Ieee32, Ieee64};
use cretonne::ir::entities::{AnyEntity, NO_EBB, NO_INST, NO_VALUE};
use cretonne::ir::instructions::{InstructionFormat, InstructionData, VariableArgs,
@@ -1202,7 +1202,8 @@ impl<'a> Parser<'a> {
#[cfg(test)]
mod tests {
use super::*;
use cretonne::ir::types::{self, ArgumentType, ArgumentExtension};
use cretonne::ir::{ArgumentType, ArgumentExtension};
use cretonne::ir::types;
use cretonne::ir::entities::AnyEntity;
use testfile::{Details, Comment};
use isaspec::IsaSpec;