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
//! `TargetIsa::legalize_signature()` method.
use ir::{ArgumentLoc, ArgumentType, ArgumentExtension, Type};
use ir::{ArgumentLoc, AbiParam, ArgumentExtension, Type};
use std::cmp::Ordering;
/// 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.
pub trait ArgAssigner {
/// 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.
///
/// 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.
// 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.
@@ -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.
ArgAction::Convert(conv) => {
let new_arg = ArgumentType {
let new_arg = AbiParam {
value_type: conv.apply(arg.value_type),
..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
/// desired argument type appears. This will happen when a vector or integer type needs to be split
/// 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 arg_bits = arg.value_type.bits();
@@ -186,11 +186,11 @@ pub fn legalize_abi_value(have: Type, arg: &ArgumentType) -> ValueConversion {
mod tests {
use super::*;
use ir::types;
use ir::ArgumentType;
use ir::AbiParam;
#[test]
fn legalize() {
let mut arg = ArgumentType::new(types::I32);
let mut arg = AbiParam::new(types::I32);
assert_eq!(
legalize_abi_value(types::I64X2, &arg),

View File

@@ -463,10 +463,10 @@ impl DataFlowGraph {
// Get the call signature if this is a function call.
if let Some(sig) = self.call_signature(inst) {
// 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;
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() {
debug_assert_eq!(self.value_type(v), ty, "Reused {} is wrong type", ty);
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.
self.call_signature(inst).and_then(|sigref| {
self.signatures[sigref]
.return_types
.returns
.get(result_idx - fixed_results)
.map(|&arg| arg.value_type)
})

View File

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

View File

@@ -144,12 +144,12 @@ impl Function {
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.
pub fn special_arg(&self, purpose: ir::ArgumentPurpose) -> Option<ir::Value> {
/// Returns the value of the last `purpose` parameter, or `None` if no such parameter exists.
pub fn special_param(&self, purpose: ir::ArgumentPurpose) -> Option<ir::Value> {
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]
})
}

View File

@@ -24,7 +24,7 @@ mod valueloc;
pub use ir::builder::{InstBuilder, InstBuilderBase, InstInserterBase, InsertBuilder};
pub use ir::dfg::{DataFlowGraph, ValueDef};
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};
pub use ir::funcname::FunctionName;
pub use ir::function::Function;

View File

@@ -6,7 +6,7 @@ use regalloc::AllocatableSet;
use settings as shared_settings;
use super::registers::{GPR, FPR, RU};
use abi::{ArgAction, ValueConversion, ArgAssigner, legalize_args};
use ir::{ArgumentType, ArgumentPurpose, ArgumentLoc, ArgumentExtension};
use ir::{AbiParam, ArgumentPurpose, ArgumentLoc, ArgumentExtension};
/// Argument registers for x86-64
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 {
fn assign(&mut self, arg: &ArgumentType) -> ArgAction {
fn assign(&mut self, arg: &AbiParam) -> ArgAction {
let ty = arg.value_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);
}
legalize_args(&mut sig.argument_types, &mut args);
legalize_args(&mut sig.params, &mut args);
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.

View File

@@ -6,7 +6,7 @@
//! This doesn't support the soft-float ABI at the moment.
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 regalloc::AllocatableSet;
use settings as shared_settings;
@@ -36,7 +36,7 @@ impl 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 {
(value + to - 1) & !(to - 1)
}
@@ -95,10 +95,10 @@ pub fn legalize_signature(
let bits = if flags.is_64bit() { 64 } else { 32 };
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());
legalize_args(&mut sig.return_types, &mut rets);
legalize_args(&mut sig.returns, &mut rets);
if current {
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
// 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`.
let link = ArgumentType::special_reg(ptr, ArgumentPurpose::Link, GPR.unit(1));
sig.argument_types.push(link);
sig.return_types.push(link);
let link = AbiParam::special_reg(ptr, ArgumentPurpose::Link, GPR.unit(1));
sig.params.push(link);
sig.returns.push(link);
}
}

View File

@@ -21,7 +21,7 @@ use abi::{legalize_abi_value, ValueConversion};
use cursor::{Cursor, FuncCursor};
use flowgraph::ControlFlowGraph;
use ir::{Function, DataFlowGraph, Inst, InstBuilder, Ebb, Type, Value, Signature, SigRef,
ArgumentType, ArgumentPurpose, ArgumentLoc, ValueLoc};
AbiParam, ArgumentPurpose, ArgumentLoc, ValueLoc};
use ir::instructions::CallInfo;
use isa::TargetIsa;
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() {
legalize_entry_arguments(func, entry);
spill_entry_arguments(func, entry);
legalize_entry_params(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
/// argument types have been changed. This function goes through the arguments to the entry EBB and
/// replaces them with arguments of the right type for the ABI.
/// The legalized signature may contain more parameters than the original signature, and the
/// parameter types have been changed. This function goes through the parameters of the entry EBB
/// 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.
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_link = 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) {
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);
if arg_type == abi_type.value_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;
} 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 abi_type = func.signature.argument_types[abi_arg];
let abi_type = func.signature.params[abi_arg];
assert_eq!(
abi_type.purpose,
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.
for &arg in &pos.func.signature.argument_types[abi_arg..] {
for &arg in &pos.func.signature.params[abi_arg..] {
match arg.purpose {
// Any normal arguments should have been processed above.
// Any normal parameters should have been processed above.
ArgumentPurpose::Normal => {
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.
ArgumentPurpose::FramePointer |
ArgumentPurpose::CalleeSaved => {
@@ -136,19 +136,19 @@ fn legalize_entry_arguments(func: &mut Function, entry: Ebb) {
}
// These can be meaningfully added by `legalize_signature()`.
ArgumentPurpose::Link => {
assert!(!has_link, "Multiple link arguments found");
assert!(!has_link, "Multiple link parameters found");
has_link = true;
}
ArgumentPurpose::StructReturn => {
assert!(!has_sret, "Multiple sret arguments found");
assert!(!has_sret, "Multiple sret parameters found");
has_sret = true;
}
ArgumentPurpose::VMContext => {
assert!(!has_vmctx, "Multiple vmctx arguments found");
assert!(!has_vmctx, "Multiple vmctx parameters found");
has_vmctx = true;
}
ArgumentPurpose::SignatureId => {
assert!(!has_sigid, "Multiple sigid arguments found");
assert!(!has_sigid, "Multiple sigid parameters found");
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
/// 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.
fn legalize_inst_results<ResType>(pos: &mut FuncCursor, mut get_abi_type: ResType) -> Inst
where
ResType: FnMut(&Function, usize) -> ArgumentType,
ResType: FnMut(&Function, usize) -> AbiParam,
{
let call = pos.current_inst().expect(
"Cursor must point to a call instruction",
@@ -230,7 +230,7 @@ fn convert_from_abi<GetArg>(
get_arg: &mut GetArg,
) -> Value
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.
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
/// of arguments and return `Ok(())`.
/// 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>(
pos: &mut FuncCursor,
@@ -312,7 +312,7 @@ fn convert_to_abi<PutArg>(
value: Value,
put_arg: &mut PutArg,
) 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
// 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.
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 sig_types = types.iter().map(|&at| at.value_type);
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];
if check_arg_types(dfg, args, &sig.argument_types[..]) &&
check_arg_types(dfg, dfg.inst_results(inst), &sig.return_types[..])
if check_arg_types(dfg, args, &sig.params[..]) &&
check_arg_types(dfg, dfg.inst_results(inst), &sig.returns[..])
{
// All types check out.
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.
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`.
///
/// - `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`.
///
fn legalize_inst_arguments<ArgType>(
@@ -402,7 +402,7 @@ fn legalize_inst_arguments<ArgType>(
abi_args: usize,
mut get_abi_type: ArgType,
) where
ArgType: FnMut(&Function, usize) -> ArgumentType,
ArgType: FnMut(&Function, usize) -> AbiParam,
{
let inst = pos.current_inst().expect(
"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.
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| {
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| {
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
// the legalized signature.
let special_args = func.signature
.return_types
.returns
.iter()
.rev()
.take_while(|&rt| {
@@ -545,13 +545,13 @@ pub fn handle_return_abi(inst: Inst, func: &mut Function, cfg: &ControlFlowGraph
rt.purpose == ArgumentPurpose::VMContext
})
.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);
pos.use_srcloc(inst);
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);
@@ -565,7 +565,7 @@ pub fn handle_return_abi(inst: Inst, func: &mut Function, cfg: &ControlFlowGraph
pos.func.dfg.display_inst(inst, None)
);
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 {
ArgumentPurpose::Link |
ArgumentPurpose::StructReturn |
@@ -578,7 +578,7 @@ pub fn handle_return_abi(inst: Inst, func: &mut Function, cfg: &ControlFlowGraph
// the end.
let idx = pos.func
.signature
.argument_types
.params
.iter()
.rposition(|t| t.purpose == arg.purpose)
.expect("No matching special purpose argument.");
@@ -605,17 +605,12 @@ pub fn handle_return_abi(inst: Inst, func: &mut Function, cfg: &ControlFlowGraph
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`
/// stack slot already during legalization.
fn spill_entry_arguments(func: &mut Function, entry: Ebb) {
for (abi, &arg) in func.signature.argument_types.iter().zip(
func.dfg.ebb_params(
entry,
),
)
{
fn spill_entry_params(func: &mut Function, entry: Ebb) {
for (abi, &arg) in func.signature.params.iter().zip(func.dfg.ebb_params(entry)) {
if let ArgumentLoc::Stack(offset) = abi.location {
let ss = func.stack_slots.make_incoming_arg(abi.value_type, offset);
func.locations[arg] = ValueLoc::Stack(ss);
@@ -648,7 +643,7 @@ fn spill_call_arguments(pos: &mut FuncCursor) -> bool {
.dfg
.inst_variable_args(inst)
.iter()
.zip(&pos.func.dfg.signatures[sig_ref].argument_types)
.zip(&pos.func.dfg.signatures[sig_ref].params)
.enumerate()
.filter_map(|(idx, (&arg, abi))| {
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.
fn vmctx_addr(inst: ir::Inst, func: &mut ir::Function, offset: i64) {
// 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",
);

View File

@@ -9,7 +9,7 @@
//! larger register class instead.
use std::fmt;
use ir::{ArgumentType, ArgumentLoc};
use ir::{AbiParam, ArgumentLoc};
use isa::{TargetIsa, RegInfo, RegClassIndex, OperandConstraint, ConstraintKind};
/// Preferred register allocation for an SSA value.
@@ -48,7 +48,7 @@ impl Affinity {
}
/// 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 {
ArgumentLoc::Unassigned => Affinity::None,
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)
);
// 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
// `incoming_arg` stack slot too.
if let ValueDef::Param(def_ebb, def_num) = self.func.dfg.value_def(pred_val) {
if Some(def_ebb) == self.func.layout.entry_block() &&
self.func.signature.argument_types[def_num]
.location
.is_stack()
self.func.signature.params[def_num].location.is_stack()
{
dbg!("Isolating incoming stack parameter {}", 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 dominator_tree::DominatorTree;
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::{TargetIsa, EncInfo, RecipeConstraints, OperandConstraint, ConstraintKind};
use packed_option::PackedOption;
@@ -188,10 +188,10 @@ impl<'a> Context<'a> {
);
if self.cur.func.layout.entry_block() == Some(ebb) {
// Arguments to the entry block have ABI constraints.
self.color_entry_args(tracker.live())
// Parameters on the entry block have ABI constraints.
self.color_entry_params(tracker.live())
} 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.
self.livein_regs(tracker.live())
}
@@ -230,19 +230,19 @@ impl<'a> Context<'a> {
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.
///
/// 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;
assert_eq!(sig.argument_types.len(), args.len());
assert_eq!(sig.params.len(), args.len());
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 {
Affinity::Reg(rci) => {
let rc = self.reginfo.rc(rci);
@@ -305,7 +305,7 @@ impl<'a> Context<'a> {
program_input_abi(
&mut self.solver,
inst,
&self.cur.func.dfg.signatures[sig].argument_types,
&self.cur.func.dfg.signatures[sig].params,
&self.cur.func,
&self.liveness,
&self.reginfo,
@@ -315,7 +315,7 @@ impl<'a> Context<'a> {
program_input_abi(
&mut self.solver,
inst,
&self.cur.func.signature.return_types,
&self.cur.func.signature.returns,
&self.cur.func,
&self.liveness,
&self.reginfo,
@@ -687,12 +687,9 @@ impl<'a> Context<'a> {
// 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.
// Just assume all results are variable return values.
assert_eq!(
defs.len(),
self.cur.func.dfg.signatures[sig].return_types.len()
);
assert_eq!(defs.len(), self.cur.func.dfg.signatures[sig].returns.len());
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 Affinity::Reg(rci) = lv.affinity {
let rc = self.reginfo.rc(rci);
@@ -1015,7 +1012,7 @@ impl<'a> Context<'a> {
fn program_input_abi(
solver: &mut Solver,
inst: Inst,
abi_types: &[ArgumentType],
abi_types: &[AbiParam],
func: &Function,
liveness: &Liveness,
reginfo: &RegInfo,

View File

@@ -216,7 +216,7 @@ fn get_or_create<'a>(
.or_else(|| {
// If this is a call, get the return value affinity.
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();
@@ -226,7 +226,7 @@ fn get_or_create<'a>(
if func.layout.entry_block() == Some(ebb) {
// The affinity for entry block parameters can be inferred from the function
// signature.
affinity = Affinity::abi(&func.signature.argument_types[num], isa);
affinity = Affinity::abi(&func.signature.params[num], isa);
} else {
// Don't apply any affinity to normal EBB parameters.
// 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 entity::{SparseMap, SparseMapValue};
use ir::{Ebb, Inst, Value, Function};
use ir::{InstBuilder, ArgumentType, ArgumentLoc};
use ir::{InstBuilder, AbiParam, ArgumentLoc};
use isa::RegClass;
use isa::{TargetIsa, Encoding, EncInfo, RecipeConstraints, ConstraintKind};
use regalloc::affinity::Affinity;
@@ -137,20 +137,20 @@ impl<'a> Context<'a> {
if self.cur.func.layout.entry_block() == Some(ebb) {
assert_eq!(liveins.len(), 0);
self.visit_entry_args(ebb, args);
self.visit_entry_params(ebb, args);
} else {
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.
fn visit_entry_args(&mut self, ebb: Ebb, args: &[LiveValue]) {
assert_eq!(self.cur.func.signature.argument_types.len(), args.len());
fn visit_entry_params(&mut self, ebb: Ebb, args: &[LiveValue]) {
assert_eq!(self.cur.func.signature.params.len(), args.len());
self.cur.goto_first_inst(ebb);
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 {
ArgumentLoc::Reg(_) => {
if arg.affinity.is_stack() {
@@ -266,7 +266,7 @@ impl<'a> Context<'a> {
"Extra results on non-call instruction",
);
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());
if lv.affinity.is_stack() {
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) {
handle_abi_args(
self.candidates,
&self.cur.func.dfg.signatures[sig].argument_types,
&self.cur.func.dfg.signatures[sig].params,
var_args,
self.cur.isa,
self.liveness,
@@ -316,7 +316,7 @@ impl<'a> Context<'a> {
} else if self.cur.func.dfg[inst].opcode().is_return() {
handle_abi_args(
self.candidates,
&self.cur.func.signature.return_types,
&self.cur.func.signature.returns,
var_args,
self.cur.isa,
self.liveness,
@@ -348,7 +348,7 @@ impl<'a> Context<'a> {
/// return values and call arguments.
fn handle_abi_args(
candidates: &mut Vec<ReloadCandidate>,
abi_types: &[ArgumentType],
abi_types: &[AbiParam],
var_args: &[Value],
isa: &TargetIsa,
liveness: &Liveness,

View File

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

View File

@@ -129,7 +129,7 @@ impl<'a> LocationVerifier<'a> {
let varargs = self.func.dfg.inst_variable_args(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(
inst,
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(
inst,
value,
@@ -157,7 +157,7 @@ impl<'a> LocationVerifier<'a> {
let sig = &self.func.signature;
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(
inst,
value,
@@ -175,7 +175,7 @@ impl<'a> LocationVerifier<'a> {
&self,
inst: ir::Inst,
value: ir::Value,
abi: &ir::ArgumentType,
abi: &ir::AbiParam,
loc: ir::ValueLoc,
want_kind: ir::StackSlotKind,
) -> Result {

View File

@@ -241,7 +241,7 @@ impl<'a> Verifier<'a> {
let fixed_results = inst_data.opcode().constraints().fixed_results();
// var_results is 0 if we aren't a call instruction
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);
let total_results = fixed_results + var_results;
@@ -551,9 +551,9 @@ impl<'a> Verifier<'a> {
Ok(())
}
fn typecheck_entry_block_arguments(&self) -> Result {
fn typecheck_entry_block_params(&self) -> Result {
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);
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) {
CallInfo::Direct(func_ref, _) => {
let sig_ref = self.func.dfg.ext_funcs[func_ref].signature;
let arg_types = self.func.dfg.signatures[sig_ref]
.argument_types
.iter()
.map(|a| a.value_type);
let arg_types = self.func.dfg.signatures[sig_ref].params.iter().map(|a| {
a.value_type
});
self.typecheck_variable_args_iterator(inst, arg_types)?;
self.check_outgoing_args(inst, sig_ref)?;
}
CallInfo::Indirect(sig_ref, _) => {
let arg_types = self.func.dfg.signatures[sig_ref]
.argument_types
.iter()
.map(|a| a.value_type);
let arg_types = self.func.dfg.signatures[sig_ref].params.iter().map(|a| {
a.value_type
});
self.typecheck_variable_args_iterator(inst, arg_types)?;
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 expected_args = &sig.argument_types[..];
let expected_args = &sig.params[..];
for (&arg, &abi) in args.iter().zip(expected_args) {
// 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 {
if self.func.dfg[inst].opcode().is_return() {
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() {
return err!(inst, "arguments of return must match function signature");
}
@@ -1081,7 +1079,7 @@ impl<'a> Verifier<'a> {
pub fn run(&self) -> Result {
self.verify_global_vars()?;
self.typecheck_entry_block_arguments()?;
self.typecheck_entry_block_params()?;
for ebb in self.func.layout.ebbs() {
for inst in self.func.layout.ebb_insts(ebb) {
self.ebb_integrity(ebb, inst)?;

View File

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

View File

@@ -36,7 +36,7 @@
//! extern crate cton_frontend;
//!
//! 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::settings;
//! use cton_frontend::{ILBuilder, FunctionBuilder};
@@ -64,8 +64,8 @@
//!
//! fn main() {
//! let mut sig = Signature::new(CallConv::Native);
//! sig.return_types.push(ArgumentType::new(I32));
//! sig.argument_types.push(ArgumentType::new(I32));
//! sig.returns.push(AbiParam::new(I32));
//! sig.params.push(AbiParam::new(I32));
//! let mut il_builder = ILBuilder::<Variable>::new();
//! 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::mem;
use cretonne::ir::{Function, Ebb, Opcode, Value, Type, FunctionName, CallConv, StackSlotData,
JumpTable, JumpTableData, Signature, ArgumentType, ArgumentExtension,
ExtFuncData, SigRef, FuncRef, StackSlot, ValueLoc, ArgumentLoc, MemFlags,
GlobalVar, GlobalVarData, Heap, HeapData, HeapStyle, HeapBase};
JumpTable, JumpTableData, Signature, AbiParam, ArgumentExtension, ExtFuncData,
SigRef, FuncRef, StackSlot, ValueLoc, ArgumentLoc, MemFlags, GlobalVar,
GlobalVarData, Heap, HeapData, HeapStyle, HeapBase};
use cretonne::ir;
use cretonne::ir::types::VOID;
use cretonne::ir::immediates::{Imm64, Uimm32, Offset32, Ieee32, Ieee64};
@@ -918,7 +918,7 @@ impl<'a> Parser<'a> {
// Parse a function signature.
//
// signature ::= * "(" [arglist] ")" ["->" retlist] [callconv]
// signature ::= * "(" [paramlist] ")" ["->" retlist] [callconv]
//
fn parse_signature(&mut self, unique_isa: Option<&TargetIsa>) -> Result<Signature> {
// Calling convention defaults to `native`, but can be changed.
@@ -928,16 +928,16 @@ impl<'a> Parser<'a> {
Token::LPar,
"expected function signature: ( args... )",
)?;
// signature ::= "(" * [arglist] ")" ["->" retlist] [callconv]
// signature ::= "(" * [abi-param-list] ")" ["->" retlist] [callconv]
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(
Token::RPar,
"expected ')' after function arguments",
)?;
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.
@@ -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();
}
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();
// arglist ::= * arg { "," arg }
list.push(self.parse_argument_type(unique_isa)?);
// abi-param-list ::= * abi-param { "," abi-param }
list.push(self.parse_abi_param(unique_isa)?);
// arglist ::= arg * { "," arg }
// abi-param-list ::= abi-param * { "," abi-param }
while self.optional(Token::Comma) {
// arglist ::= arg { "," * arg }
list.push(self.parse_argument_type(unique_isa)?);
// abi-param-list ::= abi-param { "," * abi-param }
list.push(self.parse_abi_param(unique_isa)?);
}
Ok(list)
}
// Parse a single argument type with flags.
fn parse_argument_type(&mut self, unique_isa: Option<&TargetIsa>) -> Result<ArgumentType> {
// arg ::= * type { flag } [ argumentloc ]
let mut arg = ArgumentType::new(self.match_type("expected argument type")?);
fn parse_abi_param(&mut self, unique_isa: Option<&TargetIsa>) -> Result<AbiParam> {
// abi-param ::= * type { flag } [ argumentloc ]
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() {
match s {
"uext" => arg.extension = ArgumentExtension::Uext,
@@ -998,7 +998,7 @@ impl<'a> Parser<'a> {
self.consume();
}
// arg ::= type { flag } * [ argumentloc ]
// abi-param ::= type { flag } * [ argumentloc ]
arg.location = self.parse_argument_location(unique_isa)?;
Ok(arg)
@@ -1374,7 +1374,7 @@ impl<'a> Parser<'a> {
self.parse_ebb_params(ctx, ebb)?;
self.match_token(
Token::Colon,
"expected ':' after EBB arguments",
"expected ':' after EBB parameters",
)?;
}
@@ -1437,7 +1437,7 @@ impl<'a> Parser<'a> {
// ebb-params ::= * "(" ebb-param { "," ebb-param } ")"
self.match_token(
Token::LPar,
"expected '(' before EBB arguments",
"expected '(' before EBB parameters",
)?;
// ebb-params ::= "(" * ebb-param { "," ebb-param } ")"
@@ -1452,7 +1452,7 @@ impl<'a> Parser<'a> {
// ebb-params ::= "(" ebb-param { "," ebb-param } * ")"
self.match_token(
Token::RPar,
"expected ')' after EBB arguments",
"expected ')' after EBB parameters",
)?;
Ok(())
@@ -2337,13 +2337,13 @@ mod tests {
#[test]
fn argument_type() {
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.extension, ArgumentExtension::Sext);
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!(message, "expected argument type");
assert_eq!(message, "expected parameter type");
}
#[test]
@@ -2374,8 +2374,8 @@ mod tests {
#[test]
fn signature() {
let sig = Parser::new("()native").parse_signature(None).unwrap();
assert_eq!(sig.argument_types.len(), 0);
assert_eq!(sig.return_types.len(), 0);
assert_eq!(sig.params.len(), 0);
assert_eq!(sig.returns.len(), 0);
assert_eq!(sig.call_conv, CallConv::Native);
let sig2 = Parser::new("(i8 uext, f32, f64, i32 sret) -> i32 sext, f64 spiderwasm")
@@ -2406,7 +2406,7 @@ mod tests {
.parse_signature(None)
.unwrap_err()
.to_string(),
"1: expected argument type"
"1: expected parameter type"
);
assert_eq!(
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.
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;
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
// signature arguments. For example, a `vmctx` pointer.
if arg_type.purpose == ir::ArgumentPurpose::Normal {
@@ -256,12 +256,8 @@ mod tests {
let mut ctx = Context::new();
ctx.func.name = ir::FunctionName::new("small1");
ctx.func.signature.argument_types.push(
ir::ArgumentType::new(I32),
);
ctx.func.signature.return_types.push(
ir::ArgumentType::new(I32),
);
ctx.func.signature.params.push(ir::AbiParam::new(I32));
ctx.func.signature.returns.push(ir::AbiParam::new(I32));
trans
.translate(&BODY, &mut ctx.func, &mut runtime.func_env())
@@ -291,12 +287,8 @@ mod tests {
let mut ctx = Context::new();
ctx.func.name = ir::FunctionName::new("small2");
ctx.func.signature.argument_types.push(
ir::ArgumentType::new(I32),
);
ctx.func.signature.return_types.push(
ir::ArgumentType::new(I32),
);
ctx.func.signature.params.push(ir::AbiParam::new(I32));
ctx.func.signature.returns.push(ir::AbiParam::new(I32));
trans
.translate(&BODY, &mut ctx.func, &mut runtime.func_env())
@@ -335,9 +327,7 @@ mod tests {
let mut ctx = Context::new();
ctx.func.name = ir::FunctionName::new("infloop");
ctx.func.signature.return_types.push(
ir::ArgumentType::new(I32),
);
ctx.func.signature.returns.push(ir::AbiParam::new(I32));
trans
.translate(&BODY, &mut ctx.func, &mut runtime.func_env())

View File

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

View File

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