Add is_call and is_return instruction attributes.

This commit is contained in:
Jakob Stoklund Olesen
2017-03-08 14:48:50 -08:00
parent cbbf5cc88b
commit ecc46e56e1
3 changed files with 23 additions and 31 deletions

View File

@@ -111,7 +111,7 @@ x_return = Instruction(
provided return values. The list of return values must match the provided return values. The list of return values must match the
function signature's return types. function signature's return types.
""", """,
ins=rvals, is_terminator=True) ins=rvals, is_return=True, is_terminator=True)
raddr = Operand('raddr', iAddr, doc='Return address') raddr = Operand('raddr', iAddr, doc='Return address')
@@ -130,7 +130,7 @@ return_reg = Instruction(
:inst:`return` will be legalized into this instruction on these :inst:`return` will be legalized into this instruction on these
architectures. architectures.
""", """,
ins=(raddr, rvals), is_terminator=True) ins=(raddr, rvals), is_return=True, is_terminator=True)
FN = Operand( FN = Operand(
'FN', 'FN',
@@ -145,8 +145,7 @@ call = Instruction(
Call a function which has been declared in the preamble. The argument Call a function which has been declared in the preamble. The argument
types must match the function's signature. types must match the function's signature.
""", """,
ins=(FN, args), ins=(FN, args), outs=rvals, is_call=True)
outs=rvals)
SIG = Operand('SIG', entities.sig_ref, doc='function signature') SIG = Operand('SIG', entities.sig_ref, doc='function signature')
callee = Operand('callee', iAddr, doc='address of function to call') callee = Operand('callee', iAddr, doc='address of function to call')
@@ -158,8 +157,7 @@ call_indirect = Instruction(
Call the function pointed to by `callee` with the given arguments. The Call the function pointed to by `callee` with the given arguments. The
called function must match the specified signature. called function must match the specified signature.
""", """,
ins=(SIG, callee, args), ins=(SIG, callee, args), outs=rvals, is_call=True)
outs=rvals)
# #
# Materializing constants. # Materializing constants.

View File

@@ -80,9 +80,22 @@ class Instruction(object):
values or `variable_args`. values or `variable_args`.
:param is_terminator: This is a terminator instruction. :param is_terminator: This is a terminator instruction.
:param is_branch: This is a branch instruction. :param is_branch: This is a branch instruction.
:param is_call: This is a call instruction.
:param is_return: This is a return instruction.
:param can_trap: This instruction can trap. :param can_trap: This instruction can trap.
""" """
# Boolean instruction attributes that can be passed as keyword arguments to
# the constructor. Map attribute name to doc comment for generated Rust
# code.
ATTRIBS = {
'is_terminator': 'True for instructions that terminate the EBB.',
'is_branch': 'True for all branch or jump instructions.',
'is_call': 'Is this a call instruction?',
'is_return': 'Is this a return instruction?',
'can_trap': 'Can this instruction cause a trap?',
}
def __init__(self, name, doc, ins=(), outs=(), **kwargs): def __init__(self, name, doc, ins=(), outs=(), **kwargs):
# type: (str, str, OpList, OpList, **Any) -> None # noqa # type: (str, str, OpList, OpList, **Any) -> None # noqa
self.name = name self.name = name
@@ -95,9 +108,8 @@ class Instruction(object):
self.value_results = tuple( self.value_results = tuple(
i for i, o in enumerate(self.outs) if o.is_value()) i for i, o in enumerate(self.outs) if o.is_value())
self._verify_polymorphic() self._verify_polymorphic()
self.is_branch = 'is_branch' in kwargs for attr in Instruction.ATTRIBS:
self.is_terminator = 'is_terminator' in kwargs setattr(self, attr, not not kwargs.get(attr, False))
self.can_trap = 'can_trap' in kwargs
InstructionGroup.append(self) InstructionGroup.append(self)
def __str__(self): def __str__(self):

View File

@@ -288,31 +288,13 @@ def gen_opcodes(groups, fmt):
fmt.line() fmt.line()
with fmt.indented('impl Opcode {', '}'): with fmt.indented('impl Opcode {', '}'):
attrs = [ for attr in sorted(Instruction.ATTRIBS.keys()):
{ fmt.doc_comment(Instruction.ATTRIBS[attr])
'name': 'is_branch',
'comment': 'True for all branch instructions.'
},
{
'name': 'is_terminator',
'comment': 'True for instructions that terminate EBB.'
},
{
'name': 'can_trap',
'comment': 'True if instruction could trap.'
}
]
for attr in attrs:
if attr != attrs[0]:
fmt.line()
fmt.doc_comment(attr['comment'])
with fmt.indented('pub fn {}(self) -> bool {{' with fmt.indented('pub fn {}(self) -> bool {{'
.format(attr['name']), '}'): .format(attr), '}'):
with fmt.indented('match self {', '}'): with fmt.indented('match self {', '}'):
for i in instrs: for i in instrs:
if getattr(i, attr['name']): if getattr(i, attr):
fmt.format( fmt.format(
'Opcode::{} => true,', 'Opcode::{} => true,',
i.camel_name, i.name) i.camel_name, i.name)