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