First look for exact matches before trying the implicit
lookup. Otherwise, finding two wrong matches first will
result in an ambiguous function error.
This logic could use with a bit of a cleanup, keeping
track of a closer score and doing more exact matching
on types, but this might be good enough for now.
A single `Writer` can be reused to convert any number of Naga IR modules to
SPIR-V. This lets us reuse the heap allocations, but makes us responsible for
resetting the state of the `Writer` fully between modules. The old code
neglected to clear several different fields: logical_layout (all fields),
lookup_type, and cached_constants.
This commit uses Rust struct literal expressions to construct the re-initialized
`Writer`, which makes the compiler check that each field has been handled.
It also introduces a policy limiting how much storage will be retained, so that
processing the occasional whale doesn't leave us with leviathan buffers
permanently.
Rather than giving `Block` an optional `terminator` field in addition to its
`body`, track block termination statically, with two types:
- `Block` is a block without a termination instruction. This is what most code
generation functions operate on.
- `TerminatedBlock` is a block with a termination instruction. This is what
`Function::blocks` holds.
The `Function::consume` method takes a `Block` by value, together with a
termination instruction, and turns it into a `TerminatedBlock`.
This lets us remove some unwraps and awkward conditions.
As part of this change, `Writer::write_block` no longer hits an `unimplemented!`
for Naga statements following `Break`, `Return`, and so on. Instead, it simply
doesn't emit code for them, which is a correct translation. If we want to forbid
these, we should handle that in validation instead.
If validation fails, `Validator` may be left with entries in
`valid_expression_list` and `valid_expression_set`. The validator does clear the
set before examining a function's body, but not the list, which means a
long-lived `Validator` could accumulate an unbounded amount of garbage in the
list.
(Minor cleanup: use structural update syntax where appropriate.)
The `impl` blocks for `Writer` and its associated types remain in spv/writer.rs.
There should be no substantive code changes in this commit, only moving code
around and adjusting `use` declarations to match.