Add helper routines for special-purpose arguments.
- ArgumentType::special() creates a new special-purpose argument without assigning it to a register location. - Signature::special_arg_index() funds a unique special-purpose argument. - Function::special_arg() finds a special-purpose argument by value. Also add a new "sigid" argument purpose which will be used for runtime signature checks in WebAssembly indirect calls.
This commit is contained in:
@@ -76,6 +76,13 @@ impl Signature {
|
|||||||
pub fn display<'a, R: Into<Option<&'a RegInfo>>>(&'a self, regs: R) -> DisplaySignature<'a> {
|
pub fn display<'a, R: Into<Option<&'a RegInfo>>>(&'a self, regs: R) -> DisplaySignature<'a> {
|
||||||
DisplaySignature(self, regs.into())
|
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,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wrapper type capable of displaying a `Signature` with correct register names.
|
/// Wrapper type capable of displaying a `Signature` with correct register names.
|
||||||
@@ -146,6 +153,16 @@ 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 {
|
||||||
|
value_type: vt,
|
||||||
|
extension: ArgumentExtension::None,
|
||||||
|
purpose,
|
||||||
|
location: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Create an argument type for a special-purpose register.
|
/// Create an argument type 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) -> ArgumentType {
|
||||||
ArgumentType {
|
ArgumentType {
|
||||||
@@ -255,10 +272,16 @@ pub enum ArgumentPurpose {
|
|||||||
/// This is a pointer to a context struct containing details about the current sandbox. It is
|
/// This is a pointer to a context struct containing details about the current sandbox. It is
|
||||||
/// used as a base pointer for `vmctx` global variables.
|
/// used as a base pointer for `vmctx` global variables.
|
||||||
VMContext,
|
VMContext,
|
||||||
|
|
||||||
|
/// A signature identifier.
|
||||||
|
///
|
||||||
|
/// This is a special-purpose argument used to identify the calling convention expected by the
|
||||||
|
/// caller in an indirect call. The callee can verify that the expected signature ID matches.
|
||||||
|
SignatureId,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Text format names of the `ArgumentPurpose` variants.
|
/// Text format names of the `ArgumentPurpose` variants.
|
||||||
static PURPOSE_NAMES: [&str; 6] = ["normal", "sret", "link", "fp", "csr", "vmctx"];
|
static PURPOSE_NAMES: [&str; 7] = ["normal", "sret", "link", "fp", "csr", "vmctx", "sigid"];
|
||||||
|
|
||||||
impl fmt::Display for ArgumentPurpose {
|
impl fmt::Display for ArgumentPurpose {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
@@ -276,6 +299,7 @@ impl FromStr for ArgumentPurpose {
|
|||||||
"fp" => Ok(ArgumentPurpose::FramePointer),
|
"fp" => Ok(ArgumentPurpose::FramePointer),
|
||||||
"csr" => Ok(ArgumentPurpose::CalleeSaved),
|
"csr" => Ok(ArgumentPurpose::CalleeSaved),
|
||||||
"vmctx" => Ok(ArgumentPurpose::VMContext),
|
"vmctx" => Ok(ArgumentPurpose::VMContext),
|
||||||
|
"sigid" => Ok(ArgumentPurpose::SignatureId),
|
||||||
_ => Err(()),
|
_ => Err(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,6 +135,16 @@ impl Function {
|
|||||||
pub fn display<'a, I: Into<Option<&'a TargetIsa>>>(&'a self, isa: I) -> DisplayFunction<'a> {
|
pub fn display<'a, I: Into<Option<&'a TargetIsa>>>(&'a self, isa: I) -> DisplayFunction<'a> {
|
||||||
DisplayFunction(self, isa.into())
|
DisplayFunction(self, isa.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Find a presumed unique special-purpose function argument 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> {
|
||||||
|
let entry = self.layout.entry_block().expect("Function is empty");
|
||||||
|
self.signature.special_arg_index(purpose).map(|i| {
|
||||||
|
self.dfg.ebb_args(entry)[i]
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wrapper type capable of displaying a `Function` with correct ISA annotations.
|
/// Wrapper type capable of displaying a `Function` with correct ISA annotations.
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ fn legalize_entry_arguments(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;
|
||||||
|
let mut has_sigid = false;
|
||||||
|
|
||||||
// Insert position for argument conversion code.
|
// Insert position for argument conversion code.
|
||||||
// We want to insert instructions before the first instruction in the entry block.
|
// We want to insert instructions before the first instruction in the entry block.
|
||||||
@@ -91,6 +92,10 @@ fn legalize_entry_arguments(func: &mut Function, entry: Ebb) {
|
|||||||
assert!(!has_vmctx, "Multiple vmctx arguments found");
|
assert!(!has_vmctx, "Multiple vmctx arguments found");
|
||||||
has_vmctx = true;
|
has_vmctx = true;
|
||||||
}
|
}
|
||||||
|
ArgumentPurpose::SignatureId => {
|
||||||
|
assert!(!has_sigid, "Multiple sigid arguments found");
|
||||||
|
has_sigid = true;
|
||||||
|
}
|
||||||
_ => panic!("Unexpected special-purpose arg {}", abi_types[abi_arg]),
|
_ => panic!("Unexpected special-purpose arg {}", abi_types[abi_arg]),
|
||||||
}
|
}
|
||||||
abi_arg += 1;
|
abi_arg += 1;
|
||||||
@@ -145,6 +150,10 @@ fn legalize_entry_arguments(func: &mut Function, entry: Ebb) {
|
|||||||
assert!(!has_vmctx, "Multiple vmctx arguments found");
|
assert!(!has_vmctx, "Multiple vmctx arguments found");
|
||||||
has_vmctx = true;
|
has_vmctx = true;
|
||||||
}
|
}
|
||||||
|
ArgumentPurpose::SignatureId => {
|
||||||
|
assert!(!has_sigid, "Multiple sigid arguments found");
|
||||||
|
has_sigid = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Just create entry block values to match here. We will use them in `handle_return_abi()`
|
// Just create entry block values to match here. We will use them in `handle_return_abi()`
|
||||||
|
|||||||
Reference in New Issue
Block a user