Load, store, local variables.
This commit is contained in:
@@ -19,7 +19,7 @@ from sphinx.directives import ObjectDescription
|
||||
from sphinx.domains import Domain, ObjType
|
||||
from sphinx.locale import l_, _
|
||||
from sphinx.roles import XRefRole
|
||||
from sphinx.util.docfields import Field, TypedField
|
||||
from sphinx.util.docfields import Field, GroupedField, TypedField
|
||||
from sphinx.util.nodes import make_refnode
|
||||
|
||||
class CtonObject(ObjectDescription):
|
||||
@@ -120,6 +120,7 @@ class CtonInst(CtonObject):
|
||||
TypedField('result', label=l_('Results'),
|
||||
names=('out', 'result'),
|
||||
typerolename='type', typenames=('type',)),
|
||||
GroupedField('flag', names=('flag',), label=l_('Flags')),
|
||||
Field('resulttype', label=l_('Result type'), has_arg=False,
|
||||
names=('rtype',)),
|
||||
]
|
||||
|
||||
@@ -28,7 +28,7 @@ class CretonneLexer(RegexLexer):
|
||||
# Reserved words.
|
||||
(keywords('function', 'entry'), Keyword),
|
||||
# Known attributes.
|
||||
(keywords('align', 'uext', 'sext', 'inreg'), Name.Attribute),
|
||||
(keywords('align', 'aligntrap', 'uext', 'sext', 'inreg'), Name.Attribute),
|
||||
# Well known value types.
|
||||
(r'\b(bool|i\d+|f32|f64)(x\d+)?\b', Keyword.Type),
|
||||
# v<nn> = value
|
||||
@@ -38,7 +38,7 @@ class CretonneLexer(RegexLexer):
|
||||
(r'(ebb)\d+', Name.Label),
|
||||
# Match instruction names in context.
|
||||
(r'(=)( *)([a-z]\w*)', bygroups(Operator, Whitespace, Name.Function)),
|
||||
(r'^( +)([a-z]\w*\b)(?! *[,=])', bygroups(Whitespace, Name.Function)),
|
||||
(r'^( *)([a-z]\w*\b)(?! *[,=])', bygroups(Whitespace, Name.Function)),
|
||||
# Other names: results and arguments
|
||||
(r'[a-z]\w*', Name),
|
||||
(r'->|=|:', Operator),
|
||||
|
||||
124
docs/langref.rst
124
docs/langref.rst
@@ -390,6 +390,130 @@ Indirect function calls use a signature declared in the preample.
|
||||
:inst:`br_table`.
|
||||
|
||||
|
||||
Memory
|
||||
======
|
||||
|
||||
Cretonne provides fully general :inst:`load` and :inst:`store` instructions for
|
||||
accessing memory. However, it can be very complicated to verify the safety of
|
||||
general loads and stores when compiling code for a sandboxed environment, so
|
||||
Cretonne also provides more restricted memory operations that are always safe.
|
||||
|
||||
.. inst:: a = load p, Offset, Flags...
|
||||
|
||||
Load from memory at ``p + Offset``.
|
||||
|
||||
This is a polymorphic instruction that can load any value type which has a
|
||||
memory representation (i.e., everything except :type:`bool` and boolean
|
||||
vectors).
|
||||
|
||||
:arg iPtr p: Base address.
|
||||
:arg Offset: Immediate signed offset.
|
||||
:flag align(N): Expected alignment of ``p + Offset``. Power of two.
|
||||
:flag aligntrap: Always trap if the memory access is misaligned.
|
||||
:result T a: Loaded value.
|
||||
|
||||
.. inst:: store x, p, Offset, Flags...
|
||||
|
||||
Store ``x`` to memory at ``p + Offset``.
|
||||
|
||||
This is a polymorphic instruction that can store any value type with a
|
||||
memory representation.
|
||||
|
||||
:arg T x: Value to store.
|
||||
:arg iPtr p: Base address.
|
||||
:arg Offset: Immediate signed offset.
|
||||
:flag align(N): Expected alignment of ``p + Offset``. Power of two.
|
||||
:flag aligntrap: Always trap if the memory access is misaligned.
|
||||
|
||||
Loads and stores are *misaligned* if the resultant address is not a multiple of
|
||||
the expected alignment. Depending on the target architecture, misaligned memory
|
||||
accesses may trap, or they may work. Sometimes, operating systems catch
|
||||
alignment traps and emulate the misaligned memory access.
|
||||
|
||||
On target architectures like x86 that don't check alignment, Cretonne expands
|
||||
the aligntrap flag into a conditional trap instruction::
|
||||
|
||||
v5 = load.i32 v1, 4, align(4), aligntrap
|
||||
; Becomes:
|
||||
v10 = and_imm v1, 3
|
||||
trapnz v10
|
||||
v5 = load.i32 v1, 4
|
||||
|
||||
|
||||
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
|
||||
simply represent a contiguous sequence of bytes in the stack frame.
|
||||
|
||||
.. inst:: SS = stack_slot Bytes, Flags...
|
||||
|
||||
Allocate a stack slot in the preample.
|
||||
|
||||
If no alignment is specified, Cretonne will pick an appropriate alignment
|
||||
for the stack slot based on its size and access patterns.
|
||||
|
||||
:arg Bytes: Stack slot size on bytes.
|
||||
:flag align(N): Request at least N bytes alignment.
|
||||
:result SS: Stack slot index.
|
||||
|
||||
.. inst:: a = stack_load SS, Offset
|
||||
|
||||
Load a value from a stack slot at the constant offset.
|
||||
|
||||
This is a polymorphic instruction that can load any value type which has a
|
||||
memory representation.
|
||||
|
||||
The offset is an immediate constant, not an SSA value. The memory access
|
||||
cannot go out of bounds, i.e. ``sizeof(a) + Offset <= sizeof(SS)``.
|
||||
|
||||
:arg SS: Stack slot declared with :inst:`stack_slot`.
|
||||
:arg Offset: Immediate non-negative offset.
|
||||
:result T a: Value loaded.
|
||||
|
||||
.. inst:: stack_store x, SS, Offset
|
||||
|
||||
Store a value to a stack slot at a constant offset.
|
||||
|
||||
This is a polymorphic instruction that can store any value type with a
|
||||
memory representation.
|
||||
|
||||
The offset is an immediate constant, not an SSA value. The memory access
|
||||
cannot go out of bounds, i.e. ``sizeof(a) + Offset <= sizeof(SS)``.
|
||||
|
||||
:arg T x: Value to be stored.
|
||||
:arg SS: Stack slot declared with :inst:`stack_slot`.
|
||||
:arg Offset: Immediate non-negative offset.
|
||||
|
||||
The dedicated stack access instructions are easy ofr the compiler to reason
|
||||
about because stack slots and offsets are fixed at compile time. For example,
|
||||
the alignment of these stack memory accesses can be inferred from the offsets
|
||||
and stack slot alignments.
|
||||
|
||||
It can be necessary to escape from the safety of the restricted instructions by
|
||||
taking the address of a stack slot.
|
||||
|
||||
.. inst:: a = stack_addr SS, Offset
|
||||
|
||||
Get the address of a stack slot.
|
||||
|
||||
Compute the absolute address of a byte in a stack slot. The offset must
|
||||
refer to a byte inside the stack slot: ``0 <= Offset < sizeof(SS)``.
|
||||
|
||||
:arg SS: Stack slot declared with :inst:`stack_slot`.
|
||||
:arg Offset: Immediate non-negative offset.
|
||||
:result iPtr a: Address.
|
||||
|
||||
The :inst:`stack_addr` instruction can be used to macro-expand the stack access
|
||||
instructions before instruction selection::
|
||||
|
||||
v1 = stack_load.f64 ss3, 16
|
||||
; Expands to:
|
||||
v9 = stack_addr ss3, 16
|
||||
v1 = load.f64 v9
|
||||
|
||||
|
||||
Operations
|
||||
==========
|
||||
|
||||
Reference in New Issue
Block a user