Add OperandKind to the meta language.

We have a two-level type system: OperandKinds and ValueTypes. The value types
only apply to value operands, but there are many more kinds of operands:
immediate numbers, condition codes, basic block references, etc.
This commit is contained in:
Jakob Stoklund Olesen
2016-05-12 15:59:40 -07:00
parent ea46a17f56
commit 477fa01bfc
4 changed files with 120 additions and 62 deletions

View File

@@ -15,15 +15,15 @@ module :mod:`cretonne.base`.
.. module:: cretonne .. module:: cretonne
Types Value Types
===== ===========
Concrete value types are represented as instances of :class:`cretonne.Type`. There are Concrete value types are represented as instances of :class:`cretonne.ValueType`. There are
subclasses to represent scalar and vector types. subclasses to represent scalar and vector types.
.. inheritance-diagram:: Type ScalarType VectorType IntType FloatType .. inheritance-diagram:: ValueType ScalarType VectorType IntType FloatType
:parts: 1 :parts: 1
.. autoclass:: Type .. autoclass:: ValueType
.. autoclass:: ScalarType .. autoclass:: ScalarType
:members: :members:
.. autoclass:: VectorType .. autoclass:: VectorType
@@ -48,33 +48,35 @@ types for their operands. This makes the instructions polymorphic.
.. autoclass:: TypeVar .. autoclass:: TypeVar
Immediates
----------
Immediate instruction operands don't correspond to SSA values, but have values
that are encoded directly in the instruction. Immediate operands don't
have types from the :class:`cretonne.Type` type system; they often have
enumerated values of a specific type. The type of an immediate operand is
indicated with an instance of :class:`ImmediateType`.
.. autoclass:: ImmediateType
.. automodule:: cretonne.immediates
:members:
.. currentmodule:: cretonne
Instructions Instructions
============ ============
New instructions are defined as instances of the :class:`cretonne.Instruction` New instructions are defined as instances of the :class:`cretonne.Instruction`
class. class.
.. autoclass:: Operand
.. autoclass:: Instruction .. autoclass:: Instruction
.. autoclass:: Operand
.. autoclass:: OperandKind
.. autoclass:: InstructionGroup .. autoclass:: InstructionGroup
:members: :members:
Immediates
----------
Immediate instruction operands don't correspond to SSA values, but have values
that are encoded directly in the instruction. Immediate operands don't
have types from the :class:`cretonne.ValueType` type system; they often have
enumerated values of a specific type. The type of an immediate operand is
indicated with an instance of :class:`ImmediateKind`.
.. autoclass:: ImmediateKind
.. automodule:: cretonne.immediates
:members:
.. currentmodule:: cretonne
Targets Targets
======= =======

View File

