Expand description
What this target can be asked to do, and what happens when it cannot.
Design: spec/optimizer/36-lowering-and-isel.md section 36.4.
GCC asks one question of a target, which is whether it has an instruction for this operation at
this mode, and the whole of gcc/optabs.cc is built on the answer. rucc asks the same question
and used to give three separate answers in three separate places: a list in crate::coverage
saying an opcode has no rule and that is on purpose, a set of match arms in
crate::quad and crate::wide turning an operation into a call to the compiler runtime,
and the pre-selection group in crate::lowering rewriting an operation into ones the machine
does have.
Those are not three questions. They are one question with three possible answers, and three
places that answer it can disagree without anything noticing. An opcode named on the exception
list and also lowered before selection is a stale line in the list; an opcode named there that
has grown a libcall is the same staleness the other way round. This module is the one table, and
Row is the three columns.
§A row is a name
Section 36.4 says one row per operation and mode. A name is exactly that here, and it is already
how the rest of the back end talks: add.i64 is the addition opcode at sixty four bits, and
crate::coverage has always said that a name is an opcode and a width together. So the rows
are the names, which come from three places.
rucc_ir::term::heads gives every name the rule language can spell, which is the universe the
rule column is about. LIBCALLS gives the names at the two modes the rule language cannot
spell, which is the whole reason those calls exist. And an opcode with no mode at all, a call
or a jump or a trap, gets one row under its own name, because the question is still asked
about it and the answer is still one of the three.
§Why more than one column can be filled
An operation is not obliged to have exactly one answer, and reading it that way is the mistake
the old list made. sitofp.i64.f64 has a rule, because this machine has cvtsi2sd, and it is
also named by crate::lowering::Step::Floats, because the same pass handles the widths the
machine has no instruction for and walks away from the ones it does. Both columns are true and
neither is stale. What would be a contradiction is a rule at a name something rewrites by hand
before selection ever runs, since that rule could never fire, and that is the one overlap the
tests below refuse.
§Which way the arrow points
The lowering column is not written down here. It is read out of crate::lowering::Step, which
is where a lowering says which opcodes it is about, so there is no second copy of the group
membership to go stale. That is the only direction worth having: the group is the authority on
what the group rewrites, and a table that repeated it would be the third mechanism again under a
new name.
What is written down here is the half no pass can be asked for. HAND is the opcodes lowered
somewhere a rule cannot reach and a pass cannot be asked about either, because the answer is a
match arm in crate::lower or in rucc_safety, and LIBCALLS is the runtime function an
operation becomes, which was three sets of match arms and is now one list they read.
Structs§
- Row
- One operation at one mode, and the three answers.
Enums§
- Lowering
- What rewrites an operation before the selector sees it.
Statics§
- HAND
- An opcode lowered somewhere a rule cannot reach, and what happens to it there.
- LIBCALLS
- The runtime function an operation becomes, by opcode and by mode.