Registering a target

For running the llc tool in the TOY target architecture, it has to be registered with the llc tool. This recipe demonstrates which configuration files need to be modified to register a target. The build files are modified in this recipe.

How to do it…

To register a target with a static compiler, follow these steps:

  1. First, add the entry of the TOY backend to llvm_root_dir/CMakeLists.txt:
    set(LLVM_ALL_TARGETS
      AArch64
      ARM
      …
      …
      TOY
      )
  2. Then add the toy entry to llvm_root_dir/include/llvm/ADT/Triple.h:
    class Triple {
    public:
      enum ArchType {
        UnknownArch,
    
        arm,        // ARM (little endian): arm, armv.*, xscale
        armeb,      // ARM (big endian): armeb
        aarch64,    // AArch64 (little endian): aarch64
        …
       …
    
    toy     // TOY: toy
    };
  3. Add the toy entry to llvm_root_dir/include/llvm/ MC/MCExpr.h:
    class MCSymbolRefExpr : public MCExpr {
    public:
    enum VariantKind {
    ...
    VK_TOY_LO,
    VK_TOY_HI,
    };
  4. Add the toy entry to llvm_root_dir/include/llvm/ Support/ELF.h:
    enum {
      EM_NONE          = 0, // No machine
      EM_M32           = 1, // AT&T WE 32100
      …
      …
      EM_TOY           = 220 // whatever is the next number
    };
  5. Then, add the toy entry to lib/MC/MCExpr.cpp:
    StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
    switch (Kind) {
    
      …
      …
      case VK_TOY_LO: return "TOY_LO";
      case VK_TOY_HI: return "TOY_HI";
      }
    …
    }
  6. Next, add the toy entry to lib/Support/Triple.cpp:
    const char *Triple::getArchTypeName(ArchType Kind) {
      switch (Kind) {
     …
     …
     case toy:         return "toy";
    
    }
    
    const char *Triple::getArchTypePrefix(ArchType Kind) {
      switch (Kind) {
     …
     …
    case toy:         return "toy";
      }
    }
    
    Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
    …
    …
        .Case("toy", toy)
    …
    }
    
    static Triple::ArchType parseArch(StringRef ArchName) {
    …
    …
        .Case("toy", Triple::toy)
    …
    }
    
    
    static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) {
    …
    …
    case llvm::Triple::toy:
        return 32;
    
    …
    …
    }
    
    Triple Triple::get32BitArchVariant() const {
    …
    …
    case Triple::toy:
        // Already 32-bit.
        break;
    …
    }
    
    Triple Triple::get64BitArchVariant() const {
    …
    …
    case Triple::toy:
        T.setArch(UnknownArch);
        break;
    
    …
    …
    }
  7. Add the toy directory entry to lib/Target/LLVMBuild.txt:
    [common]
    subdirectories = ARM AArch64 CppBackend Hexagon MSP430 … … TOY
  8. Create a new file called TOY.h in the lib/Target/TOY folder:
    #ifndef TARGET_TOY_H
    #define TARGET_TOY_H
    
    #include "MCTargetDesc/TOYMCTargetDesc.h"
    #include "llvm/Target/TargetMachine.h"
    
    namespace llvm {
    class TargetMachine;
    class TOYTargetMachine;
    
    FunctionPass *createTOYISelDag(TOYTargetMachine &TM,
                                   CodeGenOpt::Level OptLevel);
    } // end namespace llvm;
    
    #endif
  9. Create a new folder called TargetInfo in the lib/Target/TOY folder. Inside that folder, create a new file called TOYTargetInfo.cpp, as follows:
    #include "TOY.h"
    #include "llvm/IR/Module.h"
    #include "llvm/Support/TargetRegistry.h"
    using namespace llvm;
    
    Target llvm::TheTOYTarget;
    
    extern "C" void LLVMInitializeTOYTargetInfo() {
      RegisterTarget<Triple::toy> X(TheTOYTarget, "toy", "TOY");
    }
  10. In the same folder, create the CMakeLists.txt file:
    add_llvm_library(LLVMTOYInfo
      TOYTargetInfo.cpp
      )
  11. Create an LLVMBuild.txt file:
    [component_0]
    type = Library
    name = TOYInfo
    parent = TOY
    required_libraries = Support
    add_to_library_groups = TOY
  12. In the lib/Target/TOY folder, create a file called TOYTargetMachine.cpp:
    #include "TOYTargetMachine.h"
    #include "TOY.h"
    #include "TOYFrameLowering.h"
    #include "TOYInstrInfo.h"
    #include TOYISelLowering.h"
    #include "TOYSelectionDAGInfo.h"
    #include "llvm/CodeGen/Passes.h"
    #include "llvm/IR/Module.h"
    #include "llvm/PassManager.h"
    #include "llvm/Support/TargetRegistry.h"
    using namespace llvm;
    
    TOYTargetMachine::TOYTargetMachine(const Target &T, StringRef TT, StringRef CPU, StringRef FS, const TargetOptions &Options,
    Reloc::Model RM, CodeModel::Model CM,
                                       CodeGenOpt::Level OL)
        : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL),
          Subtarget(TT, CPU, FS, *this) {
      initAsmInfo();
    }
    
    namespace {
    class TOYPassConfig : public TargetPassConfig {
    public:
      TOYPassConfig(TOYTargetMachine *TM, PassManagerBase &PM)
          : TargetPassConfig(TM, PM) {}
    
      TOYTargetMachine &getTOYTargetMachine() const {
        return getTM<TOYTargetMachine>();
      }
    
      virtual bool addPreISel();
      virtual bool addInstSelector();
      virtual bool addPreEmitPass();
    };
    } // namespace
    
    TargetPassConfig *TOYTargetMachine::createPassConfig(PassManagerBase &PM) {
      return new TOYPassConfig(this, PM);
    }
    
    bool TOYPassConfig::addPreISel() { return false; }
    
    bool TOYPassConfig::addInstSelector() {
      addPass(createTOYISelDag(getTOYTargetMachine(), getOptLevel()));
      return false;
    }
    
    bool TOYPassConfig::addPreEmitPass() { return false; }
    
    // Force static initialization.
    extern "C" void LLVMInitializeTOYTarget() {
      RegisterTargetMachine<TOYTargetMachine> X(TheTOYTarget);
    }
    
    void TOYTargetMachine::addAnalysisPasses(PassManagerBase &PM) {}
  13. Create a new folder called MCTargetDesc and a new file called TOYMCTargetDesc.h:
    #ifndef TOYMCTARGETDESC_H
    #define TOYMCTARGETDESC_H
    
    #include "llvm/Support/DataTypes.h"
    
    namespace llvm {
    class Target;
    class MCInstrInfo;
    class MCRegisterInfo;
    class MCSubtargetInfo;
    class MCContext;
    class MCCodeEmitter;
    class MCAsmInfo;
    class MCCodeGenInfo;
    class MCInstPrinter;
    class MCObjectWriter;
    class MCAsmBackend;
    
    class StringRef;
    class raw_ostream;
    
    extern Target TheTOYTarget;
    
    MCCodeEmitter *createTOYMCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, const MCSubtargetInfo &STI, MCContext &Ctx);
    
    MCAsmBackend *createTOYAsmBackend(const Target &T, const MCRegisterInfo &MRI, StringRef TT, StringRef   CPU);
    
    MCObjectWriter *createTOYELFObjectWriter(raw_ostream &OS, uint8_t OSABI);
    
    } // End llvm namespace
    
    #define GET_REGINFO_ENUM
    #include "TOYGenRegisterInfo.inc"
    
    #define GET_INSTRINFO_ENUM
    #include "TOYGenInstrInfo.inc"
    
    #define GET_SUBTARGETINFO_ENUM
    #include "TOYGenSubtargetInfo.inc"
    
    #endif
  14. Create one more file, called TOYMCTargetDesc.cpp, in the same folder:
    #include "TOYMCTargetDesc.h"
    #include "InstPrinter/TOYInstPrinter.h"
    #include "TOYMCAsmInfo.h"
    #include "llvm/MC/MCCodeGenInfo.h"
    #include "llvm/MC/MCInstrInfo.h"
    #include "llvm/MC/MCRegisterInfo.h"
    #include "llvm/MC/MCSubtargetInfo.h"
    #include "llvm/MC/MCStreamer.h"
    #include "llvm/Support/ErrorHandling.h"
    #include "llvm/Support/FormattedStream.h"
    #include "llvm/Support/TargetRegistry.h"
    
    #define GET_INSTRINFO_MC_DESC
    #include "TOYGenInstrInfo.inc"
    
    #define GET_SUBTARGETINFO_MC_DESC
    #include "TOYGenSubtargetInfo.inc"
    
    #define GET_REGINFO_MC_DESC
    #include "TOYGenRegisterInfo.inc"
    
    using namespace llvm;
    
    static MCInstrInfo *createTOYMCInstrInfo() {
      MCInstrInfo *X = new MCInstrInfo();
      InitTOYMCInstrInfo(X);
      return X;
    }
    
    static MCRegisterInfo *createTOYMCRegisterInfo(StringRef TT) {
      MCRegisterInfo *X = new MCRegisterInfo();
      InitTOYMCRegisterInfo(X, TOY::LR);
      return X;
    }
    
    static MCSubtargetInfo *createTOYMCSubtargetInfo(StringRef TT, StringRef CPU,
                                                     StringRef FS) {
      MCSubtargetInfo *X = new MCSubtargetInfo();
      InitTOYMCSubtargetInfo(X, TT, CPU, FS);
      return X;
    }
    
    static MCAsmInfo *createTOYMCAsmInfo(const MCRegisterInfo &MRI, StringRef TT) {
      MCAsmInfo *MAI = new TOYMCAsmInfo(TT);
      return MAI;
    }
    
    static MCCodeGenInfo *createTOYMCCodeGenInfo(StringRef TT, Reloc::Model RM,
                                                 CodeModel::Model CM,
                                                 CodeGenOpt::Level OL) {
      MCCodeGenInfo *X = new MCCodeGenInfo();
      if (RM == Reloc::Default) {
        RM = Reloc::Static;
      }
      if (CM == CodeModel::Default) {
        CM = CodeModel::Small;
      }
      if (CM != CodeModel::Small && CM != CodeModel::Large) {
        report_fatal_error("Target only supports CodeModel Small or Large");
      }
    
      X->InitMCCodeGenInfo(RM, CM, OL);
      return X;
    }
    
    static MCInstPrinter *
    createTOYMCInstPrinter(const Target &T, unsigned SyntaxVariant,
                           const MCAsmInfo &MAI, const MCInstrInfo &MII,
                           const MCRegisterInfo &MRI, const MCSubtargetInfo &STI) {
      return new TOYInstPrinter(MAI, MII, MRI);
    }
    
    static MCStreamer *
    createMCAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, bool isVerboseAsm, bool useDwarfDirectory,MCInstPrinter *InstPrint, MCCodeEmitter *CE,MCAsmBackend *TAB, bool ShowInst) {
      return createAsmStreamer(Ctx, OS, isVerboseAsm,   useDwarfDirectory, InstPrint,  CE,   TAB, ShowInst);
    }
    
    static MCStreamer *createMCStreamer(const Target &T, StringRef TT,
                                        MCContext &Ctx, MCAsmBackend &MAB,
                                        raw_ostream &OS,
                                        MCCodeEmitter *Emitter,
                                        const MCSubtargetInfo &STI,
                                        bool RelaxAll,
                                        bool NoExecStack) {
      return createELFStreamer(Ctx, MAB, OS, Emitter, false, NoExecStack);
    }
    
    
    // Force static initialization.
    extern "C" void LLVMInitializeTOYTargetMC() {
      // Register the MC asm info.
      RegisterMCAsmInfoFn X(TheTOYTarget, createTOYMCAsmInfo);
    
      // Register the MC codegen info.
      TargetRegistry::RegisterMCCodeGenInfo(TheTOYTarget, createTOYMCCodeGenInfo);
    
      // Register the MC instruction info.
      TargetRegistry::RegisterMCInstrInfo(TheTOYTarget, createTOYMCInstrInfo);
    
      // Register the MC register info.
      TargetRegistry::RegisterMCRegInfo(TheTOYTarget, createTOYMCRegisterInfo);
    
      // Register the MC subtarget info.
      TargetRegistry::RegisterMCSubtargetInfo(TheTOYTarget,
                                              createTOYMCSubtargetInfo);
    
      // Register the MCInstPrinter
      TargetRegistry::RegisterMCInstPrinter(TheTOYTarget, createTOYMCInstPrinter);
    
      // Register the ASM Backend.
  TargetRegistry::RegisterMCAsmBackend(TheTOYTarget, createTOYAsmBackend);
    
      // Register the assembly streamer.
      TargetRegistry::RegisterAsmStreamer(TheTOYTarget, createMCAsmStreamer);
    
      // Register the object streamer.
      TargetRegistry::RegisterMCObjectStreamer(TheTOYTarget, createMCStreamer);
    
      // Register the MCCodeEmitter
      TargetRegistry::RegisterMCCodeEmitter(TheTOYTarget, createTOYMCCodeEmitter);
    }
  15. In the same folder, create an LLVMBuild.txt file:
    [component_0]
    type = Library
    name = TOYDesc
    parent = TOY
    required_libraries = MC Support TOYAsmPrinter TOYInfo
    add_to_library_groups = TOY
  16. Create a CMakeLists.txt file:
    add_llvm_library(LLVMTOYDesc
      TOYMCTargetDesc.cpp)

How it works…

Build the enitre LLVM project, as follows:

$ cmake llvm_src_dir –DCMAKE_BUILD_TYPE=Release – DLLVM_TARGETS_TO_BUILD="TOY"
$ make

Here, we have specified that we are building the LLVM compiler for the toy target. After the build completes, check whether the TOY target appears with the llc command:

$ llc –version


Registered Targets :
toy – TOY

See also

  • For a more detailed description about complex targets that involve pipelining and scheduling, follow the chapters in Tutorial: Creating an LLVM Backend for the Cpu0 Architecture by Chen Chung-Shu and Anoushe Jamshidi
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
52.15.38.176