Add heaps to the Cretonne IL.
Add preamble syntax for declaring static and dynamic heaps, and update the langref section on heaps. Add IR support for heap references. Remove the heap_load and heap_store as discussed in #144. We will use heap_addr along with native load and store instructions in their place. Add the heap_addr instruction and document its bounds checking semantics.
This commit is contained in:
@@ -30,3 +30,6 @@ func_ref = EntityRefKind('func_ref', 'An external function.')
|
||||
#: A reference to a jump table declared in the function preamble.
|
||||
jump_table = EntityRefKind(
|
||||
'jump_table', 'A jump table.', default_member='table')
|
||||
|
||||
#: A reference to a heap declared in the function preamble.
|
||||
heap = EntityRefKind('heap', 'A heap.')
|
||||
|
||||
@@ -8,10 +8,11 @@ in this module.
|
||||
from __future__ import absolute_import
|
||||
from cdsl.formats import InstructionFormat
|
||||
from cdsl.operands import VALUE, VARIABLE_ARGS
|
||||
from .immediates import imm64, uimm8, ieee32, ieee64, offset32, uoffset32
|
||||
from .immediates import imm64, uimm8, uimm32, ieee32, ieee64
|
||||
from .immediates import offset32, uoffset32
|
||||
from .immediates import boolean, intcc, floatcc, memflags, regunit
|
||||
from . import entities
|
||||
from .entities import ebb, sig_ref, func_ref, stack_slot
|
||||
from .entities import ebb, sig_ref, func_ref, stack_slot, heap
|
||||
|
||||
Nullary = InstructionFormat()
|
||||
|
||||
@@ -59,6 +60,7 @@ StackStore = InstructionFormat(VALUE, stack_slot, offset32)
|
||||
# TODO: Add a reference to a `heap` declared in the preamble.
|
||||
HeapLoad = InstructionFormat(VALUE, uoffset32)
|
||||
HeapStore = InstructionFormat(VALUE, VALUE, uoffset32)
|
||||
HeapAddr = InstructionFormat(heap, VALUE, uimm32)
|
||||
|
||||
RegMove = InstructionFormat(VALUE, ('src', regunit), ('dst', regunit))
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ from cdsl.operands import Operand, VARIABLE_ARGS
|
||||
from cdsl.typevar import TypeVar
|
||||
from cdsl.instructions import Instruction, InstructionGroup
|
||||
from base.types import f32, f64, b1
|
||||
from base.immediates import imm64, uimm8, ieee32, ieee64, offset32, uoffset32
|
||||
from base.immediates import imm64, uimm8, uimm32, ieee32, ieee64, offset32
|
||||
from base.immediates import boolean, intcc, floatcc, memflags, regunit
|
||||
from base import entities
|
||||
from cdsl.ti import WiderOrEq
|
||||
@@ -360,40 +360,26 @@ global_addr = Instruction(
|
||||
#
|
||||
# WebAssembly bounds-checked heap accesses.
|
||||
#
|
||||
# TODO: Add a `heap` operand that selects between multiple heaps.
|
||||
# TODO: Should the immediate offset be a `u32`?
|
||||
# TODO: Distinguish between `iAddr` for a heap and for a target address? i.e.,
|
||||
# 32-bit WebAssembly on a 64-bit target has two different types.
|
||||
|
||||
Offset = Operand('Offset', uoffset32, 'Unsigned offset to effective address')
|
||||
HeapOffset = TypeVar('HeapOffset', 'An unsigned heap offset', ints=(32, 64))
|
||||
|
||||
heap_load = Instruction(
|
||||
'heap_load', r"""
|
||||
Load a value at the address :math:`p + Offset` in the heap H.
|
||||
|
||||
Trap if the heap access would be out of bounds.
|
||||
""",
|
||||
ins=(p, Offset), outs=a, can_load=True)
|
||||
|
||||
heap_store = Instruction(
|
||||
'heap_store', r"""
|
||||
Store a value at the address :math:`p + Offset` in the heap H.
|
||||
|
||||
Trap if the heap access would be out of bounds.
|
||||
""",
|
||||
ins=(x, p, Offset), can_store=True)
|
||||
H = Operand('H', entities.heap)
|
||||
p = Operand('p', HeapOffset)
|
||||
Size = Operand('Size', uimm32, 'Size in bytes')
|
||||
|
||||
heap_addr = Instruction(
|
||||
'heap_addr', r"""
|
||||
Bounds check and compute absolute address of heap memory.
|
||||
|
||||
Verify that the address range ``p .. p + Size - 1`` is valid in the
|
||||
heap H, and trap if not.
|
||||
Verify that the offset range ``p .. p + Size - 1`` is in bounds for the
|
||||
heap H, and generate an absolute address that is safe to dereference.
|
||||
|
||||
Convert the heap-relative address in ``p`` to a real absolute address
|
||||
and return it.
|
||||
1. If ``p + Size`` is not greater than the heap bound, return an
|
||||
absolute address corresponding to a byte offset of ``p`` from the
|
||||
heap's base address.
|
||||
2. If ``p + Size`` is greater than the heap bound, generate a trap.
|
||||
""",
|
||||
ins=(p, Offset), outs=addr)
|
||||
ins=(H, p, Size), outs=addr)
|
||||
|
||||
#
|
||||
# Materializing constants.
|
||||
|
||||
Reference in New Issue
Block a user