Skip to main content

Module capability

Module capability 

Source
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.

Functions§

libcall
The runtime function this operation at this mode becomes, or nothing where it is not a call.
lowering
What rewrites this opcode before selection, if anything does.
rows
The whole table for one target’s rules.