I’m perusing the LLVM source, and I need to know where the ISA mappings are kept in source for the semantics of a given architecture. Like, say I’m compiling to arm, I would like to know for the compiler to pick an opcode, say 0x1, that 0x1 corresponds to xyz operations that the compiler knows about. Where or what file tells the compiler this? Is there any convention for targets, where this can be regularly expected to be for a given target?
I'd recommend taking a look through
https://llvm.org/docs/CodeGenerator.html for an overview of how code
generation works in LLVM. In the common case, you'll find pattern
fragments matching target-independent SelectionDAG opcodes to native
instructions in the *InstrInfo.td files in lib/Target/<Foo>/. These
are specified using the TableGen domain-specific language. You'll find
cases that can't be handled by these patterns covered in the
<Foo>DAGToDAGIsel::Select method. See also GlobalISel
https://llvm.org/docs/GlobalISel/index.html (and talks on it at recent
LLVM Dev meetings) for an alternative instruction selection approach.
Perhaps my talk from a few years ago is also helpful
It works from the MC layer up, but slide 20 onwards cover instruction
selection and gives examples with some of the helper classes we use in
the RISC-V backend stripped away. For an add, it's as simple as:
def : Pat<(add GPR:$rs1, GPR:$rs2),
(ADD GPR:$rs1, GPR:$rs2)>;
def : Pat<(add GPR:$rs1, simm12:$imm12),
(ADDI GPR:$rs1, simm12:$imm12)>;
Hope that helps.
Would you know how I could recognize which opcodes are kernel mode vs user mode?