Add FuncRef and SigRef entity references.
These refer to external functions and function signatures declared in the preamble. Since we're already using the type names 'Signature' and 'Function', these entity references don't folow the usual EntityData / Entity naming convention.
This commit is contained in:
@@ -245,6 +245,68 @@ impl Default for JumpTable {
|
||||
}
|
||||
}
|
||||
|
||||
/// A reference to an external function.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub struct FuncRef(u32);
|
||||
|
||||
impl EntityRef for FuncRef {
|
||||
fn new(index: usize) -> FuncRef {
|
||||
assert!(index < (u32::MAX as usize));
|
||||
FuncRef(index as u32)
|
||||
}
|
||||
|
||||
fn index(self) -> usize {
|
||||
self.0 as usize
|
||||
}
|
||||
}
|
||||
|
||||
/// Display a `FuncRef` reference as "fn12".
|
||||
impl Display for FuncRef {
|
||||
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
|
||||
write!(fmt, "fn{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// A guaranteed invalid function reference.
|
||||
pub const NO_FUNC_REF: FuncRef = FuncRef(u32::MAX);
|
||||
|
||||
impl Default for FuncRef {
|
||||
fn default() -> FuncRef {
|
||||
NO_FUNC_REF
|
||||
}
|
||||
}
|
||||
|
||||
/// A reference to a function signature.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub struct SigRef(u32);
|
||||
|
||||
impl EntityRef for SigRef {
|
||||
fn new(index: usize) -> SigRef {
|
||||
assert!(index < (u32::MAX as usize));
|
||||
SigRef(index as u32)
|
||||
}
|
||||
|
||||
fn index(self) -> usize {
|
||||
self.0 as usize
|
||||
}
|
||||
}
|
||||
|
||||
/// Display a `SigRef` reference as "sig12".
|
||||
impl Display for SigRef {
|
||||
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
|
||||
write!(fmt, "sig{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// A guaranteed invalid function reference.
|
||||
pub const NO_SIG_REF: SigRef = SigRef(u32::MAX);
|
||||
|
||||
impl Default for SigRef {
|
||||
fn default() -> SigRef {
|
||||
NO_SIG_REF
|
||||
}
|
||||
}
|
||||
|
||||
/// A reference to any of the entities defined in this module.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum AnyEntity {
|
||||
@@ -255,6 +317,8 @@ pub enum AnyEntity {
|
||||
Value(Value),
|
||||
StackSlot(StackSlot),
|
||||
JumpTable(JumpTable),
|
||||
FuncRef(FuncRef),
|
||||
SigRef(SigRef),
|
||||
}
|
||||
|
||||
impl Display for AnyEntity {
|
||||
@@ -266,6 +330,8 @@ impl Display for AnyEntity {
|
||||
AnyEntity::Value(r) => r.fmt(fmt),
|
||||
AnyEntity::StackSlot(r) => r.fmt(fmt),
|
||||
AnyEntity::JumpTable(r) => r.fmt(fmt),
|
||||
AnyEntity::FuncRef(r) => r.fmt(fmt),
|
||||
AnyEntity::SigRef(r) => r.fmt(fmt),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -300,6 +366,18 @@ impl From<JumpTable> for AnyEntity {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FuncRef> for AnyEntity {
|
||||
fn from(r: FuncRef) -> AnyEntity {
|
||||
AnyEntity::FuncRef(r)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SigRef> for AnyEntity {
|
||||
fn from(r: SigRef) -> AnyEntity {
|
||||
AnyEntity::SigRef(r)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -10,8 +10,7 @@ use std::fmt::{self, Display, Formatter};
|
||||
use std::str::FromStr;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use ir::{Value, Type, Ebb, JumpTable};
|
||||
use ir::entities::NO_VALUE;
|
||||
use ir::{Value, Type, Ebb, JumpTable, FuncRef};
|
||||
use ir::immediates::{Imm64, Ieee32, Ieee64};
|
||||
use ir::condcodes::*;
|
||||
use ir::types;
|
||||
@@ -321,7 +320,10 @@ pub struct CallData {
|
||||
/// Second result value for a call producing multiple return values.
|
||||
second_result: Value,
|
||||
|
||||
// Dynamically sized array containing call argument values.
|
||||
/// Callee function.
|
||||
pub func_ref: FuncRef,
|
||||
|
||||
/// Dynamically sized array containing call argument values.
|
||||
pub varargs: VariableArgs,
|
||||
}
|
||||
|
||||
@@ -338,20 +340,6 @@ pub struct ReturnData {
|
||||
pub varargs: VariableArgs,
|
||||
}
|
||||
|
||||
impl InstructionData {
|
||||
/// Create data for a call instruction.
|
||||
pub fn call(opc: Opcode, return_type: Type) -> InstructionData {
|
||||
InstructionData::Call {
|
||||
opcode: opc,
|
||||
ty: return_type,
|
||||
data: Box::new(CallData {
|
||||
second_result: NO_VALUE,
|
||||
varargs: VariableArgs::new(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Analyzing an instruction.
|
||||
///
|
||||
/// Avoid large matches on instruction formats by using the methods efined here to examine
|
||||
|
||||
@@ -16,7 +16,7 @@ mod extfunc;
|
||||
pub use ir::funcname::FunctionName;
|
||||
pub use ir::extfunc::{Signature, ArgumentType, ArgumentExtension};
|
||||
pub use ir::types::Type;
|
||||
pub use ir::entities::{Ebb, Inst, Value, StackSlot, JumpTable};
|
||||
pub use ir::entities::{Ebb, Inst, Value, StackSlot, JumpTable, FuncRef, SigRef};
|
||||
pub use ir::instructions::{Opcode, InstructionData};
|
||||
pub use ir::stackslot::StackSlotData;
|
||||
pub use ir::jumptable::JumpTableData;
|
||||
|
||||
@@ -34,6 +34,8 @@ pub enum Token<'a> {
|
||||
Ebb(Ebb), // ebb3
|
||||
StackSlot(u32), // ss3
|
||||
JumpTable(u32), // jt2
|
||||
FuncRef(u32), // fn2
|
||||
SigRef(u32), // sig2
|
||||
Identifier(&'a str), // Unrecognized identifier (opcode, enumerator, ...)
|
||||
}
|
||||
|
||||
@@ -285,6 +287,8 @@ impl<'a> Lexer<'a> {
|
||||
"ebb" => Ebb::with_number(number).map(|ebb| Token::Ebb(ebb)),
|
||||
"ss" => Some(Token::StackSlot(number)),
|
||||
"jt" => Some(Token::JumpTable(number)),
|
||||
"fn" => Some(Token::FuncRef(number)),
|
||||
"sig" => Some(Token::SigRef(number)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user