Files
wasmtime/lib/cretonne/meta/cdsl/operands.py
Jakob Stoklund Olesen aa06e40456 Allow dot syntax notation for enumerated immediate operands.
The meta language patterns sometimes need to refer to specific values of
enumerated immediate operands. The dot syntax provides a namespaced,
typed way of doing that: icmp(intcc.ult, a, x).

Add an ast.Enumerator class for representing this kind of AST leaf node.

Add value definitions for the intcc and floatcc immediate operand kinds.
2017-03-30 11:37:05 -07:00

209 lines
6.5 KiB
Python

"""Classes for describing instruction operands."""
from __future__ import absolute_import
from . import camel_case
from .types import ValueType
from .typevar import TypeVar
try:
from typing import Union, Dict, TYPE_CHECKING # noqa
OperandSpec = Union['OperandKind', ValueType, TypeVar]
if TYPE_CHECKING:
from .ast import Enumerator # noqa
except ImportError:
pass
# Kinds of operands.
#
# Each instruction has an opcode and a number of operands. The opcode
# determines the instruction format, and the format determines the number of
# operands and the kind of each operand.
class OperandKind(object):
"""
An instance of the `OperandKind` class corresponds to a kind of operand.
Each operand kind has a corresponding type in the Rust representation of an
instruction.
"""
def __init__(self, name, doc, default_member=None, rust_type=None):
# type: (str, str, str, str) -> None
self.name = name
self.__doc__ = doc
self.default_member = default_member
# The camel-cased name of an operand kind is also the Rust type used to
# represent it.
self.rust_type = rust_type or camel_case(name)
def __str__(self):
# type: () -> str
return self.name
def __repr__(self):
# type: () -> str
return 'OperandKind({})'.format(self.name)
#: An SSA value operand. This is a value defined by another instruction.
VALUE = OperandKind(
'value', """
An SSA value defined by another instruction.
This kind of operand can represent any SSA value type, but the
instruction format may restrict the valid value types for a given
operand.
""")
#: A variable-sized list of value operands. Use for Ebb and function call
#: arguments.
VARIABLE_ARGS = OperandKind(
'variable_args', """
A variable size list of `value` operands.
Use this to represent arguemtns passed to a function call, arguments
passed to an extended basic block, or a variable number of results
returned from an instruction.
""",
rust_type='&[Value]')
# Instances of immediate operand types are provided in the
# `cretonne.immediates` module.
class ImmediateKind(OperandKind):
"""
The kind of an immediate instruction operand.
:param default_member: The default member name of this kind the
`InstructionData` data structure.
"""
def __init__(
self, name, doc,
default_member='imm',
rust_type=None,
values=None):
# type: (str, str, str, str, Dict[str, str]) -> None
super(ImmediateKind, self).__init__(
name, doc, default_member, rust_type)
self.values = values
def __repr__(self):
# type: () -> str
return 'ImmediateKind({})'.format(self.name)
def __getattr__(self, value):
# type: (str) -> Enumerator
"""
Enumerated immediate kinds allow the use of dot syntax to produce
`Enumerator` AST nodes: `icmp.i32(intcc.ult, a, b)`.
"""
from .ast import Enumerator # noqa
if not self.values:
raise AssertionError(
'{n} is not an enumerated operand kind: {n}.{a}'.format(
n=self.name, a=value))
if value not in self.values:
raise AssertionError(
'No such {n} enumerator: {n}.{a}'.format(
n=self.name, a=value))
return Enumerator(self, value)
def rust_enumerator(self, value):
# type: (str) -> str
"""
Get the qualified Rust name of the enumerator value `value`.
"""
return '{}::{}'.format(self.rust_type, self.values[value])
# 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, default_member=None, rust_type=None):
# type: (str, str, str, str) -> None
super(EntityRefKind, self).__init__(
name, doc, default_member or name, rust_type)
def __repr__(self):
# type: () -> str
return 'EntityRefKind({})'.format(self.name)
class Operand(object):
"""
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.
2. A :py:class:`TypeVar` instance indicates an SSA value operand, and the
instruction is polymorphic over the possible concrete types that the
type variable can assume.
3. An :py:class:`ImmediateKind` instance indicates an immediate operand
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=''):
# type: (str, OperandSpec, str) -> None
self.name = name
self.__doc__ = doc
# Decode the operand spec and set self.kind.
# Only VALUE operands have a typevar member.
if isinstance(typ, ValueType):
self.kind = VALUE
self.typevar = TypeVar.singleton(typ)
elif isinstance(typ, TypeVar):
self.kind = VALUE
self.typevar = typ
else:
assert isinstance(typ, OperandKind)
self.kind = typ
def get_doc(self):
# type: () -> str
if self.__doc__:
return self.__doc__
if self.kind is VALUE:
return self.typevar.__doc__
return self.kind.__doc__
def __str__(self):
# type: () -> str
return "`{}`".format(self.name)
def is_value(self):
# type: () -> bool
"""
Is this an SSA value operand?
"""
return self.kind is VALUE
def is_varargs(self):
# type: () -> bool
"""
Is this a VARIABLE_ARGS operand?
"""
return self.kind is VARIABLE_ARGS
def is_immediate(self):
# type: () -> bool
"""
Is this an immediate operand?
Note that this includes both `ImmediateKind` operands *and* entity
references. It is any operand that doesn't represent a value
dependency.
"""
return self.kind is not VALUE and self.kind is not VARIABLE_ARGS