@@ -16,13 +16,75 @@ def camel_case(s):
return camel_re.sub(lambda m: m.group(2).upper(), s) return camel_re.sub(lambda m: m.group(2).upper(), s)
# Concrete types. # Kinds of operands.
# #
# Instances (i8, i32, ...) are provided in the cretonne.types module. # 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):
"""
The kind of an operand.
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):
self.name = name
self.__doc__ = doc
# The camel-cased name of an operand kind is also the Rust type used to
# represent it.
self.camel_name = camel_case(name)
def __str__(self):
return self.name
def __repr__(self):
return 'OperandKind({})'.format(self.name)
class Type(object): #: An SSA value operand. This is a value defined by another instruction.
"""A concrete value type.""" 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.
""")
# Instances of immediate operand types are provided in the cretonne.immediates
# module.
class ImmediateKind(OperandKind):
"""
The type of an immediate instruction operand.
"""
def __init__(self, name, doc):
self.name = name
self.__doc__ = doc
def __repr__(self):
return 'ImmediateKind({})'.format(self.name)
def operand_kind(self):
"""
An `ImmediateKind` instance can be used directly as the type of an
`Operand` when defining an instruction.
"""
return self
# ValueType instances (i8, i32, ...) are provided in the cretonne.types module.
class ValueType(object):
"""
A concrete SSA value type.
All SSA values have a type that is described by an instance of `ValueType`
or one of its subclasses.
"""
def __init__(self, name, membytes, doc): def __init__(self, name, membytes, doc):
self.name = name self.name = name
@@ -32,8 +94,15 @@ class Type(object):
def __str__(self): def __str__(self):
return self.name return self.name
def operand_kind(self):
"""
When a `ValueType` object is used to describe the type of an `Operand`
in an instruction definition, the kind of that operand is an SSA value.
"""
return value
class ScalarType(Type):
class ScalarType(ValueType):
""" """
A concrete scalar (not vector) type. A concrete scalar (not vector) type.
@@ -62,7 +131,7 @@ class ScalarType(Type):
return v return v
class VectorType(Type): class VectorType(ValueType):
""" """
A concrete SIMD vector type. A concrete SIMD vector type.
@@ -144,27 +213,12 @@ class TypeVar(object):
self.name = name self.name = name
self.__doc__ = doc self.__doc__ = doc
def operand_kind(self):
# Immediate operands.
#
# Instances of immediate operand types are provided in the cretonne.immediates
# module.
class ImmediateType(object):
""" """
The type of an immediate instruction operand. When a `TypeVar` object is used to describe the type of an `Operand`
in an instruction definition, the kind of that operand is an SSA value.
""" """
return value
def __init__(self, name, doc):
self.name = name
self.__doc__ = doc
def __str__(self):
return self.name
def __repr__(self):
return 'ImmediateType({})'.format(self.name)
# Defining instructions. # Defining instructions.
@@ -225,14 +279,14 @@ class Operand(object):
An instruction operand can be either an *immediate* or an *SSA value*. The An instruction operand can be either an *immediate* or an *SSA value*. The
type of the operand is one of: type of the operand is one of:
1. A :py:class:`Type` instance indicates an SSA value operand with a 1. A :py:class:`ValueType` instance indicates an SSA value operand with a
concrete type. concrete type.
2. A :py:class:`TypeVar` instance indicates an SSA value operand, and the 2. A :py:class:`TypeVar` instance indicates an SSA value operand, and the
instruction is polymorphic over the possible concrete types that the instruction is polymorphic over the possible concrete types that the
type variable can assume. type variable can assume.
3. An :py:class:`ImmediateType` instance indicates an immediate operand 3. An :py:class:`ImmediateKind` instance indicates an immediate operand
whose value is encoded in the instruction itself rather than being whose value is encoded in the instruction itself rather than being
passed as an SSA value. passed as an SSA value.
@@ -241,6 +295,7 @@ class Operand(object):
self.name = name self.name = name
self.typ = typ self.typ = typ
self.__doc__ = doc self.__doc__ = doc
self.kind = typ.operand_kind()
def get_doc(self): def get_doc(self):
if self.__doc__: if self.__doc__:
@@ -251,7 +306,7 @@ class Operand(object):
class Instruction(object): class Instruction(object):
""" """
An instruction. An instruction description.
The operands to the instruction are specified as two tuples: ``ins`` and The operands to the instruction are specified as two tuples: ``ins`` and
``outs``. Since the Python singleton tuple syntax is a bit awkward, it is ``outs``. Since the Python singleton tuple syntax is a bit awkward, it is

View File

@@ -281,6 +281,7 @@ ishl = Instruction(
a &:= x \cdot 2^s \pmod{2^B}. a &:= x \cdot 2^s \pmod{2^B}.
.. todo:: Add ``ishl_imm`` variant with an immediate ``y``. .. todo:: Add ``ishl_imm`` variant with an immediate ``y``.
""", """,
ins=(x, y), outs=a) ins=(x, y), outs=a)

View File

@@ -1,25 +1,25 @@
""" """
The cretonne.immdiates module predefines all the Cretonne immediate operand The cretonne.immediates module predefines all the Cretonne immediate operand
types. types.
""" """
from . import ImmediateType from . import ImmediateKind
#: A 64-bit immediate integer operand. #: A 64-bit immediate integer operand.
#: #:
#: This type of immediate integer can interact with SSA values with any #: This type of immediate integer can interact with SSA values with any
#: :py:class:`cretonne.IntType` type. #: :py:class:`cretonne.IntType` type.
imm64 = ImmediateType('imm64', 'A 64-bit immediate integer.') imm64 = ImmediateKind('imm64', 'A 64-bit immediate integer.')
#: A 32-bit immediate floating point operand. #: A 32-bit immediate floating point operand.
#: #:
#: IEEE 754-2008 binary32 interchange format. #: IEEE 754-2008 binary32 interchange format.
ieee32 = ImmediateType('ieee32', 'A 32-bit immediate floating point number.') ieee32 = ImmediateKind('ieee32', 'A 32-bit immediate floating point number.')
#: A 64-bit immediate floating point operand. #: A 64-bit immediate floating point operand.
#: #:
#: IEEE 754-2008 binary64 interchange format. #: IEEE 754-2008 binary64 interchange format.
ieee64 = ImmediateType('ieee64', 'A 64-bit immediate floating point number.') ieee64 = ImmediateKind('ieee64', 'A 64-bit immediate floating point number.')
#: A large SIMD vector constant. #: A large SIMD vector constant.
immvector = ImmediateType('immvector', 'An immediate SIMD vector.') immvector = ImmediateKind('immvector', 'An immediate SIMD vector.')