We llow forward references to values and EBBs, so it is not possible to rewrite
these from the source domain to the in-memory domain during parsing.
Instead go through all the instructions after parsing everything and rewrite the
value and EBB references when everything has been created and mapped.
Instructions that don't produce any result values are marked with first_type() =
VOID. The inst_results() iterator should not return any values for such
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.
Create map entries for ebbs and values as they are defined, but leave ebb and
value operands unresolved on instructions as they are parsed. Instruction
operands can refer to ebbs and values that may not have been defined yet.
Don't infer or check result types yet.
Place instructions in a doubly linked list and point to the first and last
instruction in an EBB.
Provide an iterator for all the EBBs too. This doesn't reflect the layout
order, but simply the order blocks were created.
Avoid gathering too much code in repr.rs.
The `entities` module contains entity reference types, and the `instructions`
module contains instruction opcodes and formats.
Values that are defined together are represented as a singly linked list. These
lists appear in:
- Instructions with multiple result values. The first result value is special, and the
following results form a linked list of Def extended_value table entries.
- EBB arguments are represented as a linked list of Argument extended_value
table entries. The EbbData struct has pointers to the first and last argument
to allow fast insertion at both ends.
Add a Values iterator type whicih can enumerate both kinds of value lists.
When Function serves as a container for IL entities, use the Index trait to
translate a reference class to a Data object.
Works for:
- StackSlot -> StackSlotData
- Inst -> InstructionData
Add a stack slot array to repr::Function, use repr::StackSlot to reference them.
Parse stack slot declarations in the function preamble, add them to the
function.
Add a new `Context` struct which keeps track of mappings between identifiers
used in the file and real references.
A function owns instructions and extended basic blocks. References to these
entities are implemented as opaque structs indexing into the functions internal
tables. This avoids fighting Rust's ownership checking and it also makes
references 4 bytes on all platforms.
SSA values are identified similarly, but with an optimization for the first
value produced by an instruction. Very few instructions will produce more than
one value, and there is an extended value table for those.