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