1 //===- MCLDTargetMachine.cpp ----------------------------------------------===// 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 #include <mcld/Target/TargetMachine.h> 10 11 #include <mcld/Module.h> 12 #include <mcld/LinkerConfig.h> 13 #include <mcld/CodeGen/MCLinker.h> 14 #include <mcld/Support/raw_mem_ostream.h> 15 #include <mcld/Support/TargetRegistry.h> 16 #include <mcld/Support/ToolOutputFile.h> 17 #include <mcld/Support/MemoryArea.h> 18 #include <mcld/Target/TargetLDBackend.h> 19 20 #include <llvm/ADT/OwningPtr.h> 21 #include <llvm/Analysis/Passes.h> 22 #include <llvm/Analysis/Verifier.h> 23 #include <llvm/Assembly/PrintModulePass.h> 24 #include <llvm/CodeGen/AsmPrinter.h> 25 #include <llvm/CodeGen/MachineFunctionAnalysis.h> 26 #include <llvm/CodeGen/MachineModuleInfo.h> 27 #include <llvm/CodeGen/GCStrategy.h> 28 #include <llvm/CodeGen/Passes.h> 29 #include <llvm/IR/DataLayout.h> 30 #include <llvm/MC/MCAsmInfo.h> 31 #include <llvm/MC/MCStreamer.h> 32 #include <llvm/MC/MCInstrInfo.h> 33 #include <llvm/MC/MCSubtargetInfo.h> 34 #include <llvm/MC/MCObjectStreamer.h> 35 #include <llvm/MC/MCAssembler.h> 36 #include <llvm/MC/MCObjectWriter.h> 37 #include <llvm/MC/MCContext.h> 38 #include <llvm/PassManager.h> 39 #include <llvm/Support/CommandLine.h> 40 #include <llvm/Support/Debug.h> 41 #include <llvm/Support/TargetRegistry.h> 42 #include <llvm/Support/FormattedStream.h> 43 #include <llvm/Target/TargetInstrInfo.h> 44 #include <llvm/Target/TargetLowering.h> 45 #include <llvm/Target/TargetOptions.h> 46 #include <llvm/Target/TargetSubtargetInfo.h> 47 #include <llvm/Target/TargetLoweringObjectFile.h> 48 #include <llvm/Target/TargetRegisterInfo.h> 49 #include <llvm/Transforms/Scalar.h> 50 51 #include <string> 52 53 using namespace mcld; 54 using namespace llvm; 55 56 //===----------------------------------------------------------------------===// 57 /// Arguments 58 //===----------------------------------------------------------------------===// 59 // Enable or disable FastISel. Both options are needed, because 60 // FastISel is enabled by default with -fast, and we wish to be 61 // able to enable or disable fast-isel independently from -O0. 62 63 static cl::opt<cl::boolOrDefault> 64 ArgEnableFastISelOption("lfast-isel", cl::Hidden, 65 cl::desc("Enable the \"fast\" instruction selector")); 66 67 static cl::opt<bool> 68 ArgShowMCEncoding("lshow-mc-encoding", 69 cl::Hidden, 70 cl::desc("Show encoding in .s output")); 71 72 static cl::opt<bool> 73 ArgShowMCInst("lshow-mc-inst", 74 cl::Hidden, 75 cl::desc("Show instruction structure in .s output")); 76 77 static cl::opt<cl::boolOrDefault> 78 ArgAsmVerbose("fverbose-asm", 79 cl::desc("Put extra commentary information in the \ 80 generated assembly code to make it more readable."), 81 cl::init(cl::BOU_UNSET)); 82 83 static bool getVerboseAsm() { 84 switch (ArgAsmVerbose) { 85 default: 86 case cl::BOU_UNSET: return TargetMachine::getAsmVerbosityDefault(); 87 case cl::BOU_TRUE: return true; 88 case cl::BOU_FALSE: return false; 89 } 90 } 91 92 93 //===---------------------------------------------------------------------===// 94 /// MCLDTargetMachine 95 //===----------------------------------------------------------------------===// 96 mcld::MCLDTargetMachine::MCLDTargetMachine(llvm::TargetMachine &pTM, 97 const mcld::Target& pTarget, 98 const std::string& pTriple) 99 : m_TM(pTM), m_pTarget(&pTarget), m_Triple(pTriple) { 100 } 101 102 mcld::MCLDTargetMachine::~MCLDTargetMachine() { 103 m_pTarget = 0; 104 } 105 106 const mcld::Target& mcld::MCLDTargetMachine::getTarget() const 107 { 108 return *m_pTarget; 109 } 110 111 /// Turn exception handling constructs into something the code generators can 112 /// handle. 113 static void addPassesToHandleExceptions(llvm::TargetMachine *TM, 114 PassManagerBase &PM) { 115 switch (TM->getMCAsmInfo()->getExceptionHandlingType()) { 116 case llvm::ExceptionHandling::SjLj: 117 // SjLj piggy-backs on dwarf for this bit. The cleanups done apply to both 118 // Dwarf EH prepare needs to be run after SjLj prepare. Otherwise, 119 // catch info can get misplaced when a selector ends up more than one block 120 // removed from the parent invoke(s). This could happen when a landing 121 // pad is shared by multiple invokes and is also a target of a normal 122 // edge from elsewhere. 123 PM.add(createSjLjEHPreparePass(TM->getTargetLowering())); 124 // FALLTHROUGH 125 case llvm::ExceptionHandling::DwarfCFI: 126 case llvm::ExceptionHandling::ARM: 127 case llvm::ExceptionHandling::Win64: 128 PM.add(createDwarfEHPass(TM->getTargetLowering())); 129 break; 130 case llvm::ExceptionHandling::None: 131 PM.add(createLowerInvokePass(TM->getTargetLowering())); 132 133 // The lower invoke pass may create unreachable code. Remove it. 134 PM.add(createUnreachableBlockEliminationPass()); 135 break; 136 } 137 } 138 139 140 static llvm::MCContext *addPassesToGenerateCode(llvm::LLVMTargetMachine *TM, 141 PassManagerBase &PM, 142 bool DisableVerify) 143 { 144 // Targets may override createPassConfig to provide a target-specific sublass. 145 TargetPassConfig *PassConfig = TM->createPassConfig(PM); 146 147 // Set PassConfig options provided by TargetMachine. 148 PassConfig->setDisableVerify(DisableVerify); 149 150 PM.add(PassConfig); 151 152 PassConfig->addIRPasses(); 153 154 addPassesToHandleExceptions(TM, PM); 155 156 PassConfig->addISelPrepare(); 157 158 // Install a MachineModuleInfo class, which is an immutable pass that holds 159 // all the per-module stuff we're generating, including MCContext. 160 MachineModuleInfo *MMI = 161 new MachineModuleInfo(*TM->getMCAsmInfo(), *TM->getRegisterInfo(), 162 &TM->getTargetLowering()->getObjFileLowering()); 163 PM.add(MMI); 164 MCContext *Context = &MMI->getContext(); // Return the MCContext by-ref. 165 166 // Set up a MachineFunction for the rest of CodeGen to work on. 167 PM.add(new MachineFunctionAnalysis(*TM)); 168 169 // Enable FastISel with -fast, but allow that to be overridden. 170 if (ArgEnableFastISelOption == cl::BOU_TRUE || 171 (TM->getOptLevel() == CodeGenOpt::None && 172 ArgEnableFastISelOption != cl::BOU_FALSE)) 173 TM->setFastISel(true); 174 175 // Ask the target for an isel. 176 if (PassConfig->addInstSelector()) 177 return NULL; 178 179 PassConfig->addMachinePasses(); 180 181 PassConfig->setInitialized(); 182 183 return Context; 184 185 } 186 187 bool mcld::MCLDTargetMachine::addPassesToEmitFile(PassManagerBase &pPM, 188 mcld::ToolOutputFile& pOutput, 189 mcld::CodeGenFileType pFileType, 190 CodeGenOpt::Level pOptLvl, 191 mcld::Module& pModule, 192 LinkerConfig& pConfig, 193 bool pDisableVerify) 194 { 195 196 llvm::MCContext* Context = 197 addPassesToGenerateCode(static_cast<llvm::LLVMTargetMachine*>(&m_TM), 198 pPM, pDisableVerify); 199 if (!Context) 200 return true; 201 202 switch(pFileType) { 203 default: 204 case mcld::CGFT_NULLFile: 205 assert(0 && "fatal: file type is not set!"); 206 break; 207 case CGFT_ASMFile: { 208 assert(Context != 0 && "Failed to get MCContext"); 209 210 if (getTM().hasMCSaveTempLabels()) 211 Context->setAllowTemporaryLabels(false); 212 213 if (addCompilerPasses(pPM, 214 pOutput.formatted_os(), 215 Context)) 216 return true; 217 break; 218 } 219 case CGFT_OBJFile: { 220 assert(Context != 0 && "Failed to get MCContext"); 221 222 if (getTM().hasMCSaveTempLabels()) 223 Context->setAllowTemporaryLabels(false); 224 if (addAssemblerPasses(pPM, 225 pOutput.mem_os(), 226 Context)) 227 return true; 228 break; 229 } 230 case CGFT_EXEFile: { 231 pConfig.setCodeGenType(LinkerConfig::Exec); 232 if (addLinkerPasses(pPM, 233 pConfig, 234 pModule, 235 pOutput.memory(), 236 Context)) 237 return true; 238 break; 239 } 240 case CGFT_BINARY: { 241 pConfig.setCodeGenType(LinkerConfig::Binary); 242 if (addLinkerPasses(pPM, 243 pConfig, 244 pModule, 245 pOutput.memory(), 246 Context)) 247 return true; 248 break; 249 } 250 case CGFT_DSOFile: { 251 pConfig.setCodeGenType(LinkerConfig::DynObj); 252 if (addLinkerPasses(pPM, 253 pConfig, 254 pModule, 255 pOutput.memory(), 256 Context)) 257 return true; 258 break; 259 } 260 case CGFT_PARTIAL: { 261 pConfig.setCodeGenType(LinkerConfig::Object); 262 if (addLinkerPasses(pPM, 263 pConfig, 264 pModule, 265 pOutput.memory(), 266 Context)) 267 return true; 268 break; 269 } 270 } // switch 271 return false; 272 } 273 274 bool mcld::MCLDTargetMachine::addCompilerPasses(PassManagerBase &pPM, 275 llvm::formatted_raw_ostream &pOutput, 276 llvm::MCContext *&Context) 277 { 278 const MCAsmInfo &MAI = *getTM().getMCAsmInfo(); 279 const MCInstrInfo &MII = *getTM().getInstrInfo(); 280 const MCRegisterInfo &MRI = *getTM().getRegisterInfo(); 281 const MCSubtargetInfo &STI = getTM().getSubtarget<MCSubtargetInfo>(); 282 283 MCInstPrinter *InstPrinter = 284 getTarget().get()->createMCInstPrinter(MAI.getAssemblerDialect(), MAI, 285 MII, 286 Context->getRegisterInfo(), STI); 287 288 MCCodeEmitter* MCE = 0; 289 MCAsmBackend *MAB = 0; 290 if (ArgShowMCEncoding) { 291 MCE = getTarget().get()->createMCCodeEmitter(MII, MRI, STI, *Context); 292 MAB = getTarget().get()->createMCAsmBackend(m_Triple, 293 getTM().getTargetCPU()); 294 } 295 296 297 // now, we have MCCodeEmitter and MCAsmBackend, we can create AsmStreamer. 298 OwningPtr<MCStreamer> AsmStreamer( 299 getTarget().get()->createAsmStreamer(*Context, pOutput, 300 getVerboseAsm(), 301 getTM().hasMCUseLoc(), 302 getTM().hasMCUseCFI(), 303 getTM().hasMCUseDwarfDirectory(), 304 InstPrinter, 305 MCE, MAB, 306 ArgShowMCInst)); 307 308 llvm::MachineFunctionPass* funcPass = 309 getTarget().get()->createAsmPrinter(getTM(), *AsmStreamer.get()); 310 311 if (funcPass == 0) 312 return true; 313 // If successful, createAsmPrinter took ownership of AsmStreamer 314 AsmStreamer.take(); 315 pPM.add(funcPass); 316 return false; 317 } 318 319 bool mcld::MCLDTargetMachine::addAssemblerPasses(PassManagerBase &pPM, 320 llvm::raw_ostream &pOutput, 321 llvm::MCContext *&Context) 322 { 323 // MCCodeEmitter 324 const MCInstrInfo &MII = *getTM().getInstrInfo(); 325 const MCRegisterInfo &MRI = *getTM().getRegisterInfo(); 326 const MCSubtargetInfo &STI = getTM().getSubtarget<MCSubtargetInfo>(); 327 MCCodeEmitter* MCE = 328 getTarget().get()->createMCCodeEmitter(MII, MRI, STI, *Context); 329 330 // MCAsmBackend 331 MCAsmBackend* MAB = 332 getTarget().get()->createMCAsmBackend(m_Triple,getTM().getTargetCPU()); 333 if (MCE == 0 || MAB == 0) 334 return true; 335 336 // now, we have MCCodeEmitter and MCAsmBackend, we can create AsmStreamer. 337 OwningPtr<MCStreamer> AsmStreamer(getTarget().get()->createMCObjectStreamer( 338 m_Triple, 339 *Context, 340 *MAB, 341 pOutput, 342 MCE, 343 getTM().hasMCRelaxAll(), 344 getTM().hasMCNoExecStack())); 345 AsmStreamer.get()->InitSections(); 346 MachineFunctionPass *funcPass = getTarget().get()->createAsmPrinter(getTM(), 347 *AsmStreamer.get()); 348 if (funcPass == 0) 349 return true; 350 // If successful, createAsmPrinter took ownership of AsmStreamer 351 AsmStreamer.take(); 352 pPM.add(funcPass); 353 return false; 354 } 355 356 bool mcld::MCLDTargetMachine::addLinkerPasses(PassManagerBase &pPM, 357 LinkerConfig& pConfig, 358 mcld::Module& pModule, 359 mcld::MemoryArea& pOutput, 360 llvm::MCContext *&Context) 361 { 362 if (NULL == pOutput.handler()) 363 return true; 364 365 // set up output's SOName 366 if (pConfig.options().soname().empty()) { 367 // if the output is a shared object, and the option -soname was not 368 // enable, set soname as the output file name. soname must be UTF-8 string. 369 pModule.setName(pOutput.handler()->path().filename().native()); 370 } 371 else { 372 pModule.setName(pConfig.options().soname()); 373 } 374 375 MachineFunctionPass* funcPass = getTarget().createMCLinker(m_Triple, 376 pConfig, 377 pModule, 378 pOutput); 379 if (NULL == funcPass) 380 return true; 381 382 pPM.add(funcPass); 383 return false; 384 } 385 386