What is LLVM?
What is a Back-End?
Relevant Documentation
Basic reference for LLVM back-end writing is: http://jonathan2251.github.io/lbd/
This document is huge.. A short summary is given at https://llvm.org/docs/WritingAnLLVMBackend.html
TableGen is a program which is specifically written to help writing LLVM backends. A nice documentation about TableGen is provided by the Univ. of Aalto: https://wiki.aalto.fi/display/t1065450/LLVM+TableGen
A shortcut to writing backends is to examine already written backends. Here’s the backend for SPARC:
https://github.com/llvm-mirror/llvm/blob/master/lib/Target/Sparc/SparcTargetMachine.cpp
The following are also very useful
https://eli.thegreenplace.net/2013/02/25/a-deeper-look-into-the-llvm-code-generator-part-1
https://llvm.org/docs/CodeGenerator.html
Steps for writing the backend
- Write a subclass of TargetMachine class for our processor: Generate BirdTargetMachine.cpp and BirdTargetMachine.h files.
- Describe the register set.
- Describe the instruction set.
The BirdTargetMachine Class
namespace llvm { class Module; class BirdTargetMachine : public LLVMTargetMachine { const DataLayout DataLayout; // Calculates type size & alignment BirdSubtarget Subtarget; BirdInstrInfo InstrInfo; TargetFrameInfo FrameInfo; protected: virtual const TargetAsmInfo *createTargetAsmInfo() const; public: BirdTargetMachine(const Module &M, const std::string &FS); virtual const BirdInstrInfo *getInstrInfo() const {return &InstrInfo; } virtual const TargetFrameInfo *getFrameInfo() const {return &FrameInfo; } virtual const TargetSubtarget *getSubtargetImpl() const{return &Subtarget; } virtual const TargetRegisterInfo *getRegisterInfo() const { return &InstrInfo.getRegisterInfo(); } virtual const DataLayout *getDataLayout() const { return &DataLayout; } static unsigned getModuleMatchQuality(const Module &M); // Pass Pipeline Configuration virtual bool addInstSelector(PassManagerBase &PM, bool Fast); virtual bool addPreEmitPass(PassManagerBase &PM, bool Fast); }; } // end namespace llvm
Defining Registers
The following Register
class (specified in the file target.td) is used to define an object for each register.
class Register<string n> { //register name string Namespace = ""; string AsmName = n; string Name = n; int SpillSize = 0; int SpillAlignment = 0; list<Register> Aliases = []; list<Register> SubRegs = []; list<int> DwarfNumbers = []; }
in theBirdRegisterInfo.td
file, there are register definitions that utilize theRegister
class, such as:
def AL : Register<"AL">, DwarfRegNum<[0, 0, 0]>;
This defines register AL. “DwarfRegNum” is not important for us..
From the register info file, TableGen generates a TargetRegisterDesc
object for each register. TargetRegisterDesc
is defined in include/llvm/Target/TargetRegisterInfo.h
with the following fields:
struct TargetRegisterDesc { const char *AsmName; // Assembly language name for the register const char *Name; // Printable name for the reg (for debugging) const unsigned *AliasSet; // Register Alias Set const unsigned *SubRegs; // Sub-register set const unsigned *ImmSubRegs; // Immediate sub-register set const unsigned *SuperRegs; // Super-register set };
Structure of tablegen files
Tablegen inputs .td files and generates .inc files.
TableGen files consist of two key parts: classes (marked with the class
keyword) and definitions (marked with the def
keyword). Definitions are instantiations of classes..
TableGen’s syntax includes some automation concepts that facilitate development and reduce amount of code, for exampleforeach, let
and multiclass. let
allows derived class or definition to override a value defined by a superclass. Multiclasses are used to describe groups of records that may be instantiated all at once.