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, } }