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