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.
Amend build script to generate an encodings-<isa>.rs file for each target ISA.
Emit a function that can evaluate instruction predicates.
Describe the 3-level tables used for representing insrruction encoding tables.
Add Python classes representing the tables.
The generated code is incomplete and not used anywhere yet.
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.
Add an isa::lookup() function which serves as a target registry for creating
Box<TargetIsa> trait objects.
An isa::Builder makes it possible to confugure the trait object before it is
created.
- Move detail data structures into a settings::detail module to avoid polluting
the settings namespace.
- Rename generated data types to 'Flags' in anticipation of computed predicate
flags that can't be set. The Flags struct is immutable.
- Use a settings::Builder struct to manipulate settings, then pass it to
Flags::new().
This trait allows settings to be manipulated as strings, using descriptors and
constant hash-table lookups.
Amend gen_settings.py to generate the necessary constant tables.
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.
Replace the make_multi_inst() function with a make_inst_results() which uses
the constraint system to create the result values. A typevar argument ensures
that this function does not infer anything from the instruction data arguments.
These arguments may not be valid during parsing.
Implement basic type inference in the parser. If the designated value operand
on a polymorphic instruction refers to a known value, use that to infer the
controlling type variable.
This simple method of type inference requires the operand value to be defined
above the use in the text. Since reordering the EBBs could place a dominating
EBB below the current one, this is a bit fragile. One possibility would be to
require the value is defined in the same EBB. In all other cases, the
controlling typevar should be explicit.
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'.