Use the term "Function parameter" instead of "argument".

Rename the ArgumentType type to AbiParam since it describes the ABI
characteristics of a parameter or return value, not just the value type.

In Signature, rename members argument_types and return_types to "params"
and "returns". Again, they are not just types.

Fix a couple lingering references to "EBB arguments".
This commit is contained in:
Jakob Stoklund Olesen
2017-10-19 17:39:23 -07:00
parent 921bcc6c25
commit b3fb41087e
23 changed files with 225 additions and 255 deletions

View File

@@ -3,7 +3,7 @@
//! This module provides functions and data structures that are useful for implementing the //! This module provides functions and data structures that are useful for implementing the
//! `TargetIsa::legalize_signature()` method. //! `TargetIsa::legalize_signature()` method.
use ir::{ArgumentLoc, ArgumentType, ArgumentExtension, Type}; use ir::{ArgumentLoc, AbiParam, ArgumentExtension, Type};
use std::cmp::Ordering; use std::cmp::Ordering;
/// Legalization action to perform on a single argument or return value when converting a /// Legalization action to perform on a single argument or return value when converting a
@@ -81,13 +81,13 @@ impl ValueConversion {
/// This will be implemented by individual ISAs. /// This will be implemented by individual ISAs.
pub trait ArgAssigner { pub trait ArgAssigner {
/// Pick an assignment action for function argument (or return value) `arg`. /// Pick an assignment action for function argument (or return value) `arg`.
fn assign(&mut self, arg: &ArgumentType) -> ArgAction; fn assign(&mut self, arg: &AbiParam) -> ArgAction;
} }
/// Legalize the arguments in `args` using the given argument assigner. /// Legalize the arguments in `args` using the given argument assigner.
/// ///
/// This function can be used for both arguments and return values. /// This function can be used for both arguments and return values.
pub fn legalize_args<AA: ArgAssigner>(args: &mut Vec<ArgumentType>, aa: &mut AA) { pub fn legalize_args<AA: ArgAssigner>(args: &mut Vec<AbiParam>, aa: &mut AA) {
// Iterate over the arguments. // Iterate over the arguments.
// We may need to mutate the vector in place, so don't use a normal iterator, and clone the // We may need to mutate the vector in place, so don't use a normal iterator, and clone the
// argument to avoid holding a reference. // argument to avoid holding a reference.
@@ -108,7 +108,7 @@ pub fn legalize_args<AA: ArgAssigner>(args: &mut Vec<ArgumentType>, aa: &mut AA)
} }
// Split this argument into two smaller ones. Then revisit both. // Split this argument into two smaller ones. Then revisit both.
ArgAction::Convert(conv) => { ArgAction::Convert(conv) => {
let new_arg = ArgumentType { let new_arg = AbiParam {
value_type: conv.apply(arg.value_type), value_type: conv.apply(arg.value_type),
..arg ..arg
}; };
@@ -143,7 +143,7 @@ pub fn legalize_args<AA: ArgAssigner>(args: &mut Vec<ArgumentType>, aa: &mut AA)
/// It may be necessary to call `legalize_abi_value` more than once for a given argument before the /// It may be necessary to call `legalize_abi_value` more than once for a given argument before the
/// desired argument type appears. This will happen when a vector or integer type needs to be split /// desired argument type appears. This will happen when a vector or integer type needs to be split
/// more than once, for example. /// more than once, for example.
pub fn legalize_abi_value(have: Type, arg: &ArgumentType) -> ValueConversion { pub fn legalize_abi_value(have: Type, arg: &AbiParam) -> ValueConversion {
let have_bits = have.bits(); let have_bits = have.bits();
let arg_bits = arg.value_type.bits(); let arg_bits = arg.value_type.bits();
@@ -186,11 +186,11 @@ pub fn legalize_abi_value(have: Type, arg: &ArgumentType) -> ValueConversion {
mod tests { mod tests {
use super::*; use super::*;
use ir::types; use ir::types;
use ir::ArgumentType; use ir::AbiParam;
#[test] #[test]
fn legalize() { fn legalize() {
let mut arg = ArgumentType::new(types::I32); let mut arg = AbiParam::new(types::I32);
assert_eq!( assert_eq!(
legalize_abi_value(types::I64X2, &arg), legalize_abi_value(types::I64X2, &arg),

View File

@@ -463,10 +463,10 @@ impl DataFlowGraph {
// Get the call signature if this is a function call. // Get the call signature if this is a function call.
if let Some(sig) = self.call_signature(inst) { if let Some(sig) = self.call_signature(inst) {
// Create result values corresponding to the call return types. // Create result values corresponding to the call return types.
let var_results = self.signatures[sig].return_types.len(); let var_results = self.signatures[sig].returns.len();
total_results += var_results; total_results += var_results;
for res_idx in 0..var_results { for res_idx in 0..var_results {
let ty = self.signatures[sig].return_types[res_idx].value_type; let ty = self.signatures[sig].returns[res_idx].value_type;
if let Some(Some(v)) = reuse.next() { if let Some(Some(v)) = reuse.next() {
debug_assert_eq!(self.value_type(v), ty, "Reused {} is wrong type", ty); debug_assert_eq!(self.value_type(v), ty, "Reused {} is wrong type", ty);
self.attach_result(inst, v); self.attach_result(inst, v);
@@ -632,7 +632,7 @@ impl DataFlowGraph {
// Not a fixed result, try to extract a return type from the call signature. // Not a fixed result, try to extract a return type from the call signature.
self.call_signature(inst).and_then(|sigref| { self.call_signature(inst).and_then(|sigref| {
self.signatures[sigref] self.signatures[sigref]
.return_types .returns
.get(result_idx - fixed_results) .get(result_idx - fixed_results)
.map(|&arg| arg.value_type) .map(|&arg| arg.value_type)
}) })

View File

@@ -13,17 +13,17 @@ use std::str::FromStr;
/// Function signature. /// Function signature.
/// ///
/// The function signature describes the types of arguments and return values along with other /// The function signature describes the types of formal parameters and return values along with
/// details that are needed to call a function correctly. /// other details that are needed to call a function correctly.
/// ///
/// A signature can optionally include ISA-specific ABI information which specifies exactly how /// A signature can optionally include ISA-specific ABI information which specifies exactly how
/// arguments and return values are passed. /// arguments and return values are passed.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Signature { pub struct Signature {
/// Types of the arguments passed to the function. /// The arguments passed to the function.
pub argument_types: Vec<ArgumentType>, pub params: Vec<AbiParam>,
/// Types returned from the function. /// Values returned from the function.
pub return_types: Vec<ArgumentType>, pub returns: Vec<AbiParam>,
/// Calling convention. /// Calling convention.
pub call_conv: CallConv, pub call_conv: CallConv,
@@ -31,7 +31,7 @@ pub struct Signature {
/// When the signature has been legalized to a specific ISA, this holds the size of the /// When the signature has been legalized to a specific ISA, this holds the size of the
/// argument array on the stack. Before legalization, this is `None`. /// argument array on the stack. Before legalization, this is `None`.
/// ///
/// This can be computed from the legalized `argument_types` array as the maximum (offset plus /// This can be computed from the legalized `params` array as the maximum (offset plus
/// byte size) of the `ArgumentLoc::Stack(offset)` argument. /// byte size) of the `ArgumentLoc::Stack(offset)` argument.
pub argument_bytes: Option<u32>, pub argument_bytes: Option<u32>,
} }
@@ -40,8 +40,8 @@ impl Signature {
/// Create a new blank signature. /// Create a new blank signature.
pub fn new(call_conv: CallConv) -> Signature { pub fn new(call_conv: CallConv) -> Signature {
Signature { Signature {
argument_types: Vec::new(), params: Vec::new(),
return_types: Vec::new(), returns: Vec::new(),
call_conv, call_conv,
argument_bytes: None, argument_bytes: None,
} }
@@ -49,18 +49,18 @@ impl Signature {
/// Clear the signature so it is identical to a fresh one returned by `new()`. /// Clear the signature so it is identical to a fresh one returned by `new()`.
pub fn clear(&mut self, call_conv: CallConv) { pub fn clear(&mut self, call_conv: CallConv) {
self.argument_types.clear(); self.params.clear();
self.return_types.clear(); self.returns.clear();
self.call_conv = call_conv; self.call_conv = call_conv;
self.argument_bytes = None; self.argument_bytes = None;
} }
/// Compute the size of the stack arguments and mark signature as legalized. /// Compute the size of the stack arguments and mark signature as legalized.
/// ///
/// Even if there are no stack arguments, this will set `argument_types` to `Some(0)` instead /// Even if there are no stack arguments, this will set `params` to `Some(0)` instead
/// of `None`. This indicates that the signature has been legalized. /// of `None`. This indicates that the signature has been legalized.
pub fn compute_argument_bytes(&mut self) { pub fn compute_argument_bytes(&mut self) {
let bytes = self.argument_types let bytes = self.params
.iter() .iter()
.filter_map(|arg| match arg.location { .filter_map(|arg| match arg.location {
ArgumentLoc::Stack(offset) if offset >= 0 => { ArgumentLoc::Stack(offset) if offset >= 0 => {
@@ -77,22 +77,16 @@ impl Signature {
DisplaySignature(self, regs.into()) DisplaySignature(self, regs.into())
} }
/// Find the index of a presumed unique special-purpose argument. /// Find the index of a presumed unique special-purpose parameter.
pub fn special_arg_index(&self, purpose: ArgumentPurpose) -> Option<usize> { pub fn special_param_index(&self, purpose: ArgumentPurpose) -> Option<usize> {
self.argument_types.iter().rposition( self.params.iter().rposition(|arg| arg.purpose == purpose)
|arg| arg.purpose == purpose,
)
} }
} }
/// Wrapper type capable of displaying a `Signature` with correct register names. /// Wrapper type capable of displaying a `Signature` with correct register names.
pub struct DisplaySignature<'a>(&'a Signature, Option<&'a RegInfo>); pub struct DisplaySignature<'a>(&'a Signature, Option<&'a RegInfo>);
fn write_list( fn write_list(f: &mut fmt::Formatter, args: &[AbiParam], regs: Option<&RegInfo>) -> fmt::Result {
f: &mut fmt::Formatter,
args: &[ArgumentType],
regs: Option<&RegInfo>,
) -> fmt::Result {
match args.split_first() { match args.split_first() {
None => {} None => {}
Some((first, rest)) => { Some((first, rest)) => {
@@ -108,11 +102,11 @@ fn write_list(
impl<'a> fmt::Display for DisplaySignature<'a> { impl<'a> fmt::Display for DisplaySignature<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "(")?; write!(f, "(")?;
write_list(f, &self.0.argument_types, self.1)?; write_list(f, &self.0.params, self.1)?;
write!(f, ")")?; write!(f, ")")?;
if !self.0.return_types.is_empty() { if !self.0.returns.is_empty() {
write!(f, " -> ")?; write!(f, " -> ")?;
write_list(f, &self.0.return_types, self.1)?; write_list(f, &self.0.returns, self.1)?;
} }
write!(f, " {}", self.0.call_conv) write!(f, " {}", self.0.call_conv)
} }
@@ -124,12 +118,12 @@ impl fmt::Display for Signature {
} }
} }
/// Function argument or return value type. /// Function parameter or return value descriptor.
/// ///
/// This describes the value type being passed to or from a function along with flags that affect /// This describes the value type being passed to or from a function along with flags that affect
/// how the argument is passed. /// how the argument is passed.
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub struct ArgumentType { pub struct AbiParam {
/// Type of the argument value. /// Type of the argument value.
pub value_type: Type, pub value_type: Type,
/// Special purpose of argument, or `Normal`. /// Special purpose of argument, or `Normal`.
@@ -142,10 +136,10 @@ pub struct ArgumentType {
pub location: ArgumentLoc, pub location: ArgumentLoc,
} }
impl ArgumentType { impl AbiParam {
/// Create an argument type with default flags. /// Create a parameter with default flags.
pub fn new(vt: Type) -> ArgumentType { pub fn new(vt: Type) -> AbiParam {
ArgumentType { AbiParam {
value_type: vt, value_type: vt,
extension: ArgumentExtension::None, extension: ArgumentExtension::None,
purpose: ArgumentPurpose::Normal, purpose: ArgumentPurpose::Normal,
@@ -153,9 +147,9 @@ impl ArgumentType {
} }
} }
/// Create a special-purpose argument type that is not (yet) bound to a specific register. /// Create a special-purpose parameter that is not (yet) bound to a specific register.
pub fn special(vt: Type, purpose: ArgumentPurpose) -> ArgumentType { pub fn special(vt: Type, purpose: ArgumentPurpose) -> AbiParam {
ArgumentType { AbiParam {
value_type: vt, value_type: vt,
extension: ArgumentExtension::None, extension: ArgumentExtension::None,
purpose, purpose,
@@ -163,9 +157,9 @@ impl ArgumentType {
} }
} }
/// Create an argument type for a special-purpose register. /// Create a parameter for a special-purpose register.
pub fn special_reg(vt: Type, purpose: ArgumentPurpose, regunit: RegUnit) -> ArgumentType { pub fn special_reg(vt: Type, purpose: ArgumentPurpose, regunit: RegUnit) -> AbiParam {
ArgumentType { AbiParam {
value_type: vt, value_type: vt,
extension: ArgumentExtension::None, extension: ArgumentExtension::None,
purpose, purpose,
@@ -173,34 +167,34 @@ impl ArgumentType {
} }
} }
/// Convert `self` to an argument type with the `uext` flag set. /// Convert `self` to a parameter with the `uext` flag set.
pub fn uext(self) -> ArgumentType { pub fn uext(self) -> AbiParam {
debug_assert!(self.value_type.is_int(), "uext on {} arg", self.value_type); debug_assert!(self.value_type.is_int(), "uext on {} arg", self.value_type);
ArgumentType { AbiParam {
extension: ArgumentExtension::Uext, extension: ArgumentExtension::Uext,
..self ..self
} }
} }
/// Convert `self` to an argument type with the `sext` flag set. /// Convert `self` to a parameter type with the `sext` flag set.
pub fn sext(self) -> ArgumentType { pub fn sext(self) -> AbiParam {
debug_assert!(self.value_type.is_int(), "sext on {} arg", self.value_type); debug_assert!(self.value_type.is_int(), "sext on {} arg", self.value_type);
ArgumentType { AbiParam {
extension: ArgumentExtension::Sext, extension: ArgumentExtension::Sext,
..self ..self
} }
} }
/// Return an object that can display `self` with correct register names. /// Return an object that can display `self` with correct register names.
pub fn display<'a, R: Into<Option<&'a RegInfo>>>(&'a self, regs: R) -> DisplayArgumentType<'a> { pub fn display<'a, R: Into<Option<&'a RegInfo>>>(&'a self, regs: R) -> DisplayAbiParam<'a> {
DisplayArgumentType(self, regs.into()) DisplayAbiParam(self, regs.into())
} }
} }
/// Wrapper type capable of displaying an `ArgumentType` with correct register names. /// Wrapper type capable of displaying a `AbiParam` with correct register names.
pub struct DisplayArgumentType<'a>(&'a ArgumentType, Option<&'a RegInfo>); pub struct DisplayAbiParam<'a>(&'a AbiParam, Option<&'a RegInfo>);
impl<'a> fmt::Display for DisplayArgumentType<'a> { impl<'a> fmt::Display for DisplayAbiParam<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0.value_type)?; write!(f, "{}", self.0.value_type)?;
match self.0.extension { match self.0.extension {
@@ -220,7 +214,7 @@ impl<'a> fmt::Display for DisplayArgumentType<'a> {
} }
} }
impl fmt::Display for ArgumentType { impl fmt::Display for AbiParam {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.display(None).fmt(f) self.display(None).fmt(f)
} }
@@ -387,7 +381,7 @@ mod tests {
#[test] #[test]
fn argument_type() { fn argument_type() {
let t = ArgumentType::new(I32); let t = AbiParam::new(I32);
assert_eq!(t.to_string(), "i32"); assert_eq!(t.to_string(), "i32");
let mut t = t.uext(); let mut t = t.uext();
assert_eq!(t.to_string(), "i32 uext"); assert_eq!(t.to_string(), "i32 uext");
@@ -423,25 +417,23 @@ mod tests {
fn signatures() { fn signatures() {
let mut sig = Signature::new(CallConv::SpiderWASM); let mut sig = Signature::new(CallConv::SpiderWASM);
assert_eq!(sig.to_string(), "() spiderwasm"); assert_eq!(sig.to_string(), "() spiderwasm");
sig.argument_types.push(ArgumentType::new(I32)); sig.params.push(AbiParam::new(I32));
assert_eq!(sig.to_string(), "(i32) spiderwasm"); assert_eq!(sig.to_string(), "(i32) spiderwasm");
sig.return_types.push(ArgumentType::new(F32)); sig.returns.push(AbiParam::new(F32));
assert_eq!(sig.to_string(), "(i32) -> f32 spiderwasm"); assert_eq!(sig.to_string(), "(i32) -> f32 spiderwasm");
sig.argument_types.push( sig.params.push(AbiParam::new(I32.by(4).unwrap()));
ArgumentType::new(I32.by(4).unwrap()),
);
assert_eq!(sig.to_string(), "(i32, i32x4) -> f32 spiderwasm"); assert_eq!(sig.to_string(), "(i32, i32x4) -> f32 spiderwasm");
sig.return_types.push(ArgumentType::new(B8)); sig.returns.push(AbiParam::new(B8));
assert_eq!(sig.to_string(), "(i32, i32x4) -> f32, b8 spiderwasm"); assert_eq!(sig.to_string(), "(i32, i32x4) -> f32, b8 spiderwasm");
// Test the offset computation algorithm. // Test the offset computation algorithm.
assert_eq!(sig.argument_bytes, None); assert_eq!(sig.argument_bytes, None);
sig.argument_types[1].location = ArgumentLoc::Stack(8); sig.params[1].location = ArgumentLoc::Stack(8);
sig.compute_argument_bytes(); sig.compute_argument_bytes();
// An `i32x4` at offset 8 requires a 24-byte argument array. // An `i32x4` at offset 8 requires a 24-byte argument array.
assert_eq!(sig.argument_bytes, Some(24)); assert_eq!(sig.argument_bytes, Some(24));
// Order does not matter. // Order does not matter.
sig.argument_types[0].location = ArgumentLoc::Stack(24); sig.params[0].location = ArgumentLoc::Stack(24);
sig.compute_argument_bytes(); sig.compute_argument_bytes();
assert_eq!(sig.argument_bytes, Some(28)); assert_eq!(sig.argument_bytes, Some(28));

View File

@@ -144,12 +144,12 @@ impl Function {
DisplayFunction(self, isa.into()) DisplayFunction(self, isa.into())
} }
/// Find a presumed unique special-purpose function argument value. /// Find a presumed unique special-purpose function parameter value.
/// ///
/// Returns the value of the last `purpose` argument, or `None` if no such argument exists. /// Returns the value of the last `purpose` parameter, or `None` if no such parameter exists.
pub fn special_arg(&self, purpose: ir::ArgumentPurpose) -> Option<ir::Value> { pub fn special_param(&self, purpose: ir::ArgumentPurpose) -> Option<ir::Value> {
let entry = self.layout.entry_block().expect("Function is empty"); let entry = self.layout.entry_block().expect("Function is empty");
self.signature.special_arg_index(purpose).map(|i| { self.signature.special_param_index(purpose).map(|i| {
self.dfg.ebb_params(entry)[i] self.dfg.ebb_params(entry)[i]
}) })
} }

View File

@@ -24,7 +24,7 @@ mod valueloc;
pub use ir::builder::{InstBuilder, InstBuilderBase, InstInserterBase, InsertBuilder}; pub use ir::builder::{InstBuilder, InstBuilderBase, InstInserterBase, InsertBuilder};
pub use ir::dfg::{DataFlowGraph, ValueDef}; pub use ir::dfg::{DataFlowGraph, ValueDef};
pub use ir::entities::{Ebb, Inst, Value, StackSlot, GlobalVar, JumpTable, FuncRef, SigRef, Heap}; pub use ir::entities::{Ebb, Inst, Value, StackSlot, GlobalVar, JumpTable, FuncRef, SigRef, Heap};
pub use ir::extfunc::{Signature, CallConv, ArgumentType, ArgumentExtension, ArgumentPurpose, pub use ir::extfunc::{Signature, CallConv, AbiParam, ArgumentExtension, ArgumentPurpose,
ExtFuncData}; ExtFuncData};
pub use ir::funcname::FunctionName; pub use ir::funcname::FunctionName;
pub use ir::function::Function; pub use ir::function::Function;

View File

@@ -6,7 +6,7 @@ use regalloc::AllocatableSet;
use settings as shared_settings; use settings as shared_settings;
use super::registers::{GPR, FPR, RU}; use super::registers::{GPR, FPR, RU};
use abi::{ArgAction, ValueConversion, ArgAssigner, legalize_args}; use abi::{ArgAction, ValueConversion, ArgAssigner, legalize_args};
use ir::{ArgumentType, ArgumentPurpose, ArgumentLoc, ArgumentExtension}; use ir::{AbiParam, ArgumentPurpose, ArgumentLoc, ArgumentExtension};
/// Argument registers for x86-64 /// Argument registers for x86-64
static ARG_GPRS: [RU; 6] = [RU::rdi, RU::rsi, RU::rdx, RU::rcx, RU::r8, RU::r9]; static ARG_GPRS: [RU; 6] = [RU::rdi, RU::rsi, RU::rdx, RU::rcx, RU::r8, RU::r9];
@@ -41,7 +41,7 @@ impl Args {
} }
impl ArgAssigner for Args { impl ArgAssigner for Args {
fn assign(&mut self, arg: &ArgumentType) -> ArgAction { fn assign(&mut self, arg: &AbiParam) -> ArgAction {
let ty = arg.value_type; let ty = arg.value_type;
// Check for a legal type. // Check for a legal type.
@@ -117,10 +117,10 @@ pub fn legalize_signature(sig: &mut ir::Signature, flags: &shared_settings::Flag
args = Args::new(bits, &[], 0); args = Args::new(bits, &[], 0);
} }
legalize_args(&mut sig.argument_types, &mut args); legalize_args(&mut sig.params, &mut args);
let mut rets = Args::new(bits, &RET_GPRS, 2); let mut rets = Args::new(bits, &RET_GPRS, 2);
legalize_args(&mut sig.return_types, &mut rets); legalize_args(&mut sig.returns, &mut rets);
} }
/// Get register class for a type appearing in a legalized signature. /// Get register class for a type appearing in a legalized signature.

View File

@@ -6,7 +6,7 @@
//! This doesn't support the soft-float ABI at the moment. //! This doesn't support the soft-float ABI at the moment.
use abi::{ArgAction, ValueConversion, ArgAssigner, legalize_args}; use abi::{ArgAction, ValueConversion, ArgAssigner, legalize_args};
use ir::{self, Type, ArgumentType, ArgumentLoc, ArgumentExtension, ArgumentPurpose}; use ir::{self, Type, AbiParam, ArgumentLoc, ArgumentExtension, ArgumentPurpose};
use isa::RegClass; use isa::RegClass;
use regalloc::AllocatableSet; use regalloc::AllocatableSet;
use settings as shared_settings; use settings as shared_settings;
@@ -36,7 +36,7 @@ impl Args {
} }
impl ArgAssigner for Args { impl ArgAssigner for Args {
fn assign(&mut self, arg: &ArgumentType) -> ArgAction { fn assign(&mut self, arg: &AbiParam) -> ArgAction {
fn align(value: u32, to: u32) -> u32 { fn align(value: u32, to: u32) -> u32 {
(value + to - 1) & !(to - 1) (value + to - 1) & !(to - 1)
} }
@@ -95,10 +95,10 @@ pub fn legalize_signature(
let bits = if flags.is_64bit() { 64 } else { 32 }; let bits = if flags.is_64bit() { 64 } else { 32 };
let mut args = Args::new(bits, isa_flags.enable_e()); let mut args = Args::new(bits, isa_flags.enable_e());
legalize_args(&mut sig.argument_types, &mut args); legalize_args(&mut sig.params, &mut args);
let mut rets = Args::new(bits, isa_flags.enable_e()); let mut rets = Args::new(bits, isa_flags.enable_e());
legalize_args(&mut sig.return_types, &mut rets); legalize_args(&mut sig.returns, &mut rets);
if current { if current {
let ptr = Type::int(bits).unwrap(); let ptr = Type::int(bits).unwrap();
@@ -108,9 +108,9 @@ pub fn legalize_signature(
// The `jalr` instruction implementing a return can technically accept the return address // The `jalr` instruction implementing a return can technically accept the return address
// in any register, but a micro-architecture with a return address predictor will only // in any register, but a micro-architecture with a return address predictor will only
// recognize it as a return if the address is in `x1`. // recognize it as a return if the address is in `x1`.
let link = ArgumentType::special_reg(ptr, ArgumentPurpose::Link, GPR.unit(1)); let link = AbiParam::special_reg(ptr, ArgumentPurpose::Link, GPR.unit(1));
sig.argument_types.push(link); sig.params.push(link);
sig.return_types.push(link); sig.returns.push(link);
} }
} }

View File

@@ -21,7 +21,7 @@ use abi::{legalize_abi_value, ValueConversion};
use cursor::{Cursor, FuncCursor}; use cursor::{Cursor, FuncCursor};
use flowgraph::ControlFlowGraph; use flowgraph::ControlFlowGraph;
use ir::{Function, DataFlowGraph, Inst, InstBuilder, Ebb, Type, Value, Signature, SigRef, use ir::{Function, DataFlowGraph, Inst, InstBuilder, Ebb, Type, Value, Signature, SigRef,
ArgumentType, ArgumentPurpose, ArgumentLoc, ValueLoc}; AbiParam, ArgumentPurpose, ArgumentLoc, ValueLoc};
use ir::instructions::CallInfo; use ir::instructions::CallInfo;
use isa::TargetIsa; use isa::TargetIsa;
use legalizer::split::{isplit, vsplit}; use legalizer::split::{isplit, vsplit};
@@ -40,20 +40,20 @@ pub fn legalize_signatures(func: &mut Function, isa: &TargetIsa) {
} }
if let Some(entry) = func.layout.entry_block() { if let Some(entry) = func.layout.entry_block() {
legalize_entry_arguments(func, entry); legalize_entry_params(func, entry);
spill_entry_arguments(func, entry); spill_entry_params(func, entry);
} }
} }
/// Legalize the entry block arguments after `func`'s signature has been legalized. /// Legalize the entry block parameters after `func`'s signature has been legalized.
/// ///
/// The legalized signature may contain more arguments than the original signature, and the /// The legalized signature may contain more parameters than the original signature, and the
/// argument types have been changed. This function goes through the arguments to the entry EBB and /// parameter types have been changed. This function goes through the parameters of the entry EBB
/// replaces them with arguments of the right type for the ABI. /// and replaces them with parameters of the right type for the ABI.
/// ///
/// The original entry EBB arguments are computed from the new ABI arguments by code inserted at /// The original entry EBB parameters are computed from the new ABI parameters by code inserted at
/// the top of the entry block. /// the top of the entry block.
fn legalize_entry_arguments(func: &mut Function, entry: Ebb) { fn legalize_entry_params(func: &mut Function, entry: Ebb) {
let mut has_sret = false; let mut has_sret = false;
let mut has_link = false; let mut has_link = false;
let mut has_vmctx = false; let mut has_vmctx = false;
@@ -74,7 +74,7 @@ fn legalize_entry_arguments(func: &mut Function, entry: Ebb) {
while let Some(arg) = ebb_params.get(old_arg, &pos.func.dfg.value_lists) { while let Some(arg) = ebb_params.get(old_arg, &pos.func.dfg.value_lists) {
old_arg += 1; old_arg += 1;
let abi_type = pos.func.signature.argument_types[abi_arg]; let abi_type = pos.func.signature.params[abi_arg];
let arg_type = pos.func.dfg.value_type(arg); let arg_type = pos.func.dfg.value_type(arg);
if arg_type == abi_type.value_type { if arg_type == abi_type.value_type {
// No value translation is necessary, this argument matches the ABI type. // No value translation is necessary, this argument matches the ABI type.
@@ -98,9 +98,9 @@ fn legalize_entry_arguments(func: &mut Function, entry: Ebb) {
} }
abi_arg += 1; abi_arg += 1;
} else { } else {
// Compute the value we want for `arg` from the legalized ABI arguments. // Compute the value we want for `arg` from the legalized ABI parameters.
let mut get_arg = |func: &mut Function, ty| { let mut get_arg = |func: &mut Function, ty| {
let abi_type = func.signature.argument_types[abi_arg]; let abi_type = func.signature.params[abi_arg];
assert_eq!( assert_eq!(
abi_type.purpose, abi_type.purpose,
ArgumentPurpose::Normal, ArgumentPurpose::Normal,
@@ -120,15 +120,15 @@ fn legalize_entry_arguments(func: &mut Function, entry: Ebb) {
} }
} }
// The legalized signature may contain additional arguments representing special-purpose // The legalized signature may contain additional parameters representing special-purpose
// registers. // registers.
for &arg in &pos.func.signature.argument_types[abi_arg..] { for &arg in &pos.func.signature.params[abi_arg..] {
match arg.purpose { match arg.purpose {
// Any normal arguments should have been processed above. // Any normal parameters should have been processed above.
ArgumentPurpose::Normal => { ArgumentPurpose::Normal => {
panic!("Leftover arg: {}", arg); panic!("Leftover arg: {}", arg);
} }
// The callee-save arguments should not appear until after register allocation is // The callee-save parameters should not appear until after register allocation is
// done. // done.
ArgumentPurpose::FramePointer | ArgumentPurpose::FramePointer |
ArgumentPurpose::CalleeSaved => { ArgumentPurpose::CalleeSaved => {
@@ -136,19 +136,19 @@ fn legalize_entry_arguments(func: &mut Function, entry: Ebb) {
} }
// These can be meaningfully added by `legalize_signature()`. // These can be meaningfully added by `legalize_signature()`.
ArgumentPurpose::Link => { ArgumentPurpose::Link => {
assert!(!has_link, "Multiple link arguments found"); assert!(!has_link, "Multiple link parameters found");
has_link = true; has_link = true;
} }
ArgumentPurpose::StructReturn => { ArgumentPurpose::StructReturn => {
assert!(!has_sret, "Multiple sret arguments found"); assert!(!has_sret, "Multiple sret parameters found");
has_sret = true; has_sret = true;
} }
ArgumentPurpose::VMContext => { ArgumentPurpose::VMContext => {
assert!(!has_vmctx, "Multiple vmctx arguments found"); assert!(!has_vmctx, "Multiple vmctx parameters found");
has_vmctx = true; has_vmctx = true;
} }
ArgumentPurpose::SignatureId => { ArgumentPurpose::SignatureId => {
assert!(!has_sigid, "Multiple sigid arguments found"); assert!(!has_sigid, "Multiple sigid parameters found");
has_sigid = true; has_sigid = true;
} }
} }
@@ -164,12 +164,12 @@ fn legalize_entry_arguments(func: &mut Function, entry: Ebb) {
/// The cursor `pos` points to a call instruction with at least one return value. The cursor will /// The cursor `pos` points to a call instruction with at least one return value. The cursor will
/// be left pointing after the instructions inserted to convert the return values. /// be left pointing after the instructions inserted to convert the return values.
/// ///
/// This function is very similar to the `legalize_entry_arguments` function above. /// This function is very similar to the `legalize_entry_params` function above.
/// ///
/// Returns the possibly new instruction representing the call. /// Returns the possibly new instruction representing the call.
fn legalize_inst_results<ResType>(pos: &mut FuncCursor, mut get_abi_type: ResType) -> Inst fn legalize_inst_results<ResType>(pos: &mut FuncCursor, mut get_abi_type: ResType) -> Inst
where where
ResType: FnMut(&Function, usize) -> ArgumentType, ResType: FnMut(&Function, usize) -> AbiParam,
{ {
let call = pos.current_inst().expect( let call = pos.current_inst().expect(
"Cursor must point to a call instruction", "Cursor must point to a call instruction",
@@ -230,7 +230,7 @@ fn convert_from_abi<GetArg>(
get_arg: &mut GetArg, get_arg: &mut GetArg,
) -> Value ) -> Value
where where
GetArg: FnMut(&mut Function, Type) -> Result<Value, ArgumentType>, GetArg: FnMut(&mut Function, Type) -> Result<Value, AbiParam>,
{ {
// Terminate the recursion when we get the desired type. // Terminate the recursion when we get the desired type.
let arg_type = match get_arg(pos.func, ty) { let arg_type = match get_arg(pos.func, ty) {
@@ -304,7 +304,7 @@ where
/// 1. If the suggested argument has an acceptable value type, consume it by adding it to the list /// 1. If the suggested argument has an acceptable value type, consume it by adding it to the list
/// of arguments and return `Ok(())`. /// of arguments and return `Ok(())`.
/// 2. If the suggested argument doesn't have the right value type, don't change anything, but /// 2. If the suggested argument doesn't have the right value type, don't change anything, but
/// return the `Err(ArgumentType)` that is needed. /// return the `Err(AbiParam)` that is needed.
/// ///
fn convert_to_abi<PutArg>( fn convert_to_abi<PutArg>(
pos: &mut FuncCursor, pos: &mut FuncCursor,
@@ -312,7 +312,7 @@ fn convert_to_abi<PutArg>(
value: Value, value: Value,
put_arg: &mut PutArg, put_arg: &mut PutArg,
) where ) where
PutArg: FnMut(&mut Function, Value) -> Result<(), ArgumentType>, PutArg: FnMut(&mut Function, Value) -> Result<(), AbiParam>,
{ {
// Start by invoking the closure to either terminate the recursion or get the argument type // Start by invoking the closure to either terminate the recursion or get the argument type
// we're trying to match. // we're trying to match.
@@ -355,7 +355,7 @@ fn convert_to_abi<PutArg>(
} }
/// Check if a sequence of arguments match a desired sequence of argument types. /// Check if a sequence of arguments match a desired sequence of argument types.
fn check_arg_types(dfg: &DataFlowGraph, args: &[Value], types: &[ArgumentType]) -> bool { fn check_arg_types(dfg: &DataFlowGraph, args: &[Value], types: &[AbiParam]) -> bool {
let arg_types = args.iter().map(|&v| dfg.value_type(v)); let arg_types = args.iter().map(|&v| dfg.value_type(v));
let sig_types = types.iter().map(|&at| at.value_type); let sig_types = types.iter().map(|&at| at.value_type);
arg_types.eq(sig_types) arg_types.eq(sig_types)
@@ -374,8 +374,8 @@ fn check_call_signature(dfg: &DataFlowGraph, inst: Inst) -> Result<(), SigRef> {
}; };
let sig = &dfg.signatures[sig_ref]; let sig = &dfg.signatures[sig_ref];
if check_arg_types(dfg, args, &sig.argument_types[..]) && if check_arg_types(dfg, args, &sig.params[..]) &&
check_arg_types(dfg, dfg.inst_results(inst), &sig.return_types[..]) check_arg_types(dfg, dfg.inst_results(inst), &sig.returns[..])
{ {
// All types check out. // All types check out.
Ok(()) Ok(())
@@ -387,13 +387,13 @@ fn check_call_signature(dfg: &DataFlowGraph, inst: Inst) -> Result<(), SigRef> {
/// Check if the arguments of the return `inst` match the signature. /// Check if the arguments of the return `inst` match the signature.
fn check_return_signature(dfg: &DataFlowGraph, inst: Inst, sig: &Signature) -> bool { fn check_return_signature(dfg: &DataFlowGraph, inst: Inst, sig: &Signature) -> bool {
check_arg_types(dfg, dfg.inst_variable_args(inst), &sig.return_types) check_arg_types(dfg, dfg.inst_variable_args(inst), &sig.returns)
} }
/// Insert ABI conversion code for the arguments to the call or return instruction at `pos`. /// Insert ABI conversion code for the arguments to the call or return instruction at `pos`.
/// ///
/// - `abi_args` is the number of arguments that the ABI signature requires. /// - `abi_args` is the number of arguments that the ABI signature requires.
/// - `get_abi_type` is a closure that can provide the desired `ArgumentType` for a given ABI /// - `get_abi_type` is a closure that can provide the desired `AbiParam` for a given ABI
/// argument number in `0..abi_args`. /// argument number in `0..abi_args`.
/// ///
fn legalize_inst_arguments<ArgType>( fn legalize_inst_arguments<ArgType>(
@@ -402,7 +402,7 @@ fn legalize_inst_arguments<ArgType>(
abi_args: usize, abi_args: usize,
mut get_abi_type: ArgType, mut get_abi_type: ArgType,
) where ) where
ArgType: FnMut(&Function, usize) -> ArgumentType, ArgType: FnMut(&Function, usize) -> AbiParam,
{ {
let inst = pos.current_inst().expect( let inst = pos.current_inst().expect(
"Cursor must point to a call instruction", "Cursor must point to a call instruction",
@@ -498,14 +498,14 @@ pub fn handle_call_abi(mut inst: Inst, func: &mut Function, cfg: &ControlFlowGra
}; };
// OK, we need to fix the call arguments to match the ABI signature. // OK, we need to fix the call arguments to match the ABI signature.
let abi_args = pos.func.dfg.signatures[sig_ref].argument_types.len(); let abi_args = pos.func.dfg.signatures[sig_ref].params.len();
legalize_inst_arguments(pos, cfg, abi_args, |func, abi_arg| { legalize_inst_arguments(pos, cfg, abi_args, |func, abi_arg| {
func.dfg.signatures[sig_ref].argument_types[abi_arg] func.dfg.signatures[sig_ref].params[abi_arg]
}); });
if !pos.func.dfg.signatures[sig_ref].return_types.is_empty() { if !pos.func.dfg.signatures[sig_ref].returns.is_empty() {
inst = legalize_inst_results(pos, |func, abi_res| { inst = legalize_inst_results(pos, |func, abi_res| {
func.dfg.signatures[sig_ref].return_types[abi_res] func.dfg.signatures[sig_ref].returns[abi_res]
}); });
} }
@@ -537,7 +537,7 @@ pub fn handle_return_abi(inst: Inst, func: &mut Function, cfg: &ControlFlowGraph
// Count the special-purpose return values (`link`, `sret`, and `vmctx`) that were appended to // Count the special-purpose return values (`link`, `sret`, and `vmctx`) that were appended to
// the legalized signature. // the legalized signature.
let special_args = func.signature let special_args = func.signature
.return_types .returns
.iter() .iter()
.rev() .rev()
.take_while(|&rt| { .take_while(|&rt| {
@@ -545,13 +545,13 @@ pub fn handle_return_abi(inst: Inst, func: &mut Function, cfg: &ControlFlowGraph
rt.purpose == ArgumentPurpose::VMContext rt.purpose == ArgumentPurpose::VMContext
}) })
.count(); .count();
let abi_args = func.signature.return_types.len() - special_args; let abi_args = func.signature.returns.len() - special_args;
let pos = &mut FuncCursor::new(func).at_inst(inst); let pos = &mut FuncCursor::new(func).at_inst(inst);
pos.use_srcloc(inst); pos.use_srcloc(inst);
legalize_inst_arguments(pos, cfg, abi_args, |func, abi_arg| { legalize_inst_arguments(pos, cfg, abi_args, |func, abi_arg| {
func.signature.return_types[abi_arg] func.signature.returns[abi_arg]
}); });
assert_eq!(pos.func.dfg.inst_variable_args(inst).len(), abi_args); assert_eq!(pos.func.dfg.inst_variable_args(inst).len(), abi_args);
@@ -565,7 +565,7 @@ pub fn handle_return_abi(inst: Inst, func: &mut Function, cfg: &ControlFlowGraph
pos.func.dfg.display_inst(inst, None) pos.func.dfg.display_inst(inst, None)
); );
let mut vlist = pos.func.dfg[inst].take_value_list().unwrap(); let mut vlist = pos.func.dfg[inst].take_value_list().unwrap();
for arg in &pos.func.signature.return_types[abi_args..] { for arg in &pos.func.signature.returns[abi_args..] {
match arg.purpose { match arg.purpose {
ArgumentPurpose::Link | ArgumentPurpose::Link |
ArgumentPurpose::StructReturn | ArgumentPurpose::StructReturn |
@@ -578,7 +578,7 @@ pub fn handle_return_abi(inst: Inst, func: &mut Function, cfg: &ControlFlowGraph
// the end. // the end.
let idx = pos.func let idx = pos.func
.signature .signature
.argument_types .params
.iter() .iter()
.rposition(|t| t.purpose == arg.purpose) .rposition(|t| t.purpose == arg.purpose)
.expect("No matching special purpose argument."); .expect("No matching special purpose argument.");
@@ -605,17 +605,12 @@ pub fn handle_return_abi(inst: Inst, func: &mut Function, cfg: &ControlFlowGraph
true true
} }
/// Assign stack slots to incoming function arguments on the stack. /// Assign stack slots to incoming function parameters on the stack.
/// ///
/// Values that are passed into the function on the stack must be assigned to an `IncomingArg` /// Values that are passed into the function on the stack must be assigned to an `IncomingArg`
/// stack slot already during legalization. /// stack slot already during legalization.
fn spill_entry_arguments(func: &mut Function, entry: Ebb) { fn spill_entry_params(func: &mut Function, entry: Ebb) {
for (abi, &arg) in func.signature.argument_types.iter().zip( for (abi, &arg) in func.signature.params.iter().zip(func.dfg.ebb_params(entry)) {
func.dfg.ebb_params(
entry,
),
)
{
if let ArgumentLoc::Stack(offset) = abi.location { if let ArgumentLoc::Stack(offset) = abi.location {
let ss = func.stack_slots.make_incoming_arg(abi.value_type, offset); let ss = func.stack_slots.make_incoming_arg(abi.value_type, offset);
func.locations[arg] = ValueLoc::Stack(ss); func.locations[arg] = ValueLoc::Stack(ss);
@@ -648,7 +643,7 @@ fn spill_call_arguments(pos: &mut FuncCursor) -> bool {
.dfg .dfg
.inst_variable_args(inst) .inst_variable_args(inst)
.iter() .iter()
.zip(&pos.func.dfg.signatures[sig_ref].argument_types) .zip(&pos.func.dfg.signatures[sig_ref].params)
.enumerate() .enumerate()
.filter_map(|(idx, (&arg, abi))| { .filter_map(|(idx, (&arg, abi))| {
match abi.location { match abi.location {

View File

@@ -27,7 +27,7 @@ pub fn expand_global_addr(inst: ir::Inst, func: &mut ir::Function, _cfg: &mut Co
/// Expand a `global_addr` instruction for a vmctx global. /// Expand a `global_addr` instruction for a vmctx global.
fn vmctx_addr(inst: ir::Inst, func: &mut ir::Function, offset: i64) { fn vmctx_addr(inst: ir::Inst, func: &mut ir::Function, offset: i64) {
// Get the value representing the `vmctx` argument. // Get the value representing the `vmctx` argument.
let vmctx = func.special_arg(ir::ArgumentPurpose::VMContext).expect( let vmctx = func.special_param(ir::ArgumentPurpose::VMContext).expect(
"Missing vmctx parameter", "Missing vmctx parameter",
); );

View File

@@ -9,7 +9,7 @@
//! larger register class instead. //! larger register class instead.
use std::fmt; use std::fmt;
use ir::{ArgumentType, ArgumentLoc}; use ir::{AbiParam, ArgumentLoc};
use isa::{TargetIsa, RegInfo, RegClassIndex, OperandConstraint, ConstraintKind}; use isa::{TargetIsa, RegInfo, RegClassIndex, OperandConstraint, ConstraintKind};
/// Preferred register allocation for an SSA value. /// Preferred register allocation for an SSA value.
@@ -48,7 +48,7 @@ impl Affinity {
} }
/// Create an affinity that matches an ABI argument for `isa`. /// Create an affinity that matches an ABI argument for `isa`.
pub fn abi(arg: &ArgumentType, isa: &TargetIsa) -> Affinity { pub fn abi(arg: &AbiParam, isa: &TargetIsa) -> Affinity {
match arg.location { match arg.location {
ArgumentLoc::Unassigned => Affinity::None, ArgumentLoc::Unassigned => Affinity::None,
ArgumentLoc::Reg(_) => Affinity::Reg(isa.regclass_for_abi_type(arg.value_type).into()), ArgumentLoc::Reg(_) => Affinity::Reg(isa.regclass_for_abi_type(arg.value_type).into()),

View File

@@ -418,14 +418,12 @@ impl<'a> Context<'a> {
self.func.dfg.display_inst(pred_inst, self.isa) self.func.dfg.display_inst(pred_inst, self.isa)
); );
// Never coalesce incoming function arguments on the stack. These arguments are // Never coalesce incoming function parameters on the stack. These parameters are
// pre-spilled, and the rest of the virtual register would be forced to spill to the // pre-spilled, and the rest of the virtual register would be forced to spill to the
// `incoming_arg` stack slot too. // `incoming_arg` stack slot too.
if let ValueDef::Param(def_ebb, def_num) = self.func.dfg.value_def(pred_val) { if let ValueDef::Param(def_ebb, def_num) = self.func.dfg.value_def(pred_val) {
if Some(def_ebb) == self.func.layout.entry_block() && if Some(def_ebb) == self.func.layout.entry_block() &&
self.func.signature.argument_types[def_num] self.func.signature.params[def_num].location.is_stack()
.location
.is_stack()
{ {
dbg!("Isolating incoming stack parameter {}", pred_val); dbg!("Isolating incoming stack parameter {}", pred_val);
let new_val = self.split_pred(pred_inst, pred_ebb, argnum, pred_val); let new_val = self.split_pred(pred_inst, pred_ebb, argnum, pred_val);

View File

@@ -45,7 +45,7 @@
use cursor::{Cursor, EncCursor}; use cursor::{Cursor, EncCursor};
use dominator_tree::DominatorTree; use dominator_tree::DominatorTree;
use ir::{Ebb, Inst, Value, Function, ValueLoc, SigRef}; use ir::{Ebb, Inst, Value, Function, ValueLoc, SigRef};
use ir::{InstBuilder, ArgumentType, ArgumentLoc, ValueDef}; use ir::{InstBuilder, AbiParam, ArgumentLoc, ValueDef};
use isa::{RegUnit, RegClass, RegInfo, regs_overlap}; use isa::{RegUnit, RegClass, RegInfo, regs_overlap};
use isa::{TargetIsa, EncInfo, RecipeConstraints, OperandConstraint, ConstraintKind}; use isa::{TargetIsa, EncInfo, RecipeConstraints, OperandConstraint, ConstraintKind};
use packed_option::PackedOption; use packed_option::PackedOption;
@@ -188,10 +188,10 @@ impl<'a> Context<'a> {
); );
if self.cur.func.layout.entry_block() == Some(ebb) { if self.cur.func.layout.entry_block() == Some(ebb) {
// Arguments to the entry block have ABI constraints. // Parameters on the entry block have ABI constraints.
self.color_entry_args(tracker.live()) self.color_entry_params(tracker.live())
} else { } else {
// The live-ins and arguments to a non-entry EBB have already been assigned a register. // The live-ins and parameters of a non-entry EBB have already been assigned a register.
// Reconstruct the allocatable set. // Reconstruct the allocatable set.
self.livein_regs(tracker.live()) self.livein_regs(tracker.live())
} }
@@ -230,19 +230,19 @@ impl<'a> Context<'a> {
regs regs
} }
/// Color the arguments to the entry block. /// Color the parameters on the entry block.
/// ///
/// These are function arguments that should already have assigned register units in the /// These are function parameters that should already have assigned register units in the
/// function signature. /// function signature.
/// ///
/// Return the set of remaining allocatable registers after filtering out the dead arguments. /// Return the set of remaining allocatable registers after filtering out the dead arguments.
fn color_entry_args(&mut self, args: &[LiveValue]) -> AvailableRegs { fn color_entry_params(&mut self, args: &[LiveValue]) -> AvailableRegs {
let sig = &self.cur.func.signature; let sig = &self.cur.func.signature;
assert_eq!(sig.argument_types.len(), args.len()); assert_eq!(sig.params.len(), args.len());
let mut regs = AvailableRegs::new(&self.usable_regs); let mut regs = AvailableRegs::new(&self.usable_regs);
for (lv, abi) in args.iter().zip(&sig.argument_types) { for (lv, abi) in args.iter().zip(&sig.params) {
match lv.affinity { match lv.affinity {
Affinity::Reg(rci) => { Affinity::Reg(rci) => {
let rc = self.reginfo.rc(rci); let rc = self.reginfo.rc(rci);
@@ -305,7 +305,7 @@ impl<'a> Context<'a> {
program_input_abi( program_input_abi(
&mut self.solver, &mut self.solver,
inst, inst,
&self.cur.func.dfg.signatures[sig].argument_types, &self.cur.func.dfg.signatures[sig].params,
&self.cur.func, &self.cur.func,
&self.liveness, &self.liveness,
&self.reginfo, &self.reginfo,
@@ -315,7 +315,7 @@ impl<'a> Context<'a> {
program_input_abi( program_input_abi(
&mut self.solver, &mut self.solver,
inst, inst,
&self.cur.func.signature.return_types, &self.cur.func.signature.returns,
&self.cur.func, &self.cur.func,
&self.liveness, &self.liveness,
&self.reginfo, &self.reginfo,
@@ -687,12 +687,9 @@ impl<'a> Context<'a> {
// It's technically possible for a call instruction to have fixed results before the // It's technically possible for a call instruction to have fixed results before the
// variable list of results, but we have no known instances of that. // variable list of results, but we have no known instances of that.
// Just assume all results are variable return values. // Just assume all results are variable return values.
assert_eq!( assert_eq!(defs.len(), self.cur.func.dfg.signatures[sig].returns.len());
defs.len(),
self.cur.func.dfg.signatures[sig].return_types.len()
);
for (i, lv) in defs.iter().enumerate() { for (i, lv) in defs.iter().enumerate() {
let abi = self.cur.func.dfg.signatures[sig].return_types[i]; let abi = self.cur.func.dfg.signatures[sig].returns[i];
if let ArgumentLoc::Reg(reg) = abi.location { if let ArgumentLoc::Reg(reg) = abi.location {
if let Affinity::Reg(rci) = lv.affinity { if let Affinity::Reg(rci) = lv.affinity {
let rc = self.reginfo.rc(rci); let rc = self.reginfo.rc(rci);
@@ -1015,7 +1012,7 @@ impl<'a> Context<'a> {
fn program_input_abi( fn program_input_abi(
solver: &mut Solver, solver: &mut Solver,
inst: Inst, inst: Inst,
abi_types: &[ArgumentType], abi_types: &[AbiParam],
func: &Function, func: &Function,
liveness: &Liveness, liveness: &Liveness,
reginfo: &RegInfo, reginfo: &RegInfo,

View File

@@ -216,7 +216,7 @@ fn get_or_create<'a>(
.or_else(|| { .or_else(|| {
// If this is a call, get the return value affinity. // If this is a call, get the return value affinity.
func.dfg.call_signature(inst).map(|sig| { func.dfg.call_signature(inst).map(|sig| {
Affinity::abi(&func.dfg.signatures[sig].return_types[rnum], isa) Affinity::abi(&func.dfg.signatures[sig].returns[rnum], isa)
}) })
}) })
.unwrap_or_default(); .unwrap_or_default();
@@ -226,7 +226,7 @@ fn get_or_create<'a>(
if func.layout.entry_block() == Some(ebb) { if func.layout.entry_block() == Some(ebb) {
// The affinity for entry block parameters can be inferred from the function // The affinity for entry block parameters can be inferred from the function
// signature. // signature.
affinity = Affinity::abi(&func.signature.argument_types[num], isa); affinity = Affinity::abi(&func.signature.params[num], isa);
} else { } else {
// Don't apply any affinity to normal EBB parameters. // Don't apply any affinity to normal EBB parameters.
// They could be in a register or on the stack. // They could be in a register or on the stack.

View File

@@ -13,7 +13,7 @@ use cursor::{Cursor, EncCursor};
use dominator_tree::DominatorTree; use dominator_tree::DominatorTree;
use entity::{SparseMap, SparseMapValue}; use entity::{SparseMap, SparseMapValue};
use ir::{Ebb, Inst, Value, Function}; use ir::{Ebb, Inst, Value, Function};
use ir::{InstBuilder, ArgumentType, ArgumentLoc}; use ir::{InstBuilder, AbiParam, ArgumentLoc};
use isa::RegClass; use isa::RegClass;
use isa::{TargetIsa, Encoding, EncInfo, RecipeConstraints, ConstraintKind}; use isa::{TargetIsa, Encoding, EncInfo, RecipeConstraints, ConstraintKind};
use regalloc::affinity::Affinity; use regalloc::affinity::Affinity;
@@ -137,20 +137,20 @@ impl<'a> Context<'a> {
if self.cur.func.layout.entry_block() == Some(ebb) { if self.cur.func.layout.entry_block() == Some(ebb) {
assert_eq!(liveins.len(), 0); assert_eq!(liveins.len(), 0);
self.visit_entry_args(ebb, args); self.visit_entry_params(ebb, args);
} else { } else {
self.visit_ebb_params(ebb, args); self.visit_ebb_params(ebb, args);
} }
} }
/// Visit the arguments to the entry block. /// Visit the parameters on the entry block.
/// These values have ABI constraints from the function signature. /// These values have ABI constraints from the function signature.
fn visit_entry_args(&mut self, ebb: Ebb, args: &[LiveValue]) { fn visit_entry_params(&mut self, ebb: Ebb, args: &[LiveValue]) {
assert_eq!(self.cur.func.signature.argument_types.len(), args.len()); assert_eq!(self.cur.func.signature.params.len(), args.len());
self.cur.goto_first_inst(ebb); self.cur.goto_first_inst(ebb);
for (arg_idx, arg) in args.iter().enumerate() { for (arg_idx, arg) in args.iter().enumerate() {
let abi = self.cur.func.signature.argument_types[arg_idx]; let abi = self.cur.func.signature.params[arg_idx];
match abi.location { match abi.location {
ArgumentLoc::Reg(_) => { ArgumentLoc::Reg(_) => {
if arg.affinity.is_stack() { if arg.affinity.is_stack() {
@@ -266,7 +266,7 @@ impl<'a> Context<'a> {
"Extra results on non-call instruction", "Extra results on non-call instruction",
); );
for (i, lv) in retvals.iter().enumerate() { for (i, lv) in retvals.iter().enumerate() {
let abi = self.cur.func.dfg.signatures[sig].return_types[i]; let abi = self.cur.func.dfg.signatures[sig].returns[i];
debug_assert!(abi.location.is_reg()); debug_assert!(abi.location.is_reg());
if lv.affinity.is_stack() { if lv.affinity.is_stack() {
let reg = self.cur.func.dfg.replace_result(lv.value, abi.value_type); let reg = self.cur.func.dfg.replace_result(lv.value, abi.value_type);
@@ -308,7 +308,7 @@ impl<'a> Context<'a> {
if let Some(sig) = self.cur.func.dfg.call_signature(inst) { if let Some(sig) = self.cur.func.dfg.call_signature(inst) {
handle_abi_args( handle_abi_args(
self.candidates, self.candidates,
&self.cur.func.dfg.signatures[sig].argument_types, &self.cur.func.dfg.signatures[sig].params,
var_args, var_args,
self.cur.isa, self.cur.isa,
self.liveness, self.liveness,
@@ -316,7 +316,7 @@ impl<'a> Context<'a> {
} else if self.cur.func.dfg[inst].opcode().is_return() { } else if self.cur.func.dfg[inst].opcode().is_return() {
handle_abi_args( handle_abi_args(
self.candidates, self.candidates,
&self.cur.func.signature.return_types, &self.cur.func.signature.returns,
var_args, var_args,
self.cur.isa, self.cur.isa,
self.liveness, self.liveness,
@@ -348,7 +348,7 @@ impl<'a> Context<'a> {
/// return values and call arguments. /// return values and call arguments.
fn handle_abi_args( fn handle_abi_args(
candidates: &mut Vec<ReloadCandidate>, candidates: &mut Vec<ReloadCandidate>,
abi_types: &[ArgumentType], abi_types: &[AbiParam],
var_args: &[Value], var_args: &[Value],
isa: &TargetIsa, isa: &TargetIsa,
liveness: &Liveness, liveness: &Liveness,

View File

@@ -324,7 +324,7 @@ impl<'a> Context<'a> {
let args = self.cur.func.dfg.inst_variable_args(inst); let args = self.cur.func.dfg.inst_variable_args(inst);
for (idx, (abi, &arg)) in for (idx, (abi, &arg)) in
self.cur.func.dfg.signatures[sig] self.cur.func.dfg.signatures[sig]
.argument_types .params
.iter() .iter()
.zip(args) .zip(args)
.enumerate() .enumerate()

View File

@@ -129,7 +129,7 @@ impl<'a> LocationVerifier<'a> {
let varargs = self.func.dfg.inst_variable_args(inst); let varargs = self.func.dfg.inst_variable_args(inst);
let results = self.func.dfg.inst_results(inst); let results = self.func.dfg.inst_results(inst);
for (abi, &value) in sig.argument_types.iter().zip(varargs) { for (abi, &value) in sig.params.iter().zip(varargs) {
self.check_abi_location( self.check_abi_location(
inst, inst,
value, value,
@@ -139,7 +139,7 @@ impl<'a> LocationVerifier<'a> {
)?; )?;
} }
for (abi, &value) in sig.return_types.iter().zip(results) { for (abi, &value) in sig.returns.iter().zip(results) {
self.check_abi_location( self.check_abi_location(
inst, inst,
value, value,
@@ -157,7 +157,7 @@ impl<'a> LocationVerifier<'a> {
let sig = &self.func.signature; let sig = &self.func.signature;
let varargs = self.func.dfg.inst_variable_args(inst); let varargs = self.func.dfg.inst_variable_args(inst);
for (abi, &value) in sig.return_types.iter().zip(varargs) { for (abi, &value) in sig.returns.iter().zip(varargs) {
self.check_abi_location( self.check_abi_location(
inst, inst,
value, value,
@@ -175,7 +175,7 @@ impl<'a> LocationVerifier<'a> {
&self, &self,
inst: ir::Inst, inst: ir::Inst,
value: ir::Value, value: ir::Value,
abi: &ir::ArgumentType, abi: &ir::AbiParam,
loc: ir::ValueLoc, loc: ir::ValueLoc,
want_kind: ir::StackSlotKind, want_kind: ir::StackSlotKind,
) -> Result { ) -> Result {

View File

@@ -241,7 +241,7 @@ impl<'a> Verifier<'a> {
let fixed_results = inst_data.opcode().constraints().fixed_results(); let fixed_results = inst_data.opcode().constraints().fixed_results();
// var_results is 0 if we aren't a call instruction // var_results is 0 if we aren't a call instruction
let var_results = dfg.call_signature(inst) let var_results = dfg.call_signature(inst)
.map(|sig| dfg.signatures[sig].return_types.len()) .map(|sig| dfg.signatures[sig].returns.len())
.unwrap_or(0); .unwrap_or(0);
let total_results = fixed_results + var_results; let total_results = fixed_results + var_results;
@@ -551,9 +551,9 @@ impl<'a> Verifier<'a> {
Ok(()) Ok(())
} }
fn typecheck_entry_block_arguments(&self) -> Result { fn typecheck_entry_block_params(&self) -> Result {
if let Some(ebb) = self.func.layout.entry_block() { if let Some(ebb) = self.func.layout.entry_block() {
let expected_types = &self.func.signature.argument_types; let expected_types = &self.func.signature.params;
let ebb_param_count = self.func.dfg.num_ebb_params(ebb); let ebb_param_count = self.func.dfg.num_ebb_params(ebb);
if ebb_param_count != expected_types.len() { if ebb_param_count != expected_types.len() {
@@ -700,18 +700,16 @@ impl<'a> Verifier<'a> {
match self.func.dfg[inst].analyze_call(&self.func.dfg.value_lists) { match self.func.dfg[inst].analyze_call(&self.func.dfg.value_lists) {
CallInfo::Direct(func_ref, _) => { CallInfo::Direct(func_ref, _) => {
let sig_ref = self.func.dfg.ext_funcs[func_ref].signature; let sig_ref = self.func.dfg.ext_funcs[func_ref].signature;
let arg_types = self.func.dfg.signatures[sig_ref] let arg_types = self.func.dfg.signatures[sig_ref].params.iter().map(|a| {
.argument_types a.value_type
.iter() });
.map(|a| a.value_type);
self.typecheck_variable_args_iterator(inst, arg_types)?; self.typecheck_variable_args_iterator(inst, arg_types)?;
self.check_outgoing_args(inst, sig_ref)?; self.check_outgoing_args(inst, sig_ref)?;
} }
CallInfo::Indirect(sig_ref, _) => { CallInfo::Indirect(sig_ref, _) => {
let arg_types = self.func.dfg.signatures[sig_ref] let arg_types = self.func.dfg.signatures[sig_ref].params.iter().map(|a| {
.argument_types a.value_type
.iter() });
.map(|a| a.value_type);
self.typecheck_variable_args_iterator(inst, arg_types)?; self.typecheck_variable_args_iterator(inst, arg_types)?;
self.check_outgoing_args(inst, sig_ref)?; self.check_outgoing_args(inst, sig_ref)?;
} }
@@ -772,7 +770,7 @@ impl<'a> Verifier<'a> {
} }
let args = self.func.dfg.inst_variable_args(inst); let args = self.func.dfg.inst_variable_args(inst);
let expected_args = &sig.argument_types[..]; let expected_args = &sig.params[..];
for (&arg, &abi) in args.iter().zip(expected_args) { for (&arg, &abi) in args.iter().zip(expected_args) {
// Value types have already been checked by `typecheck_variable_args_iterator()`. // Value types have already been checked by `typecheck_variable_args_iterator()`.
@@ -828,7 +826,7 @@ impl<'a> Verifier<'a> {
fn typecheck_return(&self, inst: Inst) -> Result { fn typecheck_return(&self, inst: Inst) -> Result {
if self.func.dfg[inst].opcode().is_return() { if self.func.dfg[inst].opcode().is_return() {
let args = self.func.dfg.inst_variable_args(inst); let args = self.func.dfg.inst_variable_args(inst);
let expected_types = &self.func.signature.return_types; let expected_types = &self.func.signature.returns;
if args.len() != expected_types.len() { if args.len() != expected_types.len() {
return err!(inst, "arguments of return must match function signature"); return err!(inst, "arguments of return must match function signature");
} }
@@ -1081,7 +1079,7 @@ impl<'a> Verifier<'a> {
pub fn run(&self) -> Result { pub fn run(&self) -> Result {
self.verify_global_vars()?; self.verify_global_vars()?;
self.typecheck_entry_block_arguments()?; self.typecheck_entry_block_params()?;
for ebb in self.func.layout.ebbs() { for ebb in self.func.layout.ebbs() {
for inst in self.func.layout.ebb_insts(ebb) { for inst in self.func.layout.ebb_insts(ebb) {
self.ebb_integrity(ebb, inst)?; self.ebb_integrity(ebb, inst)?;

View File

@@ -529,14 +529,14 @@ where
fn check_return_args(&self, args: &[Value]) { fn check_return_args(&self, args: &[Value]) {
debug_assert_eq!( debug_assert_eq!(
args.len(), args.len(),
self.func.signature.return_types.len(), self.func.signature.returns.len(),
"the number of returned values doesn't match the function signature " "the number of returned values doesn't match the function signature "
); );
for (i, arg) in args.iter().enumerate() { for (i, arg) in args.iter().enumerate() {
let valty = self.func.dfg.value_type(*arg); let valty = self.func.dfg.value_type(*arg);
debug_assert_eq!( debug_assert_eq!(
valty, valty,
self.func.signature.return_types[i].value_type, self.func.signature.returns[i].value_type,
"the types of the values returned don't match the \ "the types of the values returned don't match the \
function signature" function signature"
); );
@@ -545,7 +545,7 @@ where
fn fill_function_args_values(&mut self, ebb: Ebb) { fn fill_function_args_values(&mut self, ebb: Ebb) {
debug_assert!(self.pristine); debug_assert!(self.pristine);
for argtyp in &self.func.signature.argument_types { for argtyp in &self.func.signature.params {
self.builder.function_args_values.push( self.builder.function_args_values.push(
self.func.dfg.append_ebb_param(ebb, argtyp.value_type), self.func.dfg.append_ebb_param(ebb, argtyp.value_type),
); );
@@ -621,7 +621,7 @@ where
mod tests { mod tests {
use cretonne::entity::EntityRef; use cretonne::entity::EntityRef;
use cretonne::ir::{FunctionName, Function, CallConv, Signature, ArgumentType, InstBuilder}; use cretonne::ir::{FunctionName, Function, CallConv, Signature, AbiParam, InstBuilder};
use cretonne::ir::types::*; use cretonne::ir::types::*;
use frontend::{ILBuilder, FunctionBuilder}; use frontend::{ILBuilder, FunctionBuilder};
use cretonne::verifier::verify_function; use cretonne::verifier::verify_function;
@@ -651,8 +651,8 @@ mod tests {
#[test] #[test]
fn sample_function() { fn sample_function() {
let mut sig = Signature::new(CallConv::Native); let mut sig = Signature::new(CallConv::Native);
sig.return_types.push(ArgumentType::new(I32)); sig.returns.push(AbiParam::new(I32));
sig.argument_types.push(ArgumentType::new(I32)); sig.params.push(AbiParam::new(I32));
let mut il_builder = ILBuilder::<Variable>::new(); let mut il_builder = ILBuilder::<Variable>::new();
let mut func = Function::with_name_signature(FunctionName::new("sample_function"), sig); let mut func = Function::with_name_signature(FunctionName::new("sample_function"), sig);

View File

@@ -36,7 +36,7 @@
//! extern crate cton_frontend; //! extern crate cton_frontend;
//! //!
//! use cretonne::entity::EntityRef; //! use cretonne::entity::EntityRef;
//! use cretonne::ir::{FunctionName, CallConv, Function, Signature, ArgumentType, InstBuilder}; //! use cretonne::ir::{FunctionName, CallConv, Function, Signature, AbiParam, InstBuilder};
//! use cretonne::ir::types::*; //! use cretonne::ir::types::*;
//! use cretonne::settings; //! use cretonne::settings;
//! use cton_frontend::{ILBuilder, FunctionBuilder}; //! use cton_frontend::{ILBuilder, FunctionBuilder};
@@ -64,8 +64,8 @@
//! //!
//! fn main() { //! fn main() {
//! let mut sig = Signature::new(CallConv::Native); //! let mut sig = Signature::new(CallConv::Native);
//! sig.return_types.push(ArgumentType::new(I32)); //! sig.returns.push(AbiParam::new(I32));
//! sig.argument_types.push(ArgumentType::new(I32)); //! sig.params.push(AbiParam::new(I32));
//! let mut il_builder = ILBuilder::<Variable>::new(); //! let mut il_builder = ILBuilder::<Variable>::new();
//! let mut func = Function::with_name_signature(FunctionName::new("sample_function"), sig); //! let mut func = Function::with_name_signature(FunctionName::new("sample_function"), sig);
//! { //! {

View File

@@ -10,9 +10,9 @@ use std::str::FromStr;
use std::{u16, u32}; use std::{u16, u32};
use std::mem; use std::mem;
use cretonne::ir::{Function, Ebb, Opcode, Value, Type, FunctionName, CallConv, StackSlotData, use cretonne::ir::{Function, Ebb, Opcode, Value, Type, FunctionName, CallConv, StackSlotData,
JumpTable, JumpTableData, Signature, ArgumentType, ArgumentExtension, JumpTable, JumpTableData, Signature, AbiParam, ArgumentExtension, ExtFuncData,
ExtFuncData, SigRef, FuncRef, StackSlot, ValueLoc, ArgumentLoc, MemFlags, SigRef, FuncRef, StackSlot, ValueLoc, ArgumentLoc, MemFlags, GlobalVar,
GlobalVar, GlobalVarData, Heap, HeapData, HeapStyle, HeapBase}; GlobalVarData, Heap, HeapData, HeapStyle, HeapBase};
use cretonne::ir; use cretonne::ir;
use cretonne::ir::types::VOID; use cretonne::ir::types::VOID;
use cretonne::ir::immediates::{Imm64, Uimm32, Offset32, Ieee32, Ieee64}; use cretonne::ir::immediates::{Imm64, Uimm32, Offset32, Ieee32, Ieee64};
@@ -918,7 +918,7 @@ impl<'a> Parser<'a> {
// Parse a function signature. // Parse a function signature.
// //
// signature ::= * "(" [arglist] ")" ["->" retlist] [callconv] // signature ::= * "(" [paramlist] ")" ["->" retlist] [callconv]
// //
fn parse_signature(&mut self, unique_isa: Option<&TargetIsa>) -> Result<Signature> { fn parse_signature(&mut self, unique_isa: Option<&TargetIsa>) -> Result<Signature> {
// Calling convention defaults to `native`, but can be changed. // Calling convention defaults to `native`, but can be changed.
@@ -928,16 +928,16 @@ impl<'a> Parser<'a> {
Token::LPar, Token::LPar,
"expected function signature: ( args... )", "expected function signature: ( args... )",
)?; )?;
// signature ::= "(" * [arglist] ")" ["->" retlist] [callconv] // signature ::= "(" * [abi-param-list] ")" ["->" retlist] [callconv]
if self.token() != Some(Token::RPar) { if self.token() != Some(Token::RPar) {
sig.argument_types = self.parse_argument_list(unique_isa)?; sig.params = self.parse_abi_param_list(unique_isa)?;
} }
self.match_token( self.match_token(
Token::RPar, Token::RPar,
"expected ')' after function arguments", "expected ')' after function arguments",
)?; )?;
if self.optional(Token::Arrow) { if self.optional(Token::Arrow) {
sig.return_types = self.parse_argument_list(unique_isa)?; sig.returns = self.parse_abi_param_list(unique_isa)?;
} }
// The calling convention is optional. // The calling convention is optional.
@@ -951,38 +951,38 @@ impl<'a> Parser<'a> {
} }
} }
if sig.argument_types.iter().all(|a| a.location.is_assigned()) { if sig.params.iter().all(|a| a.location.is_assigned()) {
sig.compute_argument_bytes(); sig.compute_argument_bytes();
} }
Ok(sig) Ok(sig)
} }
// Parse list of function argument / return value types. // Parse list of function parameter / return value types.
// //
// arglist ::= * arg { "," arg } // paramlist ::= * param { "," param }
// //
fn parse_argument_list(&mut self, unique_isa: Option<&TargetIsa>) -> Result<Vec<ArgumentType>> { fn parse_abi_param_list(&mut self, unique_isa: Option<&TargetIsa>) -> Result<Vec<AbiParam>> {
let mut list = Vec::new(); let mut list = Vec::new();
// arglist ::= * arg { "," arg } // abi-param-list ::= * abi-param { "," abi-param }
list.push(self.parse_argument_type(unique_isa)?); list.push(self.parse_abi_param(unique_isa)?);
// arglist ::= arg * { "," arg } // abi-param-list ::= abi-param * { "," abi-param }
while self.optional(Token::Comma) { while self.optional(Token::Comma) {
// arglist ::= arg { "," * arg } // abi-param-list ::= abi-param { "," * abi-param }
list.push(self.parse_argument_type(unique_isa)?); list.push(self.parse_abi_param(unique_isa)?);
} }
Ok(list) Ok(list)
} }
// Parse a single argument type with flags. // Parse a single argument type with flags.
fn parse_argument_type(&mut self, unique_isa: Option<&TargetIsa>) -> Result<ArgumentType> { fn parse_abi_param(&mut self, unique_isa: Option<&TargetIsa>) -> Result<AbiParam> {
// arg ::= * type { flag } [ argumentloc ] // abi-param ::= * type { flag } [ argumentloc ]
let mut arg = ArgumentType::new(self.match_type("expected argument type")?); let mut arg = AbiParam::new(self.match_type("expected parameter type")?);
// arg ::= type * { flag } [ argumentloc ] // abi-param ::= type * { flag } [ argumentloc ]
while let Some(Token::Identifier(s)) = self.token() { while let Some(Token::Identifier(s)) = self.token() {
match s { match s {
"uext" => arg.extension = ArgumentExtension::Uext, "uext" => arg.extension = ArgumentExtension::Uext,
@@ -998,7 +998,7 @@ impl<'a> Parser<'a> {
self.consume(); self.consume();
} }
// arg ::= type { flag } * [ argumentloc ] // abi-param ::= type { flag } * [ argumentloc ]
arg.location = self.parse_argument_location(unique_isa)?; arg.location = self.parse_argument_location(unique_isa)?;
Ok(arg) Ok(arg)
@@ -1374,7 +1374,7 @@ impl<'a> Parser<'a> {
self.parse_ebb_params(ctx, ebb)?; self.parse_ebb_params(ctx, ebb)?;
self.match_token( self.match_token(
Token::Colon, Token::Colon,
"expected ':' after EBB arguments", "expected ':' after EBB parameters",
)?; )?;
} }
@@ -1437,7 +1437,7 @@ impl<'a> Parser<'a> {
// ebb-params ::= * "(" ebb-param { "," ebb-param } ")" // ebb-params ::= * "(" ebb-param { "," ebb-param } ")"
self.match_token( self.match_token(
Token::LPar, Token::LPar,
"expected '(' before EBB arguments", "expected '(' before EBB parameters",
)?; )?;
// ebb-params ::= "(" * ebb-param { "," ebb-param } ")" // ebb-params ::= "(" * ebb-param { "," ebb-param } ")"
@@ -1452,7 +1452,7 @@ impl<'a> Parser<'a> {
// ebb-params ::= "(" ebb-param { "," ebb-param } * ")" // ebb-params ::= "(" ebb-param { "," ebb-param } * ")"
self.match_token( self.match_token(
Token::RPar, Token::RPar,
"expected ')' after EBB arguments", "expected ')' after EBB parameters",
)?; )?;
Ok(()) Ok(())
@@ -2337,13 +2337,13 @@ mod tests {
#[test] #[test]
fn argument_type() { fn argument_type() {
let mut p = Parser::new("i32 sext"); let mut p = Parser::new("i32 sext");
let arg = p.parse_argument_type(None).unwrap(); let arg = p.parse_abi_param(None).unwrap();
assert_eq!(arg.value_type, types::I32); assert_eq!(arg.value_type, types::I32);
assert_eq!(arg.extension, ArgumentExtension::Sext); assert_eq!(arg.extension, ArgumentExtension::Sext);
assert_eq!(arg.purpose, ArgumentPurpose::Normal); assert_eq!(arg.purpose, ArgumentPurpose::Normal);
let Error { location, message } = p.parse_argument_type(None).unwrap_err(); let Error { location, message } = p.parse_abi_param(None).unwrap_err();
assert_eq!(location.line_number, 1); assert_eq!(location.line_number, 1);
assert_eq!(message, "expected argument type"); assert_eq!(message, "expected parameter type");
} }
#[test] #[test]
@@ -2374,8 +2374,8 @@ mod tests {
#[test] #[test]
fn signature() { fn signature() {
let sig = Parser::new("()native").parse_signature(None).unwrap(); let sig = Parser::new("()native").parse_signature(None).unwrap();
assert_eq!(sig.argument_types.len(), 0); assert_eq!(sig.params.len(), 0);
assert_eq!(sig.return_types.len(), 0); assert_eq!(sig.returns.len(), 0);
assert_eq!(sig.call_conv, CallConv::Native); assert_eq!(sig.call_conv, CallConv::Native);
let sig2 = Parser::new("(i8 uext, f32, f64, i32 sret) -> i32 sext, f64 spiderwasm") let sig2 = Parser::new("(i8 uext, f32, f64, i32 sret) -> i32 sext, f64 spiderwasm")
@@ -2406,7 +2406,7 @@ mod tests {
.parse_signature(None) .parse_signature(None)
.unwrap_err() .unwrap_err()
.to_string(), .to_string(),
"1: expected argument type" "1: expected parameter type"
); );
assert_eq!( assert_eq!(
Parser::new("i8 -> i8") Parser::new("i8 -> i8")

View File

@@ -100,14 +100,14 @@ impl FuncTranslator {
} }
} }
/// Declare local variables for the signature arguments that correspond to WebAssembly locals. /// Declare local variables for the signature parameters that correspond to WebAssembly locals.
/// ///
/// Return the number of local variables declared. /// Return the number of local variables declared.
fn declare_wasm_arguments(builder: &mut FunctionBuilder<Local>) -> usize { fn declare_wasm_arguments(builder: &mut FunctionBuilder<Local>) -> usize {
let sig_len = builder.func.signature.argument_types.len(); let sig_len = builder.func.signature.params.len();
let mut next_local = 0; let mut next_local = 0;
for i in 0..sig_len { for i in 0..sig_len {
let arg_type = builder.func.signature.argument_types[i]; let arg_type = builder.func.signature.params[i];
// There may be additional special-purpose arguments following the normal WebAssembly // There may be additional special-purpose arguments following the normal WebAssembly
// signature arguments. For example, a `vmctx` pointer. // signature arguments. For example, a `vmctx` pointer.
if arg_type.purpose == ir::ArgumentPurpose::Normal { if arg_type.purpose == ir::ArgumentPurpose::Normal {
@@ -256,12 +256,8 @@ mod tests {
let mut ctx = Context::new(); let mut ctx = Context::new();
ctx.func.name = ir::FunctionName::new("small1"); ctx.func.name = ir::FunctionName::new("small1");
ctx.func.signature.argument_types.push( ctx.func.signature.params.push(ir::AbiParam::new(I32));
ir::ArgumentType::new(I32), ctx.func.signature.returns.push(ir::AbiParam::new(I32));
);
ctx.func.signature.return_types.push(
ir::ArgumentType::new(I32),
);
trans trans
.translate(&BODY, &mut ctx.func, &mut runtime.func_env()) .translate(&BODY, &mut ctx.func, &mut runtime.func_env())
@@ -291,12 +287,8 @@ mod tests {
let mut ctx = Context::new(); let mut ctx = Context::new();
ctx.func.name = ir::FunctionName::new("small2"); ctx.func.name = ir::FunctionName::new("small2");
ctx.func.signature.argument_types.push( ctx.func.signature.params.push(ir::AbiParam::new(I32));
ir::ArgumentType::new(I32), ctx.func.signature.returns.push(ir::AbiParam::new(I32));
);
ctx.func.signature.return_types.push(
ir::ArgumentType::new(I32),
);
trans trans
.translate(&BODY, &mut ctx.func, &mut runtime.func_env()) .translate(&BODY, &mut ctx.func, &mut runtime.func_env())
@@ -335,9 +327,7 @@ mod tests {
let mut ctx = Context::new(); let mut ctx = Context::new();
ctx.func.name = ir::FunctionName::new("infloop"); ctx.func.name = ir::FunctionName::new("infloop");
ctx.func.signature.return_types.push( ctx.func.signature.returns.push(ir::AbiParam::new(I32));
ir::ArgumentType::new(I32),
);
trans trans
.translate(&BODY, &mut ctx.func, &mut runtime.func_env()) .translate(&BODY, &mut ctx.func, &mut runtime.func_env())

View File

@@ -9,7 +9,7 @@
//! interpreted on the fly. //! interpreted on the fly.
use translation_utils::{type_to_type, TableIndex, FunctionIndex, GlobalIndex, SignatureIndex, use translation_utils::{type_to_type, TableIndex, FunctionIndex, GlobalIndex, SignatureIndex,
MemoryIndex, Global, GlobalInit, Table, TableElementType, Memory}; MemoryIndex, Global, GlobalInit, Table, TableElementType, Memory};
use cretonne::ir::{Signature, ArgumentType, CallConv}; use cretonne::ir::{Signature, AbiParam, CallConv};
use cretonne; use cretonne;
use wasmparser::{Parser, ParserState, FuncType, ImportSectionEntryType, ExternalKind, WasmDecoder, use wasmparser::{Parser, ParserState, FuncType, ImportSectionEntryType, ExternalKind, WasmDecoder,
MemoryType, Operator}; MemoryType, Operator};
@@ -35,17 +35,17 @@ pub fn parse_function_signatures(
ref returns, ref returns,
}) => { }) => {
let mut sig = Signature::new(CallConv::Native); let mut sig = Signature::new(CallConv::Native);
sig.argument_types.extend(params.iter().map(|ty| { sig.params.extend(params.iter().map(|ty| {
let cret_arg: cretonne::ir::Type = type_to_type(ty).expect( let cret_arg: cretonne::ir::Type = type_to_type(ty).expect(
"only numeric types are supported in function signatures", "only numeric types are supported in function signatures",
); );
ArgumentType::new(cret_arg) AbiParam::new(cret_arg)
})); }));
sig.return_types.extend(returns.iter().map(|ty| { sig.returns.extend(returns.iter().map(|ty| {
let cret_arg: cretonne::ir::Type = type_to_type(ty).expect( let cret_arg: cretonne::ir::Type = type_to_type(ty).expect(
"only numeric types are supported in function signatures", "only numeric types are supported in function signatures",
); );
ArgumentType::new(cret_arg) AbiParam::new(cret_arg)
})); }));
environ.declare_signature(&sig); environ.declare_signature(&sig);
} }

View File

@@ -158,7 +158,7 @@ impl TranslationState {
self.clear(); self.clear();
self.push_block( self.push_block(
exit_block, exit_block,
sig.return_types sig.returns
.iter() .iter()
.filter(|arg| arg.purpose == ir::ArgumentPurpose::Normal) .filter(|arg| arg.purpose == ir::ArgumentPurpose::Normal)
.count(), .count(),
@@ -323,10 +323,10 @@ impl TranslationState {
} }
} }
/// Count the number of normal arguments in a signature. /// Count the number of normal parameters in a signature.
/// Exclude special-purpose arguments that represent runtime stuff and not WebAssembly arguments. /// Exclude special-purpose parameters that represent runtime stuff and not WebAssembly arguments.
fn normal_args(sig: &ir::Signature) -> usize { fn normal_args(sig: &ir::Signature) -> usize {
sig.argument_types sig.params
.iter() .iter()
.filter(|arg| arg.purpose == ir::ArgumentPurpose::Normal) .filter(|arg| arg.purpose == ir::ArgumentPurpose::Normal)
.count() .count()