1 //===- TargetRegistry.h ---------------------------------------------------===// 2 // 3 // The MCLinker Project 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 #ifndef MCLD_TARGET_REGISTRY_H 10 #define MCLD_TARGET_REGISTRY_H 11 #include <llvm/Support/TargetRegistry.h> 12 #include <string> 13 #include <list> 14 15 namespace llvm { 16 class TargetMachine; 17 class MCCodeEmitter; 18 class MCContext; 19 class AsmPrinter; 20 } // namespace of llvm 21 22 namespace mcld { 23 24 class Module; 25 class LinkerConfig; 26 class MemoryArea; 27 class MCLDTargetMachine; 28 class TargetRegistry; 29 class MCLinker; 30 class TargetLDBackend; 31 class AttributeFactory; 32 class InputFactory; 33 class ContextFactory; 34 class DiagnosticLineInfo; 35 36 //===----------------------------------------------------------------------===// 37 /// Target - mcld::Target is an object adapter of llvm::Target 38 //===----------------------------------------------------------------------===// 39 class Target 40 { 41 friend class mcld::MCLDTargetMachine; 42 friend class mcld::TargetRegistry; 43 public: 44 typedef mcld::MCLDTargetMachine *(*TargetMachineCtorTy)(const mcld::Target &, 45 llvm::TargetMachine &, 46 const std::string&); 47 48 typedef MCLinker *(*MCLinkerCtorTy)(const std::string& pTriple, 49 LinkerConfig&, 50 Module&, 51 MemoryArea& pOutput); 52 53 typedef bool (*EmulationFnTy)(const std::string& pTriple, LinkerConfig&); 54 55 typedef TargetLDBackend *(*TargetLDBackendCtorTy)(const llvm::Target&, 56 const LinkerConfig&); 57 58 typedef DiagnosticLineInfo *(*DiagnosticLineInfoCtorTy)(const mcld::Target&, 59 const std::string&); 60 61 public: 62 Target(); 63 64 void setTarget(const llvm::Target& pTarget) 65 { m_pT = &pTarget; } 66 67 mcld::MCLDTargetMachine *createTargetMachine(const std::string &pTriple, 68 const std::string &pCPU, const std::string &pFeatures, 69 const llvm::TargetOptions &Options, 70 llvm::Reloc::Model RM = llvm::Reloc::Default, 71 llvm::CodeModel::Model CM = llvm::CodeModel::Default, 72 llvm::CodeGenOpt::Level OL = llvm::CodeGenOpt::Default) const 73 { 74 if (TargetMachineCtorFn && m_pT) { 75 llvm::TargetMachine *tm = m_pT->createTargetMachine(pTriple, pCPU, pFeatures, Options, RM, CM, OL); 76 if (tm) 77 return TargetMachineCtorFn(*this, *tm, pTriple); 78 } 79 return NULL; 80 } 81 82 /// createMCLinker - create target-specific MCLinker 83 /// 84 /// @return created MCLinker 85 MCLinker *createMCLinker(const std::string &pTriple, 86 LinkerConfig& pConfig, 87 Module& pModule, 88 MemoryArea& pOutput) const { 89 if (!MCLinkerCtorFn) 90 return NULL; 91 return MCLinkerCtorFn(pTriple, pConfig, pModule, pOutput); 92 } 93 94 /// emulate - given MCLinker default values for the other aspects of the 95 /// target system. 96 bool emulate(const std::string& pTriple, LinkerConfig& pConfig) const { 97 if (!EmulationFn) 98 return false; 99 return EmulationFn(pTriple, pConfig); 100 } 101 102 /// createLDBackend - create target-specific LDBackend 103 /// 104 /// @return created TargetLDBackend 105 TargetLDBackend* createLDBackend(const LinkerConfig& pConfig) const 106 { 107 if (!TargetLDBackendCtorFn) 108 return NULL; 109 return TargetLDBackendCtorFn(*get(), pConfig); 110 } 111 112 /// createDiagnosticLineInfo - create target-specific DiagnosticLineInfo 113 DiagnosticLineInfo* createDiagnosticLineInfo(const mcld::Target& pTarget, 114 const std::string& pTriple) const 115 { 116 if (!DiagnosticLineInfoCtorFn) 117 return NULL; 118 return DiagnosticLineInfoCtorFn(pTarget, pTriple); 119 } 120 121 const llvm::Target* get() const { return m_pT; } 122 123 private: 124 // ----- function pointers ----- // 125 TargetMachineCtorTy TargetMachineCtorFn; 126 MCLinkerCtorTy MCLinkerCtorFn; 127 EmulationFnTy EmulationFn; 128 TargetLDBackendCtorTy TargetLDBackendCtorFn; 129 DiagnosticLineInfoCtorTy DiagnosticLineInfoCtorFn; 130 131 // ----- adapted llvm::Target ----- // 132 const llvm::Target* m_pT; 133 }; 134 135 //===----------------------------------------------------------------------===// 136 /// TargetRegistry - mcld::TargetRegistry is an object adapter of 137 /// llvm::TargetRegistry 138 /// 139 class TargetRegistry 140 { 141 public: 142 typedef std::list<mcld::Target*> TargetListTy; 143 typedef TargetListTy::iterator iterator; 144 145 private: 146 static TargetListTy s_TargetList; 147 148 public: 149 static iterator begin() { return s_TargetList.begin(); } 150 static iterator end() { return s_TargetList.end(); } 151 152 static size_t size() { return s_TargetList.size(); } 153 static bool empty() { return s_TargetList.empty(); } 154 155 /// RegisterTarget - Register the given target. Attempts to register a 156 /// target which has already been registered will be ignored. 157 /// 158 /// Clients are responsible for ensuring that registration doesn't occur 159 /// while another thread is attempting to access the registry. Typically 160 /// this is done by initializing all targets at program startup. 161 /// 162 /// @param T - The target being registered. 163 static void RegisterTarget(mcld::Target &T); 164 165 /// RegisterTargetMachine - Register a TargetMachine implementation for the 166 /// given target. 167 /// 168 /// @param T - The target being registered. 169 /// @param Fn - A function to construct a TargetMachine for the target. 170 static void RegisterTargetMachine(mcld::Target &T, mcld::Target::TargetMachineCtorTy Fn) 171 { 172 // Ignore duplicate registration. 173 if (!T.TargetMachineCtorFn) 174 T.TargetMachineCtorFn = Fn; 175 } 176 177 /// RegisterMCLinker - Register a MCLinker implementation for the given 178 /// target. 179 /// 180 /// @param T - the target being registered 181 /// @param Fn - A function to create MCLinker for the target 182 static void RegisterMCLinker(mcld::Target &T, mcld::Target::MCLinkerCtorTy Fn) 183 { 184 if (!T.MCLinkerCtorFn) 185 T.MCLinkerCtorFn = Fn; 186 } 187 188 /// RegisterEmulation - Register a emulation function for the target. 189 /// target. 190 /// 191 /// @param T - the target being registered 192 /// @param Fn - A emulation function 193 static void RegisterEmulation(mcld::Target &T, mcld::Target::EmulationFnTy Fn) 194 { 195 if (!T.EmulationFn) 196 T.EmulationFn = Fn; 197 } 198 199 /// RegisterTargetLDBackend - Register a TargetLDBackend implementation for 200 /// the given target. 201 /// 202 /// @param T - The target being registered 203 /// @param Fn - A function to create TargetLDBackend for the target 204 static void RegisterTargetLDBackend(mcld::Target &T, mcld::Target::TargetLDBackendCtorTy Fn) 205 { 206 if (!T.TargetLDBackendCtorFn) 207 T.TargetLDBackendCtorFn = Fn; 208 } 209 210 /// RegisterTargetDiagnosticLineInfo - Register a DiagnosticLineInfo 211 /// implementation for the given target. 212 /// 213 /// @param T - The target being registered 214 /// @param Fn - A function to create DiagnosticLineInfo for the target 215 static void 216 RegisterDiagnosticLineInfo(mcld::Target &T, 217 mcld::Target::DiagnosticLineInfoCtorTy Fn) 218 { 219 if (!T.DiagnosticLineInfoCtorFn) 220 T.DiagnosticLineInfoCtorFn = Fn; 221 } 222 223 /// lookupTarget - Lookup a target based on a llvm::Target. 224 /// 225 /// @param T - The llvm::Target to find 226 static const mcld::Target *lookupTarget(const llvm::Target& T); 227 228 /// lookupTarget - function wrapper of llvm::TargetRegistry::lookupTarget 229 /// 230 /// @param Triple - The Triple string 231 /// @param Error - The returned error message 232 static const mcld::Target *lookupTarget(const std::string &Triple, 233 std::string &Error); 234 }; 235 236 /// RegisterTarget - Helper function for registering a target, for use in the 237 /// target's initialization function. Usage: 238 /// 239 /// Target TheFooTarget; // The global target instance. 240 /// 241 /// extern "C" void MCLDInitializeFooTargetInfo() { 242 /// RegisterTarget X(TheFooTarget, "foo", "Foo description"); 243 /// } 244 struct RegisterTarget 245 { 246 RegisterTarget(mcld::Target &T, const char *Name) { 247 llvm::TargetRegistry::iterator TIter, TEnd = llvm::TargetRegistry::end(); 248 // lookup llvm::Target 249 for( TIter=llvm::TargetRegistry::begin(); TIter!=TEnd; ++TIter ) { 250 if( 0==strcmp(TIter->getName(), Name) ) 251 break; 252 } 253 254 if (TIter != TEnd) 255 T.setTarget(*TIter); 256 257 TargetRegistry::RegisterTarget(T); 258 } 259 }; 260 261 /// RegisterTargetMachine - Helper template for registering a target machine 262 /// implementation, for use in the target machine initialization 263 /// function. Usage: 264 /// 265 /// extern "C" void MCLDInitializeFooTarget() { 266 /// extern mcld::Target TheFooTarget; 267 /// RegisterTargetMachine<mcld::FooTargetMachine> X(TheFooTarget); 268 /// } 269 template<class TargetMachineImpl> 270 struct RegisterTargetMachine 271 { 272 RegisterTargetMachine(mcld::Target &T) { 273 TargetRegistry::RegisterTargetMachine(T, &Allocator); 274 } 275 276 private: 277 static mcld::MCLDTargetMachine *Allocator(const mcld::Target &T, 278 llvm::TargetMachine& TM, 279 const std::string &Triple) { 280 return new TargetMachineImpl(TM, T, Triple); 281 } 282 }; 283 284 } //end namespace mcld 285 286 #endif 287 288