Replace the isa::Legalize enumeration with a function pointer. This
allows an ISA to define its own specific legalization actions instead of
relying on the default two.
Generate a LEGALIZE_ACTIONS table for each ISA which contains
legalization function pointers indexed by the legalization codes that
are already in the encoding tables. Include this table in
isa/*/enc_tables.rs.
Give the `Encodings` iterator a reference to the action table and change
its `legalize()` method to return a function pointer instead of an
ISA-specific code.
The Result<> returned from TargetIsa::encode() no longer implements
Debug, so eliminate uses of unwrap and expect on that type.
A fallthrough jump is actually represented as 0 bytes, so no encoding is
needed.
Also allow for unencoded instructions in the generated emit_inst
implementations. The verifier has stricter rules for when this is
allowed.
We allow ghost instructions to exist if they have no side effects.
Instructions that affect control flow or that have other side effects
must be encoded.
Teach the IL verifier to enforce this. Once any instruction has an
encoding, all instructions with side effects must have an encoding.
A priory, an EBB argument value only gets an affinity if it is used
directly by a non-ghost instruction. A use by a branch passing arguments
to an EBB doesn't count.
When an EBB argument value does have an affinity, the values passed by
all the predecessors must also have affinities. This can cause EBB
argument values to get affinities recursively.
- Add a second pass to the liveness computation for propagating EBB
argument affinities, possibly recursively.
- Verify EBB argument affinities correctly: A value passed to a branch
must have an affinity only if the corresponding EBB argument value in
the destination has an affinity.
* Replace a single-character string literal with a character literal.
* Use is_some() instead of comparing with Some(_).
* Add code-quotes around type names in comments.
* Use !...is_empty() instead of len() != 0.
* Tidy up redundant returns.
* Remove redundant .clone() calls.
* Remove unnecessary explicit lifetime parameters.
* Tidy up unnecessary '&'s.
* Add parens to make operator precedence explicit.
* Use debug_assert_eq instead of debug_assert with ==.
* Replace a &Vec argument with a &[...].
* Replace `a = a op b` with `a op= b`.
* Avoid unnecessary closures.
* Avoid .iter() and .iter_mut() for iterating over containers.
* Remove unneeded qualification.
This value affinity doesn't mean "whatever", it means that the value
does not interact with any real instructions, where "real" means
instructions that have a legal encoding.
Update the liveness verifier to check this property:
- Encoded instructions can only use real values.
- Encoded instructions define real values.
- Ghost instructions define ghost values.
This means that we can verify the basics with verify_context before
moving on to verifying the liveness information.
Live ranges are now verified immediately after computing them and after
register allocation is complete.
The liveness verifier will check that the live ranges are consistent
with the function. It runs as part of the register allocation pipeline
when enable_verifier is set.
The initial implementation checks the live ranges, but not the
ISA-specific constraints and affinities.