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.
To register a target with a static compiler, follow these steps:
llvm_root_dir/CMakeLists.txt
:set(LLVM_ALL_TARGETS AArch64 ARM … … TOY )
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 };
llvm_root_dir/include/llvm/ MC/MCExpr.h
:class MCSymbolRefExpr : public MCExpr { public: enum VariantKind { ... VK_TOY_LO, VK_TOY_HI, };
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 };
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"; } … }
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; … … }
lib/Target/LLVMBuild.txt
:[common] subdirectories = ARM AArch64 CppBackend Hexagon MSP430 … … TOY
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
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"); }
CMakeLists.txt
file:add_llvm_library(LLVMTOYInfo TOYTargetInfo.cpp )
LLVMBuild.txt
file:[component_0] type = Library name = TOYInfo parent = TOY required_libraries = Support add_to_library_groups = TOY
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) {}
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
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); }
LLVMBuild.txt
file:[component_0] type = Library name = TOYDesc parent = TOY required_libraries = MC Support TOYAsmPrinter TOYInfo add_to_library_groups = TOY
CMakeLists.txt
file:add_llvm_library(LLVMTOYDesc TOYMCTargetDesc.cpp)
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
52.15.38.176