Move ValueType into a new cdsl top-level module.
We want to separate the Python classes that make up the DSL used to define the Cretonne language from the concrete definitions. - cdsl.types defines the ValueType class hierarchy. - base.types defines the concrete types.
This commit is contained in:
@@ -245,7 +245,7 @@ class TypeDocumenter(sphinx.ext.autodoc.Documenter):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def resolve_name(self, modname, parents, path, base):
|
def resolve_name(self, modname, parents, path, base):
|
||||||
return 'cretonne.types', [base]
|
return 'base.types', [base]
|
||||||
|
|
||||||
def add_content(self, more_content, no_docstring=False):
|
def add_content(self, more_content, no_docstring=False):
|
||||||
super(TypeDocumenter, self).add_content(more_content, no_docstring)
|
super(TypeDocumenter, self).add_content(more_content, no_docstring)
|
||||||
@@ -280,11 +280,11 @@ class InstDocumenter(sphinx.ext.autodoc.Documenter):
|
|||||||
op = inst.ins[0]
|
op = inst.ins[0]
|
||||||
sig += ' ' + op.name
|
sig += ' ' + op.name
|
||||||
# If the first input is variable-args, this is 'return'. No parens.
|
# If the first input is variable-args, this is 'return'. No parens.
|
||||||
if op.typ.operand_kind().name == 'variable_args':
|
if op.kind.name == 'variable_args':
|
||||||
sig += '...'.format(op.name)
|
sig += '...'.format(op.name)
|
||||||
for op in inst.ins[1:]:
|
for op in inst.ins[1:]:
|
||||||
# This is a call or branch with args in (...).
|
# This is a call or branch with args in (...).
|
||||||
if op.typ.operand_kind().name == 'variable_args':
|
if op.kind.name == 'variable_args':
|
||||||
sig += '({}...)'.format(op.name)
|
sig += '({}...)'.format(op.name)
|
||||||
else:
|
else:
|
||||||
sig += ', ' + op.name
|
sig += ', ' + op.name
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Cretonne Meta Language Reference
|
|||||||
|
|
||||||
.. default-domain:: py
|
.. default-domain:: py
|
||||||
.. highlight:: python
|
.. highlight:: python
|
||||||
.. module:: cretonne
|
.. module:: cdsl
|
||||||
|
|
||||||
The Cretonne meta language is used to define instructions for Cretonne. It is a
|
The Cretonne meta language is used to define instructions for Cretonne. It is a
|
||||||
domain specific language embedded in Python. This document describes the Python
|
domain specific language embedded in Python. This document describes the Python
|
||||||
@@ -16,8 +16,8 @@ steps:
|
|||||||
|
|
||||||
1. The Python modules are imported. This has the effect of building static data
|
1. The Python modules are imported. This has the effect of building static data
|
||||||
structures in global variables in the modules. These static data structures
|
structures in global variables in the modules. These static data structures
|
||||||
use the classes in the :mod:`cretonne` module to describe instruction sets
|
in the :mod:`base` and :mod:`isa` packages use the classes in the
|
||||||
and other properties.
|
:mod:`cdsl` module to describe instruction sets and other properties.
|
||||||
|
|
||||||
2. The static data structures are processed to produce Rust source code and
|
2. The static data structures are processed to produce Rust source code and
|
||||||
constant tables.
|
constant tables.
|
||||||
@@ -41,6 +41,7 @@ ISA, and defined in a `settings` module under the appropriate
|
|||||||
Settings can take boolean on/off values, small numbers, or explicitly enumerated
|
Settings can take boolean on/off values, small numbers, or explicitly enumerated
|
||||||
symbolic values. Each type is represented by a sub-class of :class:`Setting`:
|
symbolic values. Each type is represented by a sub-class of :class:`Setting`:
|
||||||
|
|
||||||
|
.. currentmodule:: cretonne
|
||||||
.. inheritance-diagram:: Setting BoolSetting NumSetting EnumSetting
|
.. inheritance-diagram:: Setting BoolSetting NumSetting EnumSetting
|
||||||
:parts: 1
|
:parts: 1
|
||||||
|
|
||||||
@@ -125,36 +126,36 @@ Immediate operands
|
|||||||
|
|
||||||
Immediate instruction operands don't correspond to SSA values, but have values
|
Immediate instruction operands don't correspond to SSA values, but have values
|
||||||
that are encoded directly in the instruction. Immediate operands don't
|
that are encoded directly in the instruction. Immediate operands don't
|
||||||
have types from the :class:`cretonne.ValueType` type system; they often have
|
have types from the :class:`cdsl.types.ValueType` type system; they often have
|
||||||
enumerated values of a specific type. The type of an immediate operand is
|
enumerated values of a specific type. The type of an immediate operand is
|
||||||
indicated with an instance of :class:`ImmediateKind`.
|
indicated with an instance of :class:`ImmediateKind`.
|
||||||
|
|
||||||
|
.. currentmodule:: cretonne
|
||||||
.. autoclass:: ImmediateKind
|
.. autoclass:: ImmediateKind
|
||||||
|
|
||||||
.. automodule:: cretonne.immediates
|
.. automodule:: cretonne.immediates
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
.. currentmodule:: cretonne
|
|
||||||
|
|
||||||
Entity references
|
Entity references
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
Instruction operands can also refer to other entities in the same function. This
|
Instruction operands can also refer to other entities in the same function. This
|
||||||
can be extended basic blocks, or entities declared in the function preamble.
|
can be extended basic blocks, or entities declared in the function preamble.
|
||||||
|
|
||||||
|
.. currentmodule:: cretonne
|
||||||
|
|
||||||
.. autoclass:: EntityRefKind
|
.. autoclass:: EntityRefKind
|
||||||
|
|
||||||
.. automodule:: cretonne.entities
|
.. automodule:: cretonne.entities
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
.. currentmodule:: cretonne
|
|
||||||
|
|
||||||
Value types
|
Value types
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
Concrete value types are represented as instances of :class:`cretonne.ValueType`. There are
|
Concrete value types are represented as instances of :class:`cdsl.types.ValueType`. There are
|
||||||
subclasses to represent scalar and vector types.
|
subclasses to represent scalar and vector types.
|
||||||
|
|
||||||
|
.. currentmodule:: cdsl.types
|
||||||
.. autoclass:: ValueType
|
.. autoclass:: ValueType
|
||||||
.. inheritance-diagram:: ValueType ScalarType VectorType IntType FloatType BoolType
|
.. inheritance-diagram:: ValueType ScalarType VectorType IntType FloatType BoolType
|
||||||
:parts: 1
|
:parts: 1
|
||||||
@@ -169,11 +170,9 @@ subclasses to represent scalar and vector types.
|
|||||||
.. autoclass:: BoolType
|
.. autoclass:: BoolType
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
.. automodule:: cretonne.types
|
.. automodule:: base.types
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
.. currentmodule:: cretonne
|
|
||||||
|
|
||||||
There are no predefined vector types, but they can be created as needed with
|
There are no predefined vector types, but they can be created as needed with
|
||||||
the :func:`ScalarType.by` function.
|
the :func:`ScalarType.by` function.
|
||||||
|
|
||||||
@@ -181,6 +180,8 @@ the :func:`ScalarType.by` function.
|
|||||||
Instruction representation
|
Instruction representation
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
|
.. currentmodule:: cretonne
|
||||||
|
|
||||||
The Rust in-memory representation of instructions is derived from the
|
The Rust in-memory representation of instructions is derived from the
|
||||||
instruction descriptions. Part of the representation is generated, and part is
|
instruction descriptions. Part of the representation is generated, and part is
|
||||||
written as Rust code in the `cretonne.instructions` module. The instruction
|
written as Rust code in the `cretonne.instructions` module. The instruction
|
||||||
|
|||||||
1
lib/cretonne/meta/base/__init__.py
Normal file
1
lib/cretonne/meta/base/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
"""Definitions for the base Cretonne language."""
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
"""
|
"""
|
||||||
The cretonne.types module predefines all the Cretonne scalar types.
|
The base.types module predefines all the Cretonne scalar types.
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
from . import ScalarType, IntType, FloatType, BoolType
|
from cdsl.types import ScalarType, IntType, FloatType, BoolType
|
||||||
|
|
||||||
#: Boolean.
|
#: Boolean.
|
||||||
b1 = ScalarType(
|
b1 = ScalarType(
|
||||||
6
lib/cretonne/meta/cdsl/__init__.py
Normal file
6
lib/cretonne/meta/cdsl/__init__.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
"""
|
||||||
|
Cretonne DSL classes.
|
||||||
|
|
||||||
|
This module defines the classes that are used to define Cretonne instructions
|
||||||
|
and other entitties.
|
||||||
|
"""
|
||||||
160
lib/cretonne/meta/cdsl/types.py
Normal file
160
lib/cretonne/meta/cdsl/types.py
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
"""Cretonne ValueType hierarchy"""
|
||||||
|
from __future__ import absolute_import
|
||||||
|
import math
|
||||||
|
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Map name -> ValueType.
|
||||||
|
_registry = dict() # type: Dict[str, ValueType]
|
||||||
|
|
||||||
|
# List of all the scalar types.
|
||||||
|
all_scalars = list() # type: List[ValueType]
|
||||||
|
|
||||||
|
def __init__(self, name, membytes, doc):
|
||||||
|
# type: (str, int, str) -> None
|
||||||
|
self.name = name
|
||||||
|
self.membytes = membytes
|
||||||
|
self.__doc__ = doc
|
||||||
|
assert name not in ValueType._registry
|
||||||
|
ValueType._registry[name] = self
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
# type: () -> str
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
def free_typevar(self):
|
||||||
|
return None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def by_name(name):
|
||||||
|
# type: (str) -> ValueType
|
||||||
|
if name in ValueType._registry:
|
||||||
|
return ValueType._registry[name]
|
||||||
|
else:
|
||||||
|
raise AttributeError("No type named '{}'".format(name))
|
||||||
|
|
||||||
|
|
||||||
|
class ScalarType(ValueType):
|
||||||
|
"""
|
||||||
|
A concrete scalar (not vector) type.
|
||||||
|
|
||||||
|
Also tracks a unique set of :py:class:`VectorType` instances with this type
|
||||||
|
as the lane type.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, name, membytes, doc):
|
||||||
|
# type: (str, int, str) -> None
|
||||||
|
super(ScalarType, self).__init__(name, membytes, doc)
|
||||||
|
self._vectors = dict() # type: Dict[int, VectorType]
|
||||||
|
# Assign numbers starting from 1. (0 is VOID).
|
||||||
|
ValueType.all_scalars.append(self)
|
||||||
|
self.number = len(ValueType.all_scalars)
|
||||||
|
assert self.number < 16, 'Too many scalar types'
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
# type: () -> str
|
||||||
|
return 'ScalarType({})'.format(self.name)
|
||||||
|
|
||||||
|
def rust_name(self):
|
||||||
|
# type: () -> str
|
||||||
|
return 'types::' + self.name.upper()
|
||||||
|
|
||||||
|
def by(self, lanes):
|
||||||
|
# type: (int) -> VectorType
|
||||||
|
"""
|
||||||
|
Get a vector type with this type as the lane type.
|
||||||
|
|
||||||
|
For example, ``i32.by(4)`` returns the :obj:`i32x4` type.
|
||||||
|
"""
|
||||||
|
if lanes in self._vectors:
|
||||||
|
return self._vectors[lanes]
|
||||||
|
else:
|
||||||
|
v = VectorType(self, lanes)
|
||||||
|
self._vectors[lanes] = v
|
||||||
|
return v
|
||||||
|
|
||||||
|
|
||||||
|
class VectorType(ValueType):
|
||||||
|
"""
|
||||||
|
A concrete SIMD vector type.
|
||||||
|
|
||||||
|
A vector type has a lane type which is an instance of :class:`ScalarType`,
|
||||||
|
and a positive number of lanes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, base, lanes):
|
||||||
|
# type: (ScalarType, int) -> None
|
||||||
|
assert isinstance(base, ScalarType), 'SIMD lanes must be scalar types'
|
||||||
|
super(VectorType, self).__init__(
|
||||||
|
name='{}x{}'.format(base.name, lanes),
|
||||||
|
membytes=lanes*base.membytes,
|
||||||
|
doc="""
|
||||||
|
A SIMD vector with {} lanes containing a `{}` each.
|
||||||
|
""".format(lanes, base.name))
|
||||||
|
self.base = base
|
||||||
|
self.lanes = lanes
|
||||||
|
self.number = 16*int(math.log(lanes, 2)) + base.number
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
# type: () -> str
|
||||||
|
return ('VectorType(base={}, lanes={})'
|
||||||
|
.format(self.base.name, self.lanes))
|
||||||
|
|
||||||
|
|
||||||
|
class IntType(ScalarType):
|
||||||
|
"""A concrete scalar integer type."""
|
||||||
|
|
||||||
|
def __init__(self, bits):
|
||||||
|
# type: (int) -> None
|
||||||
|
assert bits > 0, 'IntType must have positive number of bits'
|
||||||
|
super(IntType, self).__init__(
|
||||||
|
name='i{:d}'.format(bits),
|
||||||
|
membytes=bits // 8,
|
||||||
|
doc="An integer type with {} bits.".format(bits))
|
||||||
|
self.bits = bits
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
# type: () -> str
|
||||||
|
return 'IntType(bits={})'.format(self.bits)
|
||||||
|
|
||||||
|
|
||||||
|
class FloatType(ScalarType):
|
||||||
|
"""A concrete scalar floating point type."""
|
||||||
|
|
||||||
|
def __init__(self, bits, doc):
|
||||||
|
# type: (int, str) -> None
|
||||||
|
assert bits > 0, 'FloatType must have positive number of bits'
|
||||||
|
super(FloatType, self).__init__(
|
||||||
|
name='f{:d}'.format(bits),
|
||||||
|
membytes=bits // 8,
|
||||||
|
doc=doc)
|
||||||
|
self.bits = bits
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
# type: () -> str
|
||||||
|
return 'FloatType(bits={})'.format(self.bits)
|
||||||
|
|
||||||
|
|
||||||
|
class BoolType(ScalarType):
|
||||||
|
"""A concrete scalar boolean type."""
|
||||||
|
|
||||||
|
def __init__(self, bits):
|
||||||
|
# type: (int) -> None
|
||||||
|
assert bits > 0, 'BoolType must have positive number of bits'
|
||||||
|
super(BoolType, self).__init__(
|
||||||
|
name='b{:d}'.format(bits),
|
||||||
|
membytes=bits // 8,
|
||||||
|
doc="A boolean type with {} bits.".format(bits))
|
||||||
|
self.bits = bits
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
# type: () -> str
|
||||||
|
return 'BoolType(bits={})'.format(self.bits)
|
||||||
@@ -14,7 +14,7 @@ runif() {
|
|||||||
# Check Python sources for Python 3 compatibility using pylint.
|
# Check Python sources for Python 3 compatibility using pylint.
|
||||||
#
|
#
|
||||||
# Install pylint with 'pip install pylint'.
|
# Install pylint with 'pip install pylint'.
|
||||||
runif pylint --py3k --reports=no -- *.py cretonne isa
|
runif pylint --py3k --reports=no -- *.py cdsl base cretonne isa
|
||||||
|
|
||||||
# Style linting.
|
# Style linting.
|
||||||
runif flake8 .
|
runif flake8 .
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ instructions.
|
|||||||
"""
|
"""
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
import re
|
import re
|
||||||
import math
|
|
||||||
import importlib
|
import importlib
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from .predicates import And, Predicate, FieldPredicate # noqa
|
from .predicates import And, Predicate, FieldPredicate # noqa
|
||||||
|
import cdsl.types
|
||||||
|
|
||||||
# The typing module is only required by mypy, and we don't use these imports
|
# The typing module is only required by mypy, and we don't use these imports
|
||||||
# outside type comments.
|
# outside type comments.
|
||||||
@@ -17,7 +17,7 @@ try:
|
|||||||
from typing import Tuple, Union, Any, Iterable, Sequence, TYPE_CHECKING # noqa
|
from typing import Tuple, Union, Any, Iterable, Sequence, TYPE_CHECKING # noqa
|
||||||
MaybeBoundInst = Union['Instruction', 'BoundInstruction']
|
MaybeBoundInst = Union['Instruction', 'BoundInstruction']
|
||||||
AnyPredicate = Union['Predicate', 'FieldPredicate']
|
AnyPredicate = Union['Predicate', 'FieldPredicate']
|
||||||
OperandSpec = Union['OperandKind', 'ValueType', 'TypeVar']
|
OperandSpec = Union['OperandKind', 'cdsl.types.ValueType', 'TypeVar']
|
||||||
except ImportError:
|
except ImportError:
|
||||||
TYPE_CHECKING = False
|
TYPE_CHECKING = False
|
||||||
|
|
||||||
@@ -391,171 +391,6 @@ class EntityRefKind(OperandKind):
|
|||||||
return 'EntityRefKind({})'.format(self.name)
|
return 'EntityRefKind({})'.format(self.name)
|
||||||
|
|
||||||
|
|
||||||
# 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.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Map name -> ValueType.
|
|
||||||
_registry = dict() # type: Dict[str, ValueType]
|
|
||||||
|
|
||||||
# List of all the scalar types.
|
|
||||||
all_scalars = list() # type: List[ValueType]
|
|
||||||
|
|
||||||
def __init__(self, name, membytes, doc):
|
|
||||||
# type: (str, int, str) -> None
|
|
||||||
self.name = name
|
|
||||||
self.membytes = membytes
|
|
||||||
self.__doc__ = doc
|
|
||||||
assert name not in ValueType._registry
|
|
||||||
ValueType._registry[name] = self
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
# type: () -> str
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
def operand_kind(self):
|
|
||||||
# type: () -> OperandKind
|
|
||||||
"""
|
|
||||||
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
|
|
||||||
|
|
||||||
def free_typevar(self):
|
|
||||||
return None
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def by_name(name):
|
|
||||||
# type: (str) -> ValueType
|
|
||||||
if name in ValueType._registry:
|
|
||||||
return ValueType._registry[name]
|
|
||||||
else:
|
|
||||||
raise AttributeError("No type named '{}'".format(name))
|
|
||||||
|
|
||||||
|
|
||||||
class ScalarType(ValueType):
|
|
||||||
"""
|
|
||||||
A concrete scalar (not vector) type.
|
|
||||||
|
|
||||||
Also tracks a unique set of :py:class:`VectorType` instances with this type
|
|
||||||
as the lane type.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, name, membytes, doc):
|
|
||||||
# type: (str, int, str) -> None
|
|
||||||
super(ScalarType, self).__init__(name, membytes, doc)
|
|
||||||
self._vectors = dict() # type: Dict[int, VectorType]
|
|
||||||
# Assign numbers starting from 1. (0 is VOID).
|
|
||||||
ValueType.all_scalars.append(self)
|
|
||||||
self.number = len(ValueType.all_scalars)
|
|
||||||
assert self.number < 16, 'Too many scalar types'
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
# type: () -> str
|
|
||||||
return 'ScalarType({})'.format(self.name)
|
|
||||||
|
|
||||||
def rust_name(self):
|
|
||||||
# type: () -> str
|
|
||||||
return 'types::' + self.name.upper()
|
|
||||||
|
|
||||||
def by(self, lanes):
|
|
||||||
# type: (int) -> VectorType
|
|
||||||
"""
|
|
||||||
Get a vector type with this type as the lane type.
|
|
||||||
|
|
||||||
For example, ``i32.by(4)`` returns the :obj:`i32x4` type.
|
|
||||||
"""
|
|
||||||
if lanes in self._vectors:
|
|
||||||
return self._vectors[lanes]
|
|
||||||
else:
|
|
||||||
v = VectorType(self, lanes)
|
|
||||||
self._vectors[lanes] = v
|
|
||||||
return v
|
|
||||||
|
|
||||||
|
|
||||||
class VectorType(ValueType):
|
|
||||||
"""
|
|
||||||
A concrete SIMD vector type.
|
|
||||||
|
|
||||||
A vector type has a lane type which is an instance of :class:`ScalarType`,
|
|
||||||
and a positive number of lanes.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, base, lanes):
|
|
||||||
# type: (ScalarType, int) -> None
|
|
||||||
assert isinstance(base, ScalarType), 'SIMD lanes must be scalar types'
|
|
||||||
super(VectorType, self).__init__(
|
|
||||||
name='{}x{}'.format(base.name, lanes),
|
|
||||||
membytes=lanes*base.membytes,
|
|
||||||
doc="""
|
|
||||||
A SIMD vector with {} lanes containing a `{}` each.
|
|
||||||
""".format(lanes, base.name))
|
|
||||||
self.base = base
|
|
||||||
self.lanes = lanes
|
|
||||||
self.number = 16*int(math.log(lanes, 2)) + base.number
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
# type: () -> str
|
|
||||||
return ('VectorType(base={}, lanes={})'
|
|
||||||
.format(self.base.name, self.lanes))
|
|
||||||
|
|
||||||
|
|
||||||
class IntType(ScalarType):
|
|
||||||
"""A concrete scalar integer type."""
|
|
||||||
|
|
||||||
def __init__(self, bits):
|
|
||||||
# type: (int) -> None
|
|
||||||
assert bits > 0, 'IntType must have positive number of bits'
|
|
||||||
super(IntType, self).__init__(
|
|
||||||
name='i{:d}'.format(bits),
|
|
||||||
membytes=bits // 8,
|
|
||||||
doc="An integer type with {} bits.".format(bits))
|
|
||||||
self.bits = bits
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
# type: () -> str
|
|
||||||
return 'IntType(bits={})'.format(self.bits)
|
|
||||||
|
|
||||||
|
|
||||||
class FloatType(ScalarType):
|
|
||||||
"""A concrete scalar floating point type."""
|
|
||||||
|
|
||||||
def __init__(self, bits, doc):
|
|
||||||
# type: (int, str) -> None
|
|
||||||
assert bits > 0, 'FloatType must have positive number of bits'
|
|
||||||
super(FloatType, self).__init__(
|
|
||||||
name='f{:d}'.format(bits),
|
|
||||||
membytes=bits // 8,
|
|
||||||
doc=doc)
|
|
||||||
self.bits = bits
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
# type: () -> str
|
|
||||||
return 'FloatType(bits={})'.format(self.bits)
|
|
||||||
|
|
||||||
|
|
||||||
class BoolType(ScalarType):
|
|
||||||
"""A concrete scalar boolean type."""
|
|
||||||
|
|
||||||
def __init__(self, bits):
|
|
||||||
# type: (int) -> None
|
|
||||||
assert bits > 0, 'BoolType must have positive number of bits'
|
|
||||||
super(BoolType, self).__init__(
|
|
||||||
name='b{:d}'.format(bits),
|
|
||||||
membytes=bits // 8,
|
|
||||||
doc="A boolean type with {} bits.".format(bits))
|
|
||||||
self.bits = bits
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
# type: () -> str
|
|
||||||
return 'BoolType(bits={})'.format(self.bits)
|
|
||||||
|
|
||||||
|
|
||||||
# Defining instructions.
|
# Defining instructions.
|
||||||
|
|
||||||
|
|
||||||
@@ -633,8 +468,11 @@ class Operand(object):
|
|||||||
def __init__(self, name, typ, doc=''):
|
def __init__(self, name, typ, doc=''):
|
||||||
# type: (str, OperandSpec, str) -> None
|
# type: (str, OperandSpec, str) -> None
|
||||||
self.name = name
|
self.name = name
|
||||||
self.typ = typ
|
|
||||||
self.__doc__ = doc
|
self.__doc__ = doc
|
||||||
|
self.typ = typ
|
||||||
|
if isinstance(typ, cdsl.types.ValueType):
|
||||||
|
self.kind = value
|
||||||
|
else:
|
||||||
self.kind = typ.operand_kind()
|
self.kind = typ.operand_kind()
|
||||||
|
|
||||||
def get_doc(self):
|
def get_doc(self):
|
||||||
@@ -688,7 +526,7 @@ class InstructionFormat(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# Map (multiple_results, kind, kind, ...) -> InstructionFormat
|
# Map (multiple_results, kind, kind, ...) -> InstructionFormat
|
||||||
_registry = dict() # type: Dict[Tuple, InstructionFormat]
|
_registry = dict() # type: Dict[Tuple[bool, Tuple[OperandKind, ...]], InstructionFormat] # noqa
|
||||||
|
|
||||||
# All existing formats.
|
# All existing formats.
|
||||||
all_formats = list() # type: List[InstructionFormat]
|
all_formats = list() # type: List[InstructionFormat]
|
||||||
@@ -715,7 +553,7 @@ class InstructionFormat(object):
|
|||||||
self.typevar_operand = self.value_operands[0]
|
self.typevar_operand = self.value_operands[0]
|
||||||
|
|
||||||
# Compute a signature for the global registry.
|
# Compute a signature for the global registry.
|
||||||
sig = (self.multiple_results,) + self.kinds
|
sig = (self.multiple_results, self.kinds)
|
||||||
if sig in InstructionFormat._registry:
|
if sig in InstructionFormat._registry:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"Format '{}' has the same signature as existing format '{}'"
|
"Format '{}' has the same signature as existing format '{}'"
|
||||||
@@ -782,11 +620,11 @@ class InstructionFormat(object):
|
|||||||
multiple_results = outs[0].kind == variable_args
|
multiple_results = outs[0].kind == variable_args
|
||||||
else:
|
else:
|
||||||
multiple_results = len(outs) > 1
|
multiple_results = len(outs) > 1
|
||||||
sig = (multiple_results,) + tuple(op.kind for op in ins)
|
sig = (multiple_results, tuple(op.kind for op in ins))
|
||||||
if sig not in InstructionFormat._registry:
|
if sig not in InstructionFormat._registry:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"No instruction format matches ins = ({}){}".format(
|
"No instruction format matches ins = ({}){}".format(
|
||||||
", ".join(map(str, sig[1:])),
|
", ".join(map(str, sig[1])),
|
||||||
"[multiple results]" if multiple_results else ""))
|
"[multiple results]" if multiple_results else ""))
|
||||||
return InstructionFormat._registry[sig]
|
return InstructionFormat._registry[sig]
|
||||||
|
|
||||||
@@ -991,7 +829,7 @@ class Instruction(object):
|
|||||||
return x
|
return x
|
||||||
|
|
||||||
def bind(self, *args):
|
def bind(self, *args):
|
||||||
# type: (*ValueType) -> BoundInstruction
|
# type: (*cdsl.types.ValueType) -> BoundInstruction
|
||||||
"""
|
"""
|
||||||
Bind a polymorphic instruction to a concrete list of type variable
|
Bind a polymorphic instruction to a concrete list of type variable
|
||||||
values.
|
values.
|
||||||
@@ -1007,10 +845,10 @@ class Instruction(object):
|
|||||||
|
|
||||||
>>> iadd.i32
|
>>> iadd.i32
|
||||||
"""
|
"""
|
||||||
return self.bind(ValueType.by_name(name))
|
return self.bind(cdsl.types.ValueType.by_name(name))
|
||||||
|
|
||||||
def fully_bound(self):
|
def fully_bound(self):
|
||||||
# type: () -> Tuple[Instruction, Tuple[ValueType, ...]]
|
# type: () -> Tuple[Instruction, Tuple[cdsl.types.ValueType, ...]]
|
||||||
"""
|
"""
|
||||||
Verify that all typevars have been bound, and return a
|
Verify that all typevars have been bound, and return a
|
||||||
`(inst, typevars)` pair.
|
`(inst, typevars)` pair.
|
||||||
@@ -1036,7 +874,7 @@ class BoundInstruction(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, inst, typevars):
|
def __init__(self, inst, typevars):
|
||||||
# type: (Instruction, Tuple[ValueType, ...]) -> None
|
# type: (Instruction, Tuple[cdsl.types.ValueType, ...]) -> None
|
||||||
self.inst = inst
|
self.inst = inst
|
||||||
self.typevars = typevars
|
self.typevars = typevars
|
||||||
assert len(typevars) <= 1 + len(inst.other_typevars)
|
assert len(typevars) <= 1 + len(inst.other_typevars)
|
||||||
@@ -1045,7 +883,7 @@ class BoundInstruction(object):
|
|||||||
return '.'.join([self.inst.name, ] + list(map(str, self.typevars)))
|
return '.'.join([self.inst.name, ] + list(map(str, self.typevars)))
|
||||||
|
|
||||||
def bind(self, *args):
|
def bind(self, *args):
|
||||||
# type: (*ValueType) -> BoundInstruction
|
# type: (*cdsl.types.ValueType) -> BoundInstruction
|
||||||
"""
|
"""
|
||||||
Bind additional typevars.
|
Bind additional typevars.
|
||||||
"""
|
"""
|
||||||
@@ -1058,10 +896,10 @@ class BoundInstruction(object):
|
|||||||
|
|
||||||
>>> uext.i32.i8
|
>>> uext.i32.i8
|
||||||
"""
|
"""
|
||||||
return self.bind(ValueType.by_name(name))
|
return self.bind(cdsl.types.ValueType.by_name(name))
|
||||||
|
|
||||||
def fully_bound(self):
|
def fully_bound(self):
|
||||||
# type: () -> Tuple[Instruction, Tuple[ValueType, ...]]
|
# type: () -> Tuple[Instruction, Tuple[cdsl.types.ValueType, ...]]
|
||||||
"""
|
"""
|
||||||
Verify that all typevars have been bound, and return a
|
Verify that all typevars have been bound, and return a
|
||||||
`(inst, typevars)` pair.
|
`(inst, typevars)` pair.
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ support.
|
|||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
from . import Operand, Instruction, InstructionGroup, variable_args
|
from . import Operand, Instruction, InstructionGroup, variable_args
|
||||||
from .typevar import TypeVar
|
from .typevar import TypeVar
|
||||||
from .types import i8, f32, f64, b1
|
from base.types import i8, f32, f64, b1
|
||||||
from .immediates import imm64, uimm8, ieee32, ieee64, immvector, intcc, floatcc
|
from .immediates import imm64, uimm8, ieee32, ieee64, immvector, intcc, floatcc
|
||||||
from . import entities
|
from . import entities
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ from __future__ import absolute_import
|
|||||||
import srcgen
|
import srcgen
|
||||||
import constant_hash
|
import constant_hash
|
||||||
from unique_table import UniqueTable, UniqueSeqTable
|
from unique_table import UniqueTable, UniqueSeqTable
|
||||||
|
import cdsl.types
|
||||||
import cretonne
|
import cretonne
|
||||||
|
|
||||||
|
|
||||||
@@ -310,11 +311,11 @@ def get_constraint(op, ctrl_typevar, type_sets):
|
|||||||
- `Free(idx)` where `idx` is an index into `type_sets`.
|
- `Free(idx)` where `idx` is an index into `type_sets`.
|
||||||
- `Same`, `Lane`, `AsBool` for controlling typevar-derived constraints.
|
- `Same`, `Lane`, `AsBool` for controlling typevar-derived constraints.
|
||||||
"""
|
"""
|
||||||
|
assert op.kind is cretonne.value
|
||||||
t = op.typ
|
t = op.typ
|
||||||
assert t.operand_kind() is cretonne.value
|
|
||||||
|
|
||||||
# A concrete value type.
|
# A concrete value type.
|
||||||
if isinstance(t, cretonne.ValueType):
|
if isinstance(t, cdsl.types.ValueType):
|
||||||
return 'Concrete({})'.format(t.rust_name())
|
return 'Concrete({})'.format(t.rust_name())
|
||||||
|
|
||||||
if t.free_typevar() is not ctrl_typevar:
|
if t.free_typevar() is not ctrl_typevar:
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ This ensures that Python and Rust use the same type numbering.
|
|||||||
"""
|
"""
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
import srcgen
|
import srcgen
|
||||||
from cretonne import ValueType
|
from cdsl.types import ValueType
|
||||||
|
import base.types # noqa
|
||||||
|
|
||||||
|
|
||||||
def emit_type(ty, fmt):
|
def emit_type(ty, fmt):
|
||||||
|
|||||||
Reference in New Issue
Block a user