From 7cf25a073b83f5a9f3eef90cf9b35710b8151baa Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Wed, 12 Oct 2016 14:15:29 -0700 Subject: [PATCH] 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. --- docs/langref.rst | 4 +- meta/cretonne/entities.py | 4 +- meta/cretonne/formats.py | 4 +- src/libcretonne/ir/entities.rs | 78 ++++++++++++++++++++++++++++++ src/libcretonne/ir/instructions.rs | 22 ++------- src/libcretonne/ir/mod.rs | 2 +- src/libreader/lexer.rs | 4 ++ 7 files changed, 94 insertions(+), 24 deletions(-) diff --git a/docs/langref.rst b/docs/langref.rst index e4d2d9dbd3..b2ced79300 100644 --- a/docs/langref.rst +++ b/docs/langref.rst @@ -394,11 +394,11 @@ preamble`: This simple example illustrates direct function calls and signatures:: function gcd(i32 uext, i32 uext) -> i32 uext "C" { - f1 = function divmod(i32 uext, i32 uext) -> i32 uext, i32 uext + fn1 = function divmod(i32 uext, i32 uext) -> i32 uext, i32 uext ebb1(v1: i32, v2: i32): brz v2, ebb2 - v3, v4 = call f1(v1, v2) + v3, v4 = call fn1(v1, v2) br ebb1(v2, v4) ebb2: diff --git a/meta/cretonne/entities.py b/meta/cretonne/entities.py index 907fb64359..317006f79f 100644 --- a/meta/cretonne/entities.py +++ b/meta/cretonne/entities.py @@ -18,11 +18,11 @@ stack_slot = EntityRefKind('stack_slot', 'A stack slot.') #: A reference to a function sugnature declared in the function preamble. #: Tbis is used to provide the call signature in an indirect call instruction. -signature = EntityRefKind('signature', 'A function signature.') +sig_ref = EntityRefKind('sig_ref', 'A function signature.') #: A reference to an external function declared in the function preamble. #: This is used to provide the callee and signature in a call instruction. -function = EntityRefKind('function', 'An external function.') +func_ref = EntityRefKind('func_ref', 'An external function.') #: A reference to a jump table declared in the function preamble. jump_table = EntityRefKind( diff --git a/meta/cretonne/formats.py b/meta/cretonne/formats.py index df0019bff4..11a1c5ef3b 100644 --- a/meta/cretonne/formats.py +++ b/meta/cretonne/formats.py @@ -8,7 +8,7 @@ in this module. from __future__ import absolute_import from . import InstructionFormat, value, variable_args from .immediates import imm64, uimm8, ieee32, ieee64, immvector, intcc, floatcc -from .entities import ebb, function, jump_table +from .entities import ebb, func_ref, jump_table Nullary = InstructionFormat() @@ -46,7 +46,7 @@ Branch = InstructionFormat(value, ebb, variable_args, boxed_storage=True) BranchTable = InstructionFormat(value, jump_table) Call = InstructionFormat( - function, variable_args, multiple_results=True, boxed_storage=True) + func_ref, variable_args, multiple_results=True, boxed_storage=True) Return = InstructionFormat(variable_args, boxed_storage=True) diff --git a/src/libcretonne/ir/entities.rs b/src/libcretonne/ir/entities.rs index 5672e5b3d3..bd8913e5bf 100644 --- a/src/libcretonne/ir/entities.rs +++ b/src/libcretonne/ir/entities.rs @@ -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 for AnyEntity { } } +impl From for AnyEntity { + fn from(r: FuncRef) -> AnyEntity { + AnyEntity::FuncRef(r) + } +} + +impl From for AnyEntity { + fn from(r: SigRef) -> AnyEntity { + AnyEntity::SigRef(r) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/libcretonne/ir/instructions.rs b/src/libcretonne/ir/instructions.rs index 6b3e0e5ffe..56ce5ed5fd 100644 --- a/src/libcretonne/ir/instructions.rs +++ b/src/libcretonne/ir/instructions.rs @@ -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 diff --git a/src/libcretonne/ir/mod.rs b/src/libcretonne/ir/mod.rs index 285fab96e5..90581d5f12 100644 --- a/src/libcretonne/ir/mod.rs +++ b/src/libcretonne/ir/mod.rs @@ -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; diff --git a/src/libreader/lexer.rs b/src/libreader/lexer.rs index 3454225dc8..04801b2644 100644 --- a/src/libreader/lexer.rs +++ b/src/libreader/lexer.rs @@ -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, } }