Add entity references as a new operand kind.
Define known entities in the cretonne.entities module.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
"""
|
||||
An `ImmediateKind` instance can be used directly as the type of an
|
||||
`Operand` when defining an instruction.
|
||||
"""
|
||||
return self
|
||||
|
||||
# Instances of entity reference operand types are provided in the
|
||||
# `cretonne.entities` module.
|
||||
class EntityRefKind(OperandKind):
|
||||
"""
|
||||
The kind of an entity reference instruction operand.
|
||||
"""
|
||||
|
||||
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
23
meta/cretonne/entities.py
Normal 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.')
|
||||
@@ -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())
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user