Like before, we store a redundant EBB with each predecessor instruction
which allows invalidate_ebb_successors() to clean up the successor's
predecessor lists even after instructions have been moved around in the
layout.
Define two public iterator types in the flowgraph module, PredIter and
SuccIter, which are by-value iterators over an EBB's predecessors and
successors respectively.
Provide matching pred_iter() and succ_iter() methods for inspecting the
CFG. Remove the get_predecessors() method which returned a slice.
Update the uses of get_predecessors(), none of which depended on it
being a slice.
This abstraction makes it possible to change the internal representation
of the CFG.
* Treat VMContext as standard positional argument when using Native CallConv.
This requires threading the CallConv through legalize_args and into ArgAssigner.
* Stash CallConv in the intel-specific Args struct, for use ArgAssigner.
This has two advantages over the previous Vec<Ebb>:
- Duplicates are removed.
- Clearing the control flow graph is constant time.
The set of EBB successors is simply ordered by EBB number.
The control flow graph does not guarantee any particular ordering for
its successor lists, and the post-order we are computing for building
the dominator tree needs to be "split-invariant".
See #146 for details.
- Discover EBB successors directly from the EBB instruction sequence to
guarantee that the post-order we compute is canonical/split-invariant.
- Use an alternative graph DFS algorithm which doesn't require indexing
into a slice of successors.
This changes cfg_postorder in some cases because the edge pruning when
converting the (DAG) CFG to a tree for the DFT is different.
The default container is empty. We need a manual implementation of
Default because deriving it seems to imply that K and V generic
parameter types must also implement Default.
Cloning can be used to clone an empty container or for cloning the whole
forest. We can derive this trait because we already require Copy for K
and V.
The iter() methods return an iterator that traverses all set elements /
map key-value pairs. The iterator doesn't require a mutable container
and forest reference, unlike the cursor types.
Add new ordered set and map data structures based on B+-trees. These are
not general-purpose data structures like the BTreeSet and BTreeMap types
in the standard library. They are specialized for:
- Keys and values are small `Copy` types, optimized for 32-bit entities.
- Each set or map has a very small footprint, using only 32 bits of
memory when empty.
- Keys are compared using a borrowed comparator object which can provide
context for comparing tiny types that don't contain enough information
to implement `Ord`.
- A whole forest of B-trees can be cleared in constant time without
having to traverse the whole data structure.
The main change is that it avoids creating blank lines when processing
docstrings.
This also adds blank lines in various places to make the generated code
prettier.
Fixes#178.
When an instruction with a fixed output operand defines a globally live
SSA value, we need to check if the fixed register is available in the
`regs.global` set of registers that can be used across EBB boundaries.
If the fixed output register is not available in regs.global, set the
replace_global_defines flag so the output operands are rewritten as
local values.
Fixes#175.
The Intel division instructions have fixed input operands that are
clobbered by fixed output operands, so the value passed as an input will
be clobbered just like a tied operand.
The FixedTied operand constraint is used to indicate a fixed input
operand that has a corresponding output operand with the same fixed
register.
Teach the spiller to teach a FixedTied operand the same as a Tied
operand constraint and make sure that the input value is killed by the
instruction.