Compute the u16 representation of encoding lists and emit a big table
concatenating all of them. Use the UniqueSeqTable to share some table space
between CPU modes.
We need to generate hash tables keyed by types, so the Python scripts need to
know the index used to represent types in Rust code.
To enforce this, add a new gen_types.py script which generates constant
definitions for the ir/types module.
Also generate constants for common SIMD vector sizes.
When generating Rust code for an instruction predicate, call the corresponding
function in the predicates module, using a qualified name.
We don't have methods corresponding to the predicates.
This collects all of the leaf predicates that go into a compound predicate.
Current leaf predicates are:
- Settings for ISA predicates, and
- FieldPredicates for instruction predicates.
Add new instruction predicates to support the 'I' encoding recipe: IsSignedInt,
IsUnsignedInt used to test that an immediate operand is in the allowed range.
Each InstructionFormat instance gets data members corresponding to its immediate
operands, so the can be referred to as BinaryImm.imm, for example.
This will be used to construct instruction predicates.
Usually an instruction firmat has only a single immediate operand called 'imm',
or 'cond' if it is one of the condigtion codes. Add a 'default_member' field to
ImmediateKind to keep track of this default member name in the InstructionData
struct.
Predcates are boolean functions. There will be ISA predicates and instruction
predicates.
The ISA predicates will be turned into member functions on the generated Flags
structs.
Clarify terminology by always referring to a 'Target ISA' instead of just
'Target'. Use 'isa' as a module name instead of 'target' both in Rust and Python
code.
This is only to clarify terminology and not at all because Cargo insists on
using the 'target' sub-directory for build products. Oh, no. Not at all.
The shift instructions have two type variables since the shift amount can be a
differently sized integer. Fix the RISC-V shift encodings to reflect this, and
allow i64 registers to be shifted by an i32 amount.
Move the CPUMode reference from EncRecipe to the Encoding itself, allowing
EncRecipes to be shared between CPU modes. At least RISC-V should be able to
share some recipes between RV32 and RV64 modes.
It is possible to return multiple values from a function, so ReturnData contains
a VariableArgs instance.
We don't want return instructions to appear as 'return (v1)', so tweak the
printing of VariableArgs so the parantheses are added externally.
Naming is interesting here. Since 'truncate' refers to removing the least
significant digits, use 'ireduce' instead. The 'extend' use is fairly
established. Don't abbreviate, avoid unfortunate modern vernacular.
This instruction uses two type variables: input and output. Make sure that our
parser can handle it. The output type variable annotation is mandatory.
Add a ValueTypeSet::example() method which is used to provide better diagnostics
for a missing type variable.
Add new intcc and floatcc operand types for the immediate condition codes on
these instructions.
Add new IntCompare and FloatCompare instruction formats.
Add a generic match_enum() parser function that can match any identifier-like
enumerated operand kind that implements FromStr.
Define the icmp and fcmp instructions in case.py. Include documentation for the
condition codes with these two instructions.
Add an Opcode::constraints() method which returns an OpcodeConstraints object.
This object provides information on instruction polymorphism and how many
results is produced.
Generate a list of TypeSet objects for checking free type variables. The type
sets are parametrized rather than being represented as fully general sets.
Add UniqueTable and UniqueSeqTable classes to the meta code generator. Use for
compressing tabular data by removing duplicates.
Add a typevar_operand argument to the InstructionFormat constructor which
determines the operand used for inferring the controlling type variable.
Identify polymorphic instructions when they are created, determine if the
controlling type variable can be inferred from the typevar_operand, and verify
the use of type variables in the other operands.
Generate type variable summary in the documentation, including how the
controlling type variable is inferred.
This will eventualy be used for add-with-carry and add-with-overflow type
instructions. For now it only serves as a representative of instruction formats
that have multiple_results=True and boxed_storage=False at the same time.
Accessors for shared fields and multiple results can be generated automatically.
Add a 'boxed_storage' flag to the instruction format definitions to enable
generated code to access 'data'.
These two enums must have identical variants. One is generated from the
instruction formats in meta/cretonne/formats.py, the other defines the contents
of an instruction.
Emit a conversion from InstructionData to InstructionFormat which also serves
to verify the correspondence. Rustc will error is the match is not complete.
This is a no-payload enum which will have the same variants as InstructionData.
This makes it possible to talk about the format of an instruction without
actually creating an InstructionData instance.
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.