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 53using namespace mcld; 54using 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 62static cl::opt<cl::boolOrDefault> 63ArgEnableFastISelOption("lfast-isel", cl::Hidden, 64 cl::desc("Enable the \"fast\" instruction selector")); 65 66static cl::opt<bool> 67ArgShowMCEncoding("lshow-mc-encoding", 68 cl::Hidden, 69 cl::desc("Show encoding in .s output")); 70 71static cl::opt<bool> 72ArgShowMCInst("lshow-mc-inst", 73 cl::Hidden, 74 cl::desc("Show instruction structure in .s output")); 75 76static cl::opt<cl::boolOrDefault> 77ArgAsmVerbose("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 82static 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 94mcld::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 100mcld::LLVMTargetMachine::~LLVMTargetMachine() { 101 m_pTarget = 0; 102} 103 104const 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. 111static 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 138static 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 185bool 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 266bool 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 309bool 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 343bool 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