Browse Source

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.
pull/3/head
Jakob Stoklund Olesen 8 years ago
parent
commit
7cf25a073b
  1. 4
      docs/langref.rst
  2. 4
      meta/cretonne/entities.py
  3. 4
      meta/cretonne/formats.py
  4. 78
      src/libcretonne/ir/entities.rs
  5. 22
      src/libcretonne/ir/instructions.rs
  6. 2
      src/libcretonne/ir/mod.rs
  7. 4
      src/libreader/lexer.rs

4
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:

4
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(

4
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)

78
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<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::*;

22
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

2
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;

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

Loading…
Cancel
Save