Add entity references as a new operand kind.

Define known entities in the cretonne.entities module.
This commit is contained in:
Jakob Stoklund Olesen
2016-05-18 15:30:16 -07:00
parent 1dcac579fb
commit d85fda0346
7 changed files with 96 additions and 41 deletions

View File

@@ -36,11 +36,11 @@ Here is the same function compiled into Cretonne IL:
The first line of a function definition provides the function *name* and
the :term:`function signature` which declares the argument and return types.
Then follows the :term:`function preample` which declares a number of entities
that can be referenced inside the function. In the example above, the preample
Then follows the :term:`function preamble` which declares a number of entities
that can be referenced inside the function. In the example above, the preamble
declares a single local variable, ``ss1``.
After the preample follows the :term:`function body` which consists of
After the preamble follows the :term:`function body` which consists of
:term:`extended basic block`\s, one of which is marked as the :term:`entry
block`. Every EBB ends with a :term:`terminator instruction`, so execution can
never fall through to the next EBB without an explicit branch.
@@ -49,7 +49,7 @@ A ``.cton`` file consists of a sequence of independent function definitions:
.. productionlist::
function-list : { function }
function : function-spec "{" preample function-body "}"
function : function-spec "{" preamble function-body "}"
function-spec : "function" function-name signature
preamble : { preamble-decl }
function-body : { extended-basic-block }
@@ -361,12 +361,12 @@ instruction in the EBB.
blocks. Split critical edges as needed to work around this.
:arg iN x: Integer index into jump table.
:arg JT: Jump table which was declared in the preample.
:arg JT: Jump table which was declared in the preamble.
:result: None.
.. inst:: JT = jump_table EBB0, EBB1, ..., EBBn
Declare a jump table in the :term:`function preample`.
Declare a jump table in the :term:`function preamble`.
This declares a jump table for use by the :inst:`br_table` indirect branch
instruction. Entries in the table are either EBB names, or ``0`` which
@@ -433,7 +433,7 @@ dependent. They make it possible to call native functions on the target
platform. When calling other Cretonne functions, the flags are not necessary.
Functions that are called directly must be declared in the :term:`function
preample`:
preamble`:
.. inst:: F = function NAME signature
@@ -476,7 +476,7 @@ This simple example illustrates direct function calls and signatures::
return v1
}
Indirect function calls use a signature declared in the preample.
Indirect function calls use a signature declared in the preamble.
.. inst:: SIG = signature signature
@@ -556,12 +556,12 @@ Local variables
One set of restricted memory operations access the current function's stack
frame. The stack frame is divided into fixed-size stack slots that are
allocated in the :term:`function preample`. Stack slots are not typed, they
allocated in the :term:`function preamble`. Stack slots are not typed, they
simply represent a contiguous sequence of bytes in the stack frame.
.. inst:: SS = stack_slot Bytes, Flags...
Allocate a stack slot in the preample.
Allocate a stack slot in the preamble.
If no alignment is specified, Cretonne will pick an appropriate alignment
for the stack slot based on its size and access patterns.
@@ -633,14 +633,14 @@ all process memory. Instead, it is given a small set of memory areas to work
in, and all accesses are bounds checked. Cretonne models this through the
concept of *heaps*.
A heap is declared in the function preample and can be accessed with restricted
A heap is declared in the function preamble and can be accessed with restricted
instructions that trap on out-of-bounds accesses. Heap addresses can be smaller
than the native pointer size, for example unsigned :type:`i32` offsets on a
64-bit architecture.
.. inst:: H = heap Name
Declare a heap in the function preample.
Declare a heap in the function preamble.
This doesn't allocate memory, it just retrieves a handle to a sandbox from
the runtime environment.
@@ -1034,9 +1034,9 @@ Glossary
is not necessary to know when calling it, so it is just an attribute,
and not part of the signature.
function preample
function preamble
A list of declarations of entities that are used by the function body.
Some of the entities that can be declared in the preample are:
Some of the entities that can be declared in the preamble are:
- Local variables.
- Functions that are called directly.
@@ -1045,7 +1045,7 @@ Glossary
function body
The extended basic blocks which contain all the executable code in a
function. The function body follows the function preample.
function. The function body follows the function preamble.
basic block
A maximal sequence of instructions that can only be entered from the

View File

@@ -47,14 +47,14 @@ must be instances of the :class:`Operand` class.
.. autoclass:: Operand
Cretonne uses two separate type systems for immediate operands and SSA values.
Cretonne uses two separate type systems for operand kinds and SSA values.
Type variables
--------------
Instruction descriptions can be made polymorphic by using :class:`Operand`
instances that refer to a *type variable* instead of a concrete value type.
Polymorphism only works for SSA value operands. Immediate operands have a fixed
Polymorphism only works for SSA value operands. Other operands have a fixed
operand kind.
.. autoclass:: TypeVar
@@ -95,6 +95,18 @@ indicated with an instance of :class:`ImmediateKind`.
.. currentmodule:: cretonne
Entity references
-----------------
Instruction operands can also refer to other entties in the same function. This
can be extended basic blocks, or entities declared in the function preamble.
.. autoclass:: EntityRefKind
.. automodule:: cretonne.entities
:members:
.. currentmodule:: cretonne
Value types
-----------
@@ -133,13 +145,14 @@ representation depends on the input operand kinds and whether the instruction
can produce multiple results.
.. autoclass:: OperandKind
.. inheritance-diagram:: OperandKind ImmediateKind EntityRefkind
Since all SSA value operands are represented as a `Value` in Rust code, value
types don't affect the representation. Two special operand kinds are used to
represent SSA values:
.. autodata:: value
.. autodata:: args
.. autodata:: variable_args
When an instruction description is created, it is automatically assigned a
predefined instruction format which is an instance of

View File

@@ -42,6 +42,12 @@ class OperandKind(object):
def __repr__(self):
return 'OperandKind({})'.format(self.name)
def operand_kind(self):
"""
An `OperandKind` instance can be used directly as the type of an
`Operand` when defining an instruction.
"""
return self
#: An SSA value operand. This is a value defined by another instruction.
value = OperandKind(
@@ -55,8 +61,8 @@ value = OperandKind(
#: A variable-sized list of value operands. Use for Ebb and function call
#: arguments.
args = OperandKind(
'args', """
variable_args = OperandKind(
'variable_args', """
A variable size list of `value` operands.
Use this to represent arguemtns passed to a function call, arguments
@@ -65,8 +71,8 @@ args = OperandKind(
""")
# Instances of immediate operand types are provided in the cretonne.immediates
# module.
# Instances of immediate operand types are provided in the
# `cretonne.immediates` module.
class ImmediateKind(OperandKind):
"""
The kind of an immediate instruction operand.
@@ -79,12 +85,20 @@ class ImmediateKind(OperandKind):
def __repr__(self):
return 'ImmediateKind({})'.format(self.name)
def operand_kind(self):
# Instances of entity reference operand types are provided in the
# `cretonne.entities` module.
class EntityRefKind(OperandKind):
"""
An `ImmediateKind` instance can be used directly as the type of an
`Operand` when defining an instruction.
The kind of an entity reference instruction operand.
"""
return self
def __init__(self, name, doc):
self.name = name
self.__doc__ = doc
def __repr__(self):
return 'EntityRefKind({})'.format(self.name)
# ValueType instances (i8, i32, ...) are provided in the cretonne.types module.
@@ -315,8 +329,8 @@ class InstructionGroup(object):
class Operand(object):
"""
An instruction operand can be either an *immediate* or an *SSA value*. The
type of the operand is one of:
An instruction operand can be an *immediate*, an *SSA value*, or an *entity
reference*. The type of the operand is one of:
1. A :py:class:`ValueType` instance indicates an SSA value operand with a
concrete type.
@@ -329,6 +343,10 @@ class Operand(object):
whose value is encoded in the instruction itself rather than being
passed as an SSA value.
4. An :py:class:`EntityRefKind` instance indicates an operand that
references another entity in the function, typically something declared
in the function preamble.
"""
def __init__(self, name, typ, doc=''):
self.name = name
@@ -429,9 +447,9 @@ class Instruction(object):
:param name: Instruction mnemonic, also becomes opcode name.
:param doc: Documentation string.
:param ins: Tuple of input operands. This can be a mix of SSA value
operands and immediate operands.
:param outs: Tuple of output operands. The output operands can't be
immediates.
operands and other operand kinds.
:param outs: Tuple of output operands. The output operands must be SSA
values.
"""
def __init__(self, name, doc, ins=(), outs=(), **kwargs):

23
meta/cretonne/entities.py Normal file
View File

@@ -0,0 +1,23 @@
"""
The `cretonne.entities` module predefines all the Cretonne entity reference
operand types. Thee are corresponding definitions in the `cretonne.entities`
Rust module.
"""
from . import EntityRefKind
#: A reference to an extended basic block in the same function.
#: This is primarliy used in control flow instructions.
ebb = EntityRefKind('ebb', 'An extended basic block in the same function.')
#: A reference to a stack slot declared in the function preamble.
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.')
#: 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.')

View File

@@ -7,8 +7,9 @@ in this module.
"""
from . import InstructionFormat, value, args
from . import InstructionFormat, value, variable_args
from immediates import imm64, ieee32, ieee64, immvector
from entities import function
Nullary = InstructionFormat()
@@ -22,7 +23,7 @@ Binary = InstructionFormat(value, value)
BinaryImm = InstructionFormat(value, imm64)
BinaryImmRev = InstructionFormat(imm64, value)
Call = InstructionFormat(args, multiple_results=True)
Call = InstructionFormat(function, variable_args, multiple_results=True)
# Finally extract the names of global variables in this module.
InstructionFormat.extract_names(globals())

View File

@@ -1,5 +1,5 @@
"""
The cretonne.immediates module predefines all the Cretonne immediate operand
The `cretonne.immediates` module predefines all the Cretonne immediate operand
types.
"""

View File

@@ -300,19 +300,19 @@ impl<'a> Parser<'a> {
// Parse a whole function definition.
//
// function ::= * function-spec "{" preample function-body "}"
// function ::= * function-spec "{" preamble function-body "}"
//
fn parse_function(&mut self) -> Result<Function> {
let (name, sig) = try!(self.parse_function_spec());
let mut ctx = Context::new(Function::with_name_signature(name, sig));
// function ::= function-spec * "{" preample function-body "}"
// function ::= function-spec * "{" preamble function-body "}"
try!(self.match_token(Token::LBrace, "expected '{' before function body"));
// function ::= function-spec "{" * preample function-body "}"
// function ::= function-spec "{" * preamble function-body "}"
try!(self.parse_preamble(&mut ctx));
// function ::= function-spec "{" preample * function-body "}"
// function ::= function-spec "{" preamble * function-body "}"
try!(self.parse_function_body(&mut ctx));
// function ::= function-spec "{" preample function-body * "}"
// function ::= function-spec "{" preamble function-body * "}"
try!(self.match_token(Token::RBrace, "expected '}' after function body"));
Ok(ctx.function)