diff --git a/docs/langref.rst b/docs/langref.rst index 0851ea8fcd..1d987fb3c7 100644 --- a/docs/langref.rst +++ b/docs/langref.rst @@ -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 diff --git a/docs/metaref.rst b/docs/metaref.rst index 5858ef512e..c0b75f4101 100644 --- a/docs/metaref.rst +++ b/docs/metaref.rst @@ -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 diff --git a/meta/cretonne/__init__.py b/meta/cretonne/__init__.py index 8ce84394da..0447cdfcc0 100644 --- a/meta/cretonne/__init__.py +++ b/meta/cretonne/__init__.py @@ -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): diff --git a/meta/cretonne/entities.py b/meta/cretonne/entities.py new file mode 100644 index 0000000000..67265ee844 --- /dev/null +++ b/meta/cretonne/entities.py @@ -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.') diff --git a/meta/cretonne/formats.py b/meta/cretonne/formats.py index cb02d80998..9ea555a257 100644 --- a/meta/cretonne/formats.py +++ b/meta/cretonne/formats.py @@ -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()) diff --git a/meta/cretonne/immediates.py b/meta/cretonne/immediates.py index af7bd72feb..e8e581d64d 100644 --- a/meta/cretonne/immediates.py +++ b/meta/cretonne/immediates.py @@ -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. """ diff --git a/src/libreader/parser.rs b/src/libreader/parser.rs index f390f0dcfa..ab37e0896a 100644 --- a/src/libreader/parser.rs +++ b/src/libreader/parser.rs @@ -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 { 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)