diff --git a/docs/cton_domain.py b/docs/cton_domain.py index 00242ff565..47c7c2996c 100644 --- a/docs/cton_domain.py +++ b/docs/cton_domain.py @@ -269,7 +269,7 @@ class InstDocumenter(sphinx.ext.autodoc.Documenter): return False def resolve_name(self, modname, parents, path, base): - return 'cretonne.base', [base] + return 'base.instructions', [base] def format_signature(self): inst = self.object diff --git a/docs/langref.rst b/docs/langref.rst index 5dcf80a893..a9d5ac4c96 100644 --- a/docs/langref.rst +++ b/docs/langref.rst @@ -849,7 +849,7 @@ Base instruction group All of the shared instructions are part of the :instgroup:`base` instruction group. -.. autoinstgroup:: cretonne.base.instructions +.. autoinstgroup:: base.instructions.GROUP Target ISAs may define further instructions in their own instruction groups. diff --git a/docs/metaref.rst b/docs/metaref.rst index 31e4ffc9b5..190945c61d 100644 --- a/docs/metaref.rst +++ b/docs/metaref.rst @@ -71,7 +71,7 @@ a module looks like this:: Instruction descriptions ======================== -.. currentmodule:: cretonne +.. module:: cdsl.instructions New instructions are defined as instances of the :class:`Instruction` class. As instruction instances are created, they are added to the currently @@ -81,12 +81,14 @@ open :class:`InstructionGroup`. :members: The basic Cretonne instruction set described in :doc:`langref` is defined by the -Python module :mod:`cretonne.base`. This module has a global variable -:data:`cretonne.base.instructions` which is an :class:`InstructionGroup` -instance containing all the base instructions. +Python module :mod:`base.instructions`. This module has a global variable +:data:`base.instructions.GROUP` which is an :class:`InstructionGroup` instance +containing all the base instructions. .. autoclass:: Instruction +.. currentmodule:: cdsl.operands + An instruction is defined with a set of distinct input and output operands which must be instances of the :class:`Operand` class. @@ -201,7 +203,7 @@ represent SSA values: .. autodata:: VALUE .. autodata:: VARIABLE_ARGS -.. currentmodule:: cretonne +.. module:: cdsl.formats When an instruction description is created, it is automatically assigned a predefined instruction format which is an instance of @@ -253,6 +255,8 @@ controlling type variable, or it can vary independently of the other operands. Encodings ========= +.. currentmodule:: cretonne + Encodings describe how Cretonne instructions are mapped to binary machine code for the target architecture. After the legalization pass, all remaining instructions are expected to map 1-1 to native instruction encodings. Cretonne diff --git a/lib/cretonne/meta/cretonne/base.py b/lib/cretonne/meta/base/instructions.py similarity index 99% rename from lib/cretonne/meta/cretonne/base.py rename to lib/cretonne/meta/base/instructions.py index ce747cc203..b5a2c784fa 100644 --- a/lib/cretonne/meta/cretonne/base.py +++ b/lib/cretonne/meta/base/instructions.py @@ -5,16 +5,16 @@ This module defines the basic Cretonne instruction set that all targets support. """ from __future__ import absolute_import -from cdsl.operands import VARIABLE_ARGS +from cdsl.operands import Operand, VARIABLE_ARGS from cdsl.typevar import TypeVar -from . import Operand, Instruction, InstructionGroup +from cdsl.instructions import Instruction, InstructionGroup from base.types import i8, f32, f64, b1 from base.immediates import imm64, uimm8, ieee32, ieee64, immvector from base.immediates import intcc, floatcc from base import entities import base.formats # noqa -instructions = InstructionGroup("base", "Shared base instruction set") +GROUP = InstructionGroup("base", "Shared base instruction set") Int = TypeVar('Int', 'A scalar or vector integer type', ints=True, simd=True) iB = TypeVar('iB', 'A scalar integer type', ints=True) @@ -1213,4 +1213,4 @@ iconcat_lohi = Instruction( """, ins=(lo, hi), outs=a) -instructions.close() +GROUP.close() diff --git a/lib/cretonne/meta/cdsl/instructions.py b/lib/cretonne/meta/cdsl/instructions.py new file mode 100644 index 0000000000..da9f5bb179 --- /dev/null +++ b/lib/cretonne/meta/cdsl/instructions.py @@ -0,0 +1,316 @@ +"""Classes for defining instructions.""" +from __future__ import absolute_import +from . import camel_case +from .types import ValueType +from .operands import Operand +from .formats import InstructionFormat + +try: + from typing import Union, Sequence + # List of operands for ins/outs: + OpList = Union[Sequence[Operand], Operand] + MaybeBoundInst = Union['Instruction', 'BoundInstruction'] + from typing import Tuple, Any # noqa +except ImportError: + pass + + +class InstructionGroup(object): + """ + Every instruction must belong to exactly one instruction group. A given + target architecture can support instructions from multiple groups, and it + does not necessarily support all instructions in a group. + + New instructions are automatically added to the currently open instruction + group. + """ + + # The currently open instruction group. + _current = None # type: InstructionGroup + + def open(self): + # type: () -> None + """ + Open this instruction group such that future new instructions are + added to this group. + """ + assert InstructionGroup._current is None, ( + "Can't open {} since {} is already open" + .format(self, InstructionGroup._current)) + InstructionGroup._current = self + + def close(self): + # type: () -> None + """ + Close this instruction group. This function should be called before + opening another instruction group. + """ + assert InstructionGroup._current is self, ( + "Can't close {}, the open instuction group is {}" + .format(self, InstructionGroup._current)) + InstructionGroup._current = None + + def __init__(self, name, doc): + # type: (str, str) -> None + self.name = name + self.__doc__ = doc + self.instructions = [] # type: List[Instruction] + self.open() + + @staticmethod + def append(inst): + # type: (Instruction) -> None + assert InstructionGroup._current, \ + "Open an instruction group before defining instructions." + InstructionGroup._current.instructions.append(inst) + + +class Instruction(object): + """ + 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 + allowed to specify a singleton as just the operand itself, i.e., `ins=x` + and `ins=(x,)` are both allowed and mean the same thing. + + :param name: Instruction mnemonic, also becomes opcode name. + :param doc: Documentation string. + :param ins: Tuple of input operands. This can be a mix of SSA value + operands and other operand kinds. + :param outs: Tuple of output operands. The output operands must be SSA + values or `variable_args`. + :param is_terminator: This is a terminator instruction. + :param is_branch: This is a branch instruction. + """ + + def __init__(self, name, doc, ins=(), outs=(), **kwargs): + # type: (str, str, OpList, OpList, **Any) -> None # noqa + self.name = name + self.camel_name = camel_case(name) + self.__doc__ = doc + self.ins = self._to_operand_tuple(ins) + self.outs = self._to_operand_tuple(outs) + self.format = InstructionFormat.lookup(self.ins, self.outs) + # Indexes into outs for value results. Others are `variable_args`. + self.value_results = tuple( + i for i, o in enumerate(self.outs) if o.is_value()) + self._verify_polymorphic() + InstructionGroup.append(self) + + def __str__(self): + prefix = ', '.join(o.name for o in self.outs) + if prefix: + prefix = prefix + ' = ' + suffix = ', '.join(o.name for o in self.ins) + return '{}{} {}'.format(prefix, self.name, suffix) + + def snake_name(self): + # type: () -> str + """ + Get the snake_case name of this instruction. + + Keywords in Rust and Python are altered by appending a '_' + """ + if self.name == 'return': + return 'return_' + else: + return self.name + + def blurb(self): + """Get the first line of the doc comment""" + for line in self.__doc__.split('\n'): + line = line.strip() + if line: + return line + return "" + + def _verify_polymorphic(self): + """ + Check if this instruction is polymorphic, and verify its use of type + variables. + """ + poly_ins = [ + i for i in self.format.value_operands + if self.ins[i].typ.free_typevar()] + poly_outs = [ + i for i, o in enumerate(self.outs) + if o.typ.free_typevar()] + self.is_polymorphic = len(poly_ins) > 0 or len(poly_outs) > 0 + if not self.is_polymorphic: + return + + # Prefer to use the typevar_operand to infer the controlling typevar. + self.use_typevar_operand = False + typevar_error = None + if self.format.typevar_operand is not None: + try: + tv = self.ins[self.format.typevar_operand].typ + if tv is tv.free_typevar(): + self.other_typevars = self._verify_ctrl_typevar(tv) + self.ctrl_typevar = tv + self.use_typevar_operand = True + except RuntimeError as e: + typevar_error = e + + if not self.use_typevar_operand: + # The typevar_operand argument doesn't work. Can we infer from the + # first result instead? + if len(self.outs) == 0: + if typevar_error: + raise typevar_error + else: + raise RuntimeError( + "typevar_operand must be a free type variable") + tv = self.outs[0].typ + if tv is not tv.free_typevar(): + raise RuntimeError("first result must be a free type variable") + self.other_typevars = self._verify_ctrl_typevar(tv) + self.ctrl_typevar = tv + + def _verify_ctrl_typevar(self, ctrl_typevar): + """ + Verify that the use of TypeVars is consistent with `ctrl_typevar` as + the controlling type variable. + + All polymorhic inputs must either be derived from `ctrl_typevar` or be + independent free type variables only used once. + + All polymorphic results must be derived from `ctrl_typevar`. + + Return list of other type variables used, or raise an error. + """ + other_tvs = [] + # Check value inputs. + for opidx in self.format.value_operands: + typ = self.ins[opidx].typ + tv = typ.free_typevar() + # Non-polymorphic or derived form ctrl_typevar is OK. + if tv is None or tv is ctrl_typevar: + continue + # No other derived typevars allowed. + if typ is not tv: + raise RuntimeError( + "{}: type variable {} must be derived from {}" + .format(self.ins[opidx], typ.name, ctrl_typevar)) + # Other free type variables can only be used once each. + if tv in other_tvs: + raise RuntimeError( + "type variable {} can't be used more than once" + .format(tv.name)) + other_tvs.append(tv) + + # Check outputs. + for result in self.outs: + typ = result.typ + tv = typ.free_typevar() + # Non-polymorphic or derived from ctrl_typevar is OK. + if tv is None or tv is ctrl_typevar: + continue + raise RuntimeError( + "type variable in output not derived from ctrl_typevar") + + return other_tvs + + @staticmethod + def _to_operand_tuple(x): + # type: (Union[Sequence[Operand], Operand]) -> Tuple[Operand, ...] + # Allow a single Operand instance instead of the awkward singleton + # tuple syntax. + if isinstance(x, Operand): + x = (x,) + else: + x = tuple(x) + for op in x: + assert isinstance(op, Operand) + return x + + def bind(self, *args): + # type: (*ValueType) -> BoundInstruction + """ + Bind a polymorphic instruction to a concrete list of type variable + values. + """ + assert self.is_polymorphic + return BoundInstruction(self, args) + + def __getattr__(self, name): + # type: (str) -> BoundInstruction + """ + Bind a polymorphic instruction to a single type variable with dot + syntax: + + >>> iadd.i32 + """ + return self.bind(ValueType.by_name(name)) + + def fully_bound(self): + # type: () -> Tuple[Instruction, Tuple[ValueType, ...]] + """ + Verify that all typevars have been bound, and return a + `(inst, typevars)` pair. + + This version in `Instruction` itself allows non-polymorphic + instructions to duck-type as `BoundInstruction`\s. + """ + assert not self.is_polymorphic, self + return (self, ()) + + def __call__(self, *args): + """ + Create an `ast.Apply` AST node representing the application of this + instruction to the arguments. + """ + from cretonne.ast import Apply + return Apply(self, args) + + +class BoundInstruction(object): + """ + A polymorphic `Instruction` bound to concrete type variables. + """ + + def __init__(self, inst, typevars): + # type: (Instruction, Tuple[ValueType, ...]) -> None + self.inst = inst + self.typevars = typevars + assert len(typevars) <= 1 + len(inst.other_typevars) + + def __str__(self): + return '.'.join([self.inst.name, ] + list(map(str, self.typevars))) + + def bind(self, *args): + # type: (*ValueType) -> BoundInstruction + """ + Bind additional typevars. + """ + return BoundInstruction(self.inst, self.typevars + args) + + def __getattr__(self, name): + # type: (str) -> BoundInstruction + """ + Bind an additional typevar dot syntax: + + >>> uext.i32.i8 + """ + return self.bind(ValueType.by_name(name)) + + def fully_bound(self): + # type: () -> Tuple[Instruction, Tuple[ValueType, ...]] + """ + Verify that all typevars have been bound, and return a + `(inst, typevars)` pair. + """ + if len(self.typevars) < 1 + len(self.inst.other_typevars): + unb = ', '.join( + str(tv) for tv in + self.inst.other_typevars[len(self.typevars) - 1:]) + raise AssertionError("Unbound typevar {} in {}".format(unb, self)) + assert len(self.typevars) == 1 + len(self.inst.other_typevars) + return (self.inst, self.typevars) + + def __call__(self, *args): + """ + Create an `ast.Apply` AST node representing the application of this + instruction to the arguments. + """ + from cretonne.ast import Apply + return Apply(self, args) diff --git a/lib/cretonne/meta/cretonne/__init__.py b/lib/cretonne/meta/cretonne/__init__.py index 0ab55491c9..fa1da4d302 100644 --- a/lib/cretonne/meta/cretonne/__init__.py +++ b/lib/cretonne/meta/cretonne/__init__.py @@ -6,19 +6,15 @@ instructions. """ from __future__ import absolute_import import importlib -from cdsl import camel_case from cdsl.predicates import And -from cdsl.types import ValueType from cdsl.typevar import TypeVar -from cdsl.operands import Operand -from cdsl.formats import InstructionFormat # The typing module is only required by mypy, and we don't use these imports # outside type comments. try: from typing import Tuple, Union, Any, Iterable, Sequence, TYPE_CHECKING # noqa from cdsl.predicates import Predicate, FieldPredicate # noqa - MaybeBoundInst = Union['Instruction', 'BoundInstruction'] + from cdsl.instructions import MaybeBoundInst # noqa AnyPredicate = Union['Predicate', 'FieldPredicate'] except ImportError: TYPE_CHECKING = False @@ -27,310 +23,6 @@ if TYPE_CHECKING: from cdsl.typevar import TypeVar # noqa -# Defining instructions. - - -class InstructionGroup(object): - """ - Every instruction must belong to exactly one instruction group. A given - target architecture can support instructions from multiple groups, and it - does not necessarily support all instructions in a group. - - New instructions are automatically added to the currently open instruction - group. - """ - - # The currently open instruction group. - _current = None # type: InstructionGroup - - def open(self): - # type: () -> None - """ - Open this instruction group such that future new instructions are - added to this group. - """ - assert InstructionGroup._current is None, ( - "Can't open {} since {} is already open" - .format(self, InstructionGroup._current)) - InstructionGroup._current = self - - def close(self): - # type: () -> None - """ - Close this instruction group. This function should be called before - opening another instruction group. - """ - assert InstructionGroup._current is self, ( - "Can't close {}, the open instuction group is {}" - .format(self, InstructionGroup._current)) - InstructionGroup._current = None - - def __init__(self, name, doc): - # type: (str, str) -> None - self.name = name - self.__doc__ = doc - self.instructions = [] # type: List[Instruction] - self.open() - - @staticmethod - def append(inst): - # type: (Instruction) -> None - assert InstructionGroup._current, \ - "Open an instruction group before defining instructions." - InstructionGroup._current.instructions.append(inst) - - -class Instruction(object): - """ - 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 - allowed to specify a singleton as just the operand itself, i.e., `ins=x` - and `ins=(x,)` are both allowed and mean the same thing. - - :param name: Instruction mnemonic, also becomes opcode name. - :param doc: Documentation string. - :param ins: Tuple of input operands. This can be a mix of SSA value - operands and other operand kinds. - :param outs: Tuple of output operands. The output operands must be SSA - values or `variable_args`. - :param is_terminator: This is a terminator instruction. - :param is_branch: This is a branch instruction. - """ - - def __init__(self, name, doc, ins=(), outs=(), **kwargs): - # type: (str, str, Union[Sequence[Operand], Operand], Union[Sequence[Operand], Operand], **Any) -> None # noqa - self.name = name - self.camel_name = camel_case(name) - self.__doc__ = doc - self.ins = self._to_operand_tuple(ins) - self.outs = self._to_operand_tuple(outs) - self.format = InstructionFormat.lookup(self.ins, self.outs) - # Indexes into outs for value results. Others are `variable_args`. - self.value_results = tuple( - i for i, o in enumerate(self.outs) if o.is_value()) - self._verify_polymorphic() - InstructionGroup.append(self) - - def __str__(self): - prefix = ', '.join(o.name for o in self.outs) - if prefix: - prefix = prefix + ' = ' - suffix = ', '.join(o.name for o in self.ins) - return '{}{} {}'.format(prefix, self.name, suffix) - - def snake_name(self): - # type: () -> str - """ - Get the snake_case name of this instruction. - - Keywords in Rust and Python are altered by appending a '_' - """ - if self.name == 'return': - return 'return_' - else: - return self.name - - def blurb(self): - """Get the first line of the doc comment""" - for line in self.__doc__.split('\n'): - line = line.strip() - if line: - return line - return "" - - def _verify_polymorphic(self): - """ - Check if this instruction is polymorphic, and verify its use of type - variables. - """ - poly_ins = [ - i for i in self.format.value_operands - if self.ins[i].typ.free_typevar()] - poly_outs = [ - i for i, o in enumerate(self.outs) - if o.typ.free_typevar()] - self.is_polymorphic = len(poly_ins) > 0 or len(poly_outs) > 0 - if not self.is_polymorphic: - return - - # Prefer to use the typevar_operand to infer the controlling typevar. - self.use_typevar_operand = False - typevar_error = None - if self.format.typevar_operand is not None: - try: - tv = self.ins[self.format.typevar_operand].typ - if tv is tv.free_typevar(): - self.other_typevars = self._verify_ctrl_typevar(tv) - self.ctrl_typevar = tv - self.use_typevar_operand = True - except RuntimeError as e: - typevar_error = e - - if not self.use_typevar_operand: - # The typevar_operand argument doesn't work. Can we infer from the - # first result instead? - if len(self.outs) == 0: - if typevar_error: - raise typevar_error - else: - raise RuntimeError( - "typevar_operand must be a free type variable") - tv = self.outs[0].typ - if tv is not tv.free_typevar(): - raise RuntimeError("first result must be a free type variable") - self.other_typevars = self._verify_ctrl_typevar(tv) - self.ctrl_typevar = tv - - def _verify_ctrl_typevar(self, ctrl_typevar): - """ - Verify that the use of TypeVars is consistent with `ctrl_typevar` as - the controlling type variable. - - All polymorhic inputs must either be derived from `ctrl_typevar` or be - independent free type variables only used once. - - All polymorphic results must be derived from `ctrl_typevar`. - - Return list of other type variables used, or raise an error. - """ - other_tvs = [] - # Check value inputs. - for opidx in self.format.value_operands: - typ = self.ins[opidx].typ - tv = typ.free_typevar() - # Non-polymorphic or derived form ctrl_typevar is OK. - if tv is None or tv is ctrl_typevar: - continue - # No other derived typevars allowed. - if typ is not tv: - raise RuntimeError( - "{}: type variable {} must be derived from {}" - .format(self.ins[opidx], typ.name, ctrl_typevar)) - # Other free type variables can only be used once each. - if tv in other_tvs: - raise RuntimeError( - "type variable {} can't be used more than once" - .format(tv.name)) - other_tvs.append(tv) - - # Check outputs. - for result in self.outs: - typ = result.typ - tv = typ.free_typevar() - # Non-polymorphic or derived from ctrl_typevar is OK. - if tv is None or tv is ctrl_typevar: - continue - raise RuntimeError( - "type variable in output not derived from ctrl_typevar") - - return other_tvs - - @staticmethod - def _to_operand_tuple(x): - # type: (Union[Sequence[Operand], Operand]) -> Tuple[Operand, ...] - # Allow a single Operand instance instead of the awkward singleton - # tuple syntax. - if isinstance(x, Operand): - x = (x,) - else: - x = tuple(x) - for op in x: - assert isinstance(op, Operand) - return x - - def bind(self, *args): - # type: (*ValueType) -> BoundInstruction - """ - Bind a polymorphic instruction to a concrete list of type variable - values. - """ - assert self.is_polymorphic - return BoundInstruction(self, args) - - def __getattr__(self, name): - # type: (str) -> BoundInstruction - """ - Bind a polymorphic instruction to a single type variable with dot - syntax: - - >>> iadd.i32 - """ - return self.bind(ValueType.by_name(name)) - - def fully_bound(self): - # type: () -> Tuple[Instruction, Tuple[ValueType, ...]] - """ - Verify that all typevars have been bound, and return a - `(inst, typevars)` pair. - - This version in `Instruction` itself allows non-polymorphic - instructions to duck-type as `BoundInstruction`\s. - """ - assert not self.is_polymorphic, self - return (self, ()) - - def __call__(self, *args): - """ - Create an `ast.Apply` AST node representing the application of this - instruction to the arguments. - """ - from .ast import Apply - return Apply(self, args) - - -class BoundInstruction(object): - """ - A polymorphic `Instruction` bound to concrete type variables. - """ - - def __init__(self, inst, typevars): - # type: (Instruction, Tuple[ValueType, ...]) -> None - self.inst = inst - self.typevars = typevars - assert len(typevars) <= 1 + len(inst.other_typevars) - - def __str__(self): - return '.'.join([self.inst.name, ] + list(map(str, self.typevars))) - - def bind(self, *args): - # type: (*ValueType) -> BoundInstruction - """ - Bind additional typevars. - """ - return BoundInstruction(self.inst, self.typevars + args) - - def __getattr__(self, name): - # type: (str) -> BoundInstruction - """ - Bind an additional typevar dot syntax: - - >>> uext.i32.i8 - """ - return self.bind(ValueType.by_name(name)) - - def fully_bound(self): - # type: () -> Tuple[Instruction, Tuple[ValueType, ...]] - """ - Verify that all typevars have been bound, and return a - `(inst, typevars)` pair. - """ - if len(self.typevars) < 1 + len(self.inst.other_typevars): - unb = ', '.join( - str(tv) for tv in - self.inst.other_typevars[len(self.typevars) - 1:]) - raise AssertionError("Unbound typevar {} in {}".format(unb, self)) - assert len(self.typevars) == 1 + len(self.inst.other_typevars) - return (self.inst, self.typevars) - - def __call__(self, *args): - """ - Create an `ast.Apply` AST node representing the application of this - instruction to the arguments. - """ - from .ast import Apply - return Apply(self, args) - - # Defining target ISAs. diff --git a/lib/cretonne/meta/cretonne/ast.py b/lib/cretonne/meta/cretonne/ast.py index b437148435..0212de7a0b 100644 --- a/lib/cretonne/meta/cretonne/ast.py +++ b/lib/cretonne/meta/cretonne/ast.py @@ -5,7 +5,7 @@ This module defines classes that can be used to create abstract syntax trees for patern matching an rewriting of cretonne instructions. """ from __future__ import absolute_import -import cretonne +from cdsl import instructions try: from typing import Union, Tuple # noqa @@ -20,7 +20,7 @@ class Def(object): Example: - >>> from .base import iadd_cout, iconst + >>> from base.instructions import iadd_cout, iconst >>> x = Var('x') >>> y = Var('y') >>> x << iconst(4) @@ -162,7 +162,7 @@ class Apply(Expr): instructions. This applies to both bound and unbound polymorphic instructions: - >>> from .base import jump, iadd + >>> from base.instructions import jump, iadd >>> jump('next', ()) Apply(jump, ('next', ())) >>> iadd.i32('x', 'y') @@ -174,12 +174,12 @@ class Apply(Expr): """ def __init__(self, inst, args): - # type: (Union[cretonne.Instruction, cretonne.BoundInstruction], Tuple[Expr, ...]) -> None # noqa - if isinstance(inst, cretonne.BoundInstruction): + # type: (instructions.MaybeBoundInst, Tuple[Expr, ...]) -> None # noqa + if isinstance(inst, instructions.BoundInstruction): self.inst = inst.inst self.typevars = inst.typevars else: - assert isinstance(inst, cretonne.Instruction) + assert isinstance(inst, instructions.Instruction) self.inst = inst self.typevars = () self.args = args diff --git a/lib/cretonne/meta/cretonne/legalize.py b/lib/cretonne/meta/cretonne/legalize.py index 189685dce1..dd534cf108 100644 --- a/lib/cretonne/meta/cretonne/legalize.py +++ b/lib/cretonne/meta/cretonne/legalize.py @@ -7,10 +7,10 @@ patterns that describe how base instructions can be transformed to other base instructions that are legal. """ from __future__ import absolute_import -from .base import iadd, iadd_cout, iadd_cin, iadd_carry -from .base import isub, isub_bin, isub_bout, isub_borrow -from .base import band, bor, bxor, isplit_lohi, iconcat_lohi -from .base import icmp +from base.instructions import iadd, iadd_cout, iadd_cin, iadd_carry +from base.instructions import isub, isub_bin, isub_bout, isub_borrow +from base.instructions import band, bor, bxor, isplit_lohi, iconcat_lohi +from base.instructions import icmp from .ast import Var from .xform import Rtl, XFormGroup diff --git a/lib/cretonne/meta/cretonne/test_ast.py b/lib/cretonne/meta/cretonne/test_ast.py index 71791db3f6..750142af0a 100644 --- a/lib/cretonne/meta/cretonne/test_ast.py +++ b/lib/cretonne/meta/cretonne/test_ast.py @@ -2,7 +2,7 @@ from __future__ import absolute_import from unittest import TestCase from doctest import DocTestSuite from . import ast -from .base import jump, iadd +from base.instructions import jump, iadd def load_tests(loader, tests, ignore): diff --git a/lib/cretonne/meta/cretonne/test_xform.py b/lib/cretonne/meta/cretonne/test_xform.py index b472a8f458..1609bb6c5f 100644 --- a/lib/cretonne/meta/cretonne/test_xform.py +++ b/lib/cretonne/meta/cretonne/test_xform.py @@ -1,8 +1,8 @@ from __future__ import absolute_import from unittest import TestCase from doctest import DocTestSuite +from base.instructions import iadd, iadd_imm, iconst from . import xform -from .base import iadd, iadd_imm, iconst from .ast import Var from .xform import Rtl, XForm diff --git a/lib/cretonne/meta/cretonne/xform.py b/lib/cretonne/meta/cretonne/xform.py index 6b9b37f513..f8f66de85c 100644 --- a/lib/cretonne/meta/cretonne/xform.py +++ b/lib/cretonne/meta/cretonne/xform.py @@ -54,7 +54,7 @@ class XForm(object): A legalization pattern must have a source pattern containing only a single instruction. - >>> from .base import iconst, iadd, iadd_imm + >>> from base.instructions import iconst, iadd, iadd_imm >>> a = Var('a') >>> c = Var('c') >>> v = Var('v') diff --git a/lib/cretonne/meta/gen_instr.py b/lib/cretonne/meta/gen_instr.py index aae46b5652..56846c90ab 100644 --- a/lib/cretonne/meta/gen_instr.py +++ b/lib/cretonne/meta/gen_instr.py @@ -7,7 +7,7 @@ import constant_hash from unique_table import UniqueTable, UniqueSeqTable import cdsl.types import cdsl.operands -import cretonne +from cdsl.formats import InstructionFormat def gen_formats(fmt): @@ -21,7 +21,7 @@ def gen_formats(fmt): fmt.doc_comment('and the `InstructionData` enums.') fmt.line('#[derive(Copy, Clone, PartialEq, Eq, Debug)]') with fmt.indented('pub enum InstructionFormat {', '}'): - for f in cretonne.InstructionFormat.all_formats: + for f in InstructionFormat.all_formats: fmt.doc_comment(str(f)) fmt.line(f.name + ',') fmt.line() @@ -34,7 +34,7 @@ def gen_formats(fmt): "fn from(inst: &'a InstructionData) -> InstructionFormat {", '}'): with fmt.indented('match *inst {', '}'): - for f in cretonne.InstructionFormat.all_formats: + for f in InstructionFormat.all_formats: fmt.line(('InstructionData::{} {{ .. }} => ' + 'InstructionFormat::{},') .format(f.name, f.name)) @@ -55,7 +55,7 @@ def gen_arguments_method(fmt, is_mut): 'pub fn {f}(&{m}self) -> [&{m}[Value]; 2] {{' .format(f=method, m=mut), '}'): with fmt.indented('match *self {', '}'): - for f in cretonne.InstructionFormat.all_formats: + for f in InstructionFormat.all_formats: n = 'InstructionData::' + f.name has_varargs = cdsl.operands.VARIABLE_ARGS in f.kinds # Formats with both fixed and variable arguments delegate to @@ -118,7 +118,7 @@ def gen_instruction_data_impl(fmt): fmt.doc_comment('Get the opcode of this instruction.') with fmt.indented('pub fn opcode(&self) -> Opcode {', '}'): with fmt.indented('match *self {', '}'): - for f in cretonne.InstructionFormat.all_formats: + for f in InstructionFormat.all_formats: fmt.line( 'InstructionData::{} {{ opcode, .. }} => opcode,' .format(f.name)) @@ -126,7 +126,7 @@ def gen_instruction_data_impl(fmt): fmt.doc_comment('Type of the first result, or `VOID`.') with fmt.indented('pub fn first_type(&self) -> Type {', '}'): with fmt.indented('match *self {', '}'): - for f in cretonne.InstructionFormat.all_formats: + for f in InstructionFormat.all_formats: fmt.line( 'InstructionData::{} {{ ty, .. }} => ty,' .format(f.name)) @@ -135,7 +135,7 @@ def gen_instruction_data_impl(fmt): with fmt.indented( 'pub fn first_type_mut(&mut self) -> &mut Type {', '}'): with fmt.indented('match *self {', '}'): - for f in cretonne.InstructionFormat.all_formats: + for f in InstructionFormat.all_formats: fmt.line( 'InstructionData::{} {{ ref mut ty, .. }} => ty,' .format(f.name)) @@ -147,7 +147,7 @@ def gen_instruction_data_impl(fmt): with fmt.indented( 'pub fn second_result(&self) -> Option {', '}'): with fmt.indented('match *self {', '}'): - for f in cretonne.InstructionFormat.all_formats: + for f in InstructionFormat.all_formats: if f.multiple_results: fmt.line( 'InstructionData::' + f.name + @@ -164,7 +164,7 @@ def gen_instruction_data_impl(fmt): "pub fn second_result_mut<'a>(&'a mut self)" + " -> Option<&'a mut Value> {", '}'): with fmt.indented('match *self {', '}'): - for f in cretonne.InstructionFormat.all_formats: + for f in InstructionFormat.all_formats: if f.multiple_results: fmt.line( 'InstructionData::' + f.name + @@ -180,7 +180,7 @@ def gen_instruction_data_impl(fmt): with fmt.indented( 'pub fn typevar_operand(&self) -> Option {', '}'): with fmt.indented('match *self {', '}'): - for f in cretonne.InstructionFormat.all_formats: + for f in InstructionFormat.all_formats: n = 'InstructionData::' + f.name if f.typevar_operand is None: fmt.line(n + ' { .. } => None,') @@ -612,7 +612,7 @@ def gen_builder(insts, fmt): "pub trait InstBuilder<'f>: InstBuilderBase<'f> {", '}'): for inst in insts: gen_inst_builder(inst, fmt) - for f in cretonne.InstructionFormat.all_formats: + for f in InstructionFormat.all_formats: gen_format_constructor(f, fmt) diff --git a/lib/cretonne/meta/gen_settings.py b/lib/cretonne/meta/gen_settings.py index 6a05d1fa03..74aa0dca48 100644 --- a/lib/cretonne/meta/gen_settings.py +++ b/lib/cretonne/meta/gen_settings.py @@ -5,8 +5,8 @@ from __future__ import absolute_import import srcgen from unique_table import UniqueSeqTable import constant_hash +from cdsl import camel_case from cdsl.settings import BoolSetting, NumSetting, EnumSetting -from cretonne import camel_case from base import settings diff --git a/lib/cretonne/meta/isa/riscv/defs.py b/lib/cretonne/meta/isa/riscv/defs.py index 4fccbf09a6..2a3aa3cc9d 100644 --- a/lib/cretonne/meta/isa/riscv/defs.py +++ b/lib/cretonne/meta/isa/riscv/defs.py @@ -5,9 +5,9 @@ Commonly used definitions. """ from __future__ import absolute_import from cretonne import TargetISA, CPUMode -import cretonne.base +import base.instructions -isa = TargetISA('riscv', [cretonne.base.instructions]) +isa = TargetISA('riscv', [base.instructions.GROUP]) # CPU modes for 32-bit and 64-bit operation. RV32 = CPUMode('RV32', isa) diff --git a/lib/cretonne/meta/isa/riscv/encodings.py b/lib/cretonne/meta/isa/riscv/encodings.py index 807fdafc7a..0fc3a3ee8d 100644 --- a/lib/cretonne/meta/isa/riscv/encodings.py +++ b/lib/cretonne/meta/isa/riscv/encodings.py @@ -2,7 +2,7 @@ RISC-V Encodings. """ from __future__ import absolute_import -from cretonne import base +from base import instructions as base from .defs import RV32, RV64 from .recipes import OPIMM, OPIMM32, OP, OP32, R, Rshamt, I from .settings import use_m