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:
135
src/libcretonne/ir/extfunc.rs
Normal file
135
src/libcretonne/ir/extfunc.rs
Normal 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,9 +11,11 @@ pub mod dfg;
|
|||||||
pub mod layout;
|
pub mod layout;
|
||||||
pub mod function;
|
pub mod function;
|
||||||
mod funcname;
|
mod funcname;
|
||||||
|
mod extfunc;
|
||||||
|
|
||||||
pub use ir::funcname::FunctionName;
|
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::entities::{Ebb, Inst, Value, StackSlot, JumpTable};
|
||||||
pub use ir::instructions::{Opcode, InstructionData};
|
pub use ir::instructions::{Opcode, InstructionData};
|
||||||
pub use ir::stackslot::StackSlotData;
|
pub use ir::stackslot::StackSlotData;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
//! Common types for the Cretonne code generator.
|
//! Common types for the Cretonne code generator.
|
||||||
|
|
||||||
use std::default::Default;
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@@ -442,28 +339,4 @@ mod tests {
|
|||||||
assert_eq!(I8.by(512), None);
|
assert_eq!(I8.by(512), None);
|
||||||
assert_eq!(VOID.by(4), 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");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ use std::str::FromStr;
|
|||||||
use std::u32;
|
use std::u32;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use cretonne::ir::{Function, Ebb, Opcode, Value, Type, FunctionName, StackSlotData, JumpTable,
|
use cretonne::ir::{Function, Ebb, Opcode, Value, Type, FunctionName, StackSlotData, JumpTable,
|
||||||
JumpTableData};
|
JumpTableData, Signature, ArgumentType, ArgumentExtension};
|
||||||
use cretonne::ir::types::{VOID, Signature, ArgumentType, ArgumentExtension};
|
use cretonne::ir::types::VOID;
|
||||||
use cretonne::ir::immediates::{Imm64, Ieee32, Ieee64};
|
use cretonne::ir::immediates::{Imm64, Ieee32, Ieee64};
|
||||||
use cretonne::ir::entities::{AnyEntity, NO_EBB, NO_INST, NO_VALUE};
|
use cretonne::ir::entities::{AnyEntity, NO_EBB, NO_INST, NO_VALUE};
|
||||||
use cretonne::ir::instructions::{InstructionFormat, InstructionData, VariableArgs,
|
use cretonne::ir::instructions::{InstructionFormat, InstructionData, VariableArgs,
|
||||||
@@ -1202,7 +1202,8 @@ impl<'a> Parser<'a> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use cretonne::ir::types::{self, ArgumentType, ArgumentExtension};
|
use cretonne::ir::{ArgumentType, ArgumentExtension};
|
||||||
|
use cretonne::ir::types;
|
||||||
use cretonne::ir::entities::AnyEntity;
|
use cretonne::ir::entities::AnyEntity;
|
||||||
use testfile::{Details, Comment};
|
use testfile::{Details, Comment};
|
||||||
use isaspec::IsaSpec;
|
use isaspec::IsaSpec;
|
||||||
|
|||||||
Reference in New Issue
Block a user