Implement jump tables (#453)
* Add 'jump_table_entry' and 'indirect_jump' instructions. * Update CodeSink to keep track of code size. Pretty up clif-util's disassembly output. * Only disassemble the machine portion of output. Pretty print the read-only data after it. * Update switch frontend code to use new br_table instruction w/ default.
This commit is contained in:
committed by
Dan Gohman
parent
de1d82b4ba
commit
79cea5e18b
@@ -50,7 +50,10 @@ Branch = InstructionFormat(VALUE, ebb, VARIABLE_ARGS)
|
||||
BranchInt = InstructionFormat(intcc, VALUE, ebb, VARIABLE_ARGS)
|
||||
BranchFloat = InstructionFormat(floatcc, VALUE, ebb, VARIABLE_ARGS)
|
||||
BranchIcmp = InstructionFormat(intcc, VALUE, VALUE, ebb, VARIABLE_ARGS)
|
||||
BranchTable = InstructionFormat(VALUE, entities.jump_table)
|
||||
BranchTable = InstructionFormat(VALUE, ebb, entities.jump_table)
|
||||
BranchTableEntry = InstructionFormat(VALUE, VALUE, uimm8, entities.jump_table)
|
||||
BranchTableBase = InstructionFormat(entities.jump_table)
|
||||
IndirectJump = InstructionFormat(VALUE, entities.jump_table)
|
||||
|
||||
Call = InstructionFormat(func_ref, VARIABLE_ARGS)
|
||||
CallIndirect = InstructionFormat(sig_ref, VALUE, VARIABLE_ARGS)
|
||||
|
||||
@@ -130,6 +130,8 @@ brff = Instruction(
|
||||
ins=(Cond, f, EBB, args), is_branch=True)
|
||||
|
||||
x = Operand('x', iB, doc='index into jump table')
|
||||
Entry = TypeVar('Entry', 'A scalar integer type', ints=True)
|
||||
entry = Operand('entry', Entry, doc='entry of jump table')
|
||||
JT = Operand('JT', entities.jump_table)
|
||||
br_table = Instruction(
|
||||
'br_table', r"""
|
||||
@@ -137,12 +139,47 @@ br_table = Instruction(
|
||||
|
||||
Use ``x`` as an unsigned index into the jump table ``JT``. If a jump
|
||||
table entry is found, branch to the corresponding EBB. If no entry was
|
||||
found fall through to the next instruction.
|
||||
found or the index is out-of-bounds, branch to the given default EBB.
|
||||
|
||||
Note that this branch instruction can't pass arguments to the targeted
|
||||
blocks. Split critical edges as needed to work around this.
|
||||
""",
|
||||
ins=(x, JT), is_branch=True)
|
||||
ins=(x, EBB, JT), is_branch=True, is_terminator=True)
|
||||
|
||||
Size = Operand('Size', uimm8, 'Size in bytes')
|
||||
jump_table_entry = Instruction(
|
||||
'jump_table_entry', r"""
|
||||
Get an entry from a jump table.
|
||||
|
||||
Load a serialized ``entry`` from a jump table ``JT`` at a given index
|
||||
``addr`` with a specific ``Size``. The retrieved entry may need to be
|
||||
decoded after loading, depending upon the jump table type used.
|
||||
|
||||
Currently, the only type supported is entries which are relative to the
|
||||
base of the jump table.
|
||||
""",
|
||||
ins=(x, addr, Size, JT), outs=entry)
|
||||
|
||||
jump_table_base = Instruction(
|
||||
'jump_table_base', r"""
|
||||
Get the absolute base address of a jump table.
|
||||
|
||||
This is used for jump tables wherein the entries are stored relative to
|
||||
the base of jump table. In order to use these, generated code should first
|
||||
load an entry using ``jump_table_entry``, then use this instruction to add
|
||||
the relative base back to it.
|
||||
""",
|
||||
ins=JT, outs=addr)
|
||||
|
||||
indirect_jump_table_br = Instruction(
|
||||
'indirect_jump_table_br', r"""
|
||||
Branch indirectly via a jump table entry.
|
||||
|
||||
Unconditionally jump via a jump table entry that was previously loaded
|
||||
with the ``jump_table_entry`` instruction.
|
||||
""",
|
||||
ins=(addr, JT),
|
||||
is_branch=True, is_indirect_branch=True, is_terminator=True)
|
||||
|
||||
code = Operand('code', trapcode)
|
||||
trap = Instruction(
|
||||
|
||||
@@ -306,10 +306,10 @@ widen.legalize(
|
||||
|
||||
for int_ty in [types.i8, types.i16]:
|
||||
widen.legalize(
|
||||
br_table.bind(int_ty)(x, y),
|
||||
br_table.bind(int_ty)(x, y, z),
|
||||
Rtl(
|
||||
b << uextend.i32(x),
|
||||
br_table(b, y),
|
||||
br_table(b, y, z),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -166,4 +166,13 @@ probestack_size_log2 = NumSetting(
|
||||
""",
|
||||
default=12)
|
||||
|
||||
#
|
||||
# Jump table options.
|
||||
#
|
||||
jump_tables_enabled = BoolSetting(
|
||||
"""
|
||||
Enable the use of jump tables in generated machine code.
|
||||
""",
|
||||
default=True)
|
||||
|
||||
group.close(globals())
|
||||
|
||||
Reference in New Issue
Block a user