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/MCLDFile.h> 13#include <mcld/Support/RealPath.h> 14#include <mcld/Support/TargetRegistry.h> 15#include <mcld/Target/TargetMachine.h> 16#include <mcld/Target/TargetLDBackend.h> 17 18#include <llvm/ADT/OwningPtr.h> 19#include <llvm/Analysis/Passes.h> 20#include <llvm/Analysis/Verifier.h> 21#include <llvm/Assembly/PrintModulePass.h> 22#include <llvm/CodeGen/AsmPrinter.h> 23#include <llvm/CodeGen/MachineFunctionAnalysis.h> 24#include <llvm/CodeGen/MachineModuleInfo.h> 25#include <llvm/CodeGen/GCStrategy.h> 26#include <llvm/CodeGen/Passes.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/Support/ToolOutputFile.h> 41#include <llvm/Target/TargetData.h> 42#include <llvm/Target/TargetInstrInfo.h> 43#include <llvm/Target/TargetLowering.h> 44#include <llvm/Target/TargetOptions.h> 45#include <llvm/Target/TargetSubtargetInfo.h> 46#include <llvm/Target/TargetLoweringObjectFile.h> 47#include <llvm/Target/TargetRegisterInfo.h> 48#include <llvm/Transforms/Scalar.h> 49 50#include <string> 51 52using namespace mcld; 53using namespace llvm; 54 55//===----------------------------------------------------------------------===// 56/// Arguments 57//===----------------------------------------------------------------------===// 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 94//===----------------------------------------------------------------------===// 95mcld::LLVMTargetMachine::LLVMTargetMachine(llvm::TargetMachine &pTM, 96 const mcld::Target& pTarget, 97 const std::string& pTriple ) 98 : m_TM(pTM), m_pTarget(&pTarget), m_Triple(pTriple) { 99} 100 101mcld::LLVMTargetMachine::~LLVMTargetMachine() { 102 m_pTarget = 0; 103} 104 105const mcld::Target& mcld::LLVMTargetMachine::getTarget() const 106{ 107 return *m_pTarget; 108} 109 110/// Turn exception handling constructs into something the code generators can 111/// handle. 112static void addPassesToHandleExceptions(llvm::TargetMachine *TM, 113 PassManagerBase &PM) { 114 switch (TM->getMCAsmInfo()->getExceptionHandlingType()) { 115 case llvm::ExceptionHandling::SjLj: 116 // SjLj piggy-backs on dwarf for this bit. The cleanups done apply to both 117 // Dwarf EH prepare needs to be run after SjLj prepare. Otherwise, 118 // catch info can get misplaced when a selector ends up more than one block 119 // removed from the parent invoke(s). This could happen when a landing 120 // pad is shared by multiple invokes and is also a target of a normal 121 // edge from elsewhere. 122 PM.add(createSjLjEHPreparePass(TM->getTargetLowering())); 123 // FALLTHROUGH 124 case llvm::ExceptionHandling::DwarfCFI: 125 case llvm::ExceptionHandling::ARM: 126 case llvm::ExceptionHandling::Win64: 127 PM.add(createDwarfEHPass(TM)); 128 break; 129 case llvm::ExceptionHandling::None: 130 PM.add(createLowerInvokePass(TM->getTargetLowering())); 131 132 // The lower invoke pass may create unreachable code. Remove it. 133 PM.add(createUnreachableBlockEliminationPass()); 134 break; 135 } 136} 137 138 139static llvm::MCContext *addPassesToGenerateCode(llvm::LLVMTargetMachine *TM, 140 PassManagerBase &PM, 141 bool DisableVerify) 142{ 143 // Targets may override createPassConfig to provide a target-specific sublass. 144 TargetPassConfig *PassConfig = TM->createPassConfig(PM); 145 146 // Set PassConfig options provided by TargetMachine. 147 PassConfig->setDisableVerify(DisableVerify); 148 149 PM.add(PassConfig); 150 151 PassConfig->addIRPasses(); 152 153 addPassesToHandleExceptions(TM, PM); 154 155 PassConfig->addISelPrepare(); 156 157 // Install a MachineModuleInfo class, which is an immutable pass that holds 158 // all the per-module stuff we're generating, including MCContext. 159 MachineModuleInfo *MMI = 160 new MachineModuleInfo(*TM->getMCAsmInfo(), *TM->getRegisterInfo(), 161 &TM->getTargetLowering()->getObjFileLowering()); 162 PM.add(MMI); 163 MCContext *Context = &MMI->getContext(); // Return the MCContext by-ref. 164 165 // Set up a MachineFunction for the rest of CodeGen to work on. 166 PM.add(new MachineFunctionAnalysis(*TM)); 167 168 // Enable FastISel with -fast, but allow that to be overridden. 169 if (ArgEnableFastISelOption == cl::BOU_TRUE || 170 (TM->getOptLevel() == CodeGenOpt::None && 171 ArgEnableFastISelOption != cl::BOU_FALSE)) 172 TM->setFastISel(true); 173 174 // Ask the target for an isel. 175 if (PassConfig->addInstSelector()) 176 return NULL; 177 178 PassConfig->addMachinePasses(); 179 180 PassConfig->setInitialized(); 181 182 return Context; 183 184} 185 186bool mcld::LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &pPM, 187 formatted_raw_ostream &Out, 188 const std::string& pOutputFilename, 189 mcld::CodeGenFileType pFileType, 190 CodeGenOpt::Level pOptLvl, 191 SectLinkerOption *pLinkerOpt, 192 bool pDisableVerify) 193{ 194 195 llvm::MCContext* Context = 196 addPassesToGenerateCode(static_cast<llvm::LLVMTargetMachine*>(&m_TM), 197 pPM, pDisableVerify); 198 if (!Context) 199 return true; 200 201 switch(pFileType) { 202 default: 203 case mcld::CGFT_NULLFile: 204 assert(0 && "fatal: file type is not set!"); 205 break; 206 case CGFT_ASMFile: { 207 assert(Context != 0 && "Failed to get MCContext"); 208 209 if (getTM().hasMCSaveTempLabels()) 210 Context->setAllowTemporaryLabels(false); 211 212 if (addCompilerPasses(pPM, 213 Out, 214 pOutputFilename, 215 Context)) 216 return true; 217 218 pPM.add(createGCInfoDeleter()); // not in addPassesToMC 219 break; 220 } 221 case CGFT_OBJFile: { 222 assert(Context != 0 && "Failed to get MCContext"); 223 224 if (getTM().hasMCSaveTempLabels()) 225 Context->setAllowTemporaryLabels(false); 226 if (addAssemblerPasses(pPM, 227 Out, 228 pOutputFilename, 229 Context)) 230 return true; 231 232 pPM.add(createGCInfoDeleter()); // not in addPassesToMC 233 break; 234 } 235 case CGFT_EXEFile: { 236 if (pLinkerOpt == NULL) 237 return true; 238 239 if (addLinkerPasses(pPM, 240 pLinkerOpt, 241 pOutputFilename, 242 MCLDFile::Exec, 243 Context)) 244 return true; 245 break; 246 } 247 case CGFT_DSOFile: { 248 if (pLinkerOpt == NULL) 249 return true; 250 251 if (addLinkerPasses(pPM, 252 pLinkerOpt, 253 pOutputFilename, 254 MCLDFile::DynObj, 255 Context)) 256 return true; 257 break; 258 } 259 } // switch 260 return false; 261} 262 263bool mcld::LLVMTargetMachine::addCompilerPasses(PassManagerBase &pPM, 264 formatted_raw_ostream &Out, 265 const std::string& pOutputFilename, 266 llvm::MCContext *&Context) 267{ 268 const MCAsmInfo &MAI = *getTM().getMCAsmInfo(); 269 const MCInstrInfo &MII = *getTM().getInstrInfo(); 270 const MCRegisterInfo &MRI = *getTM().getRegisterInfo(); 271 const MCSubtargetInfo &STI = getTM().getSubtarget<MCSubtargetInfo>(); 272 273 MCInstPrinter *InstPrinter = 274 getTarget().get()->createMCInstPrinter(MAI.getAssemblerDialect(), MAI, 275 MII, 276 Context->getRegisterInfo(), STI); 277 278 MCCodeEmitter* MCE = 0; 279 MCAsmBackend *MAB = 0; 280 if (ArgShowMCEncoding) { 281 MCE = getTarget().get()->createMCCodeEmitter(MII, MRI, STI, *Context); 282 MAB = getTarget().get()->createMCAsmBackend(m_Triple); 283 } 284 285 286 // now, we have MCCodeEmitter and MCAsmBackend, we can create AsmStreamer. 287 OwningPtr<MCStreamer> AsmStreamer( 288 getTarget().get()->createAsmStreamer(*Context, Out, 289 getVerboseAsm(), 290 getTM().hasMCUseLoc(), 291 getTM().hasMCUseCFI(), 292 getTM().hasMCUseDwarfDirectory(), 293 InstPrinter, 294 MCE, MAB, 295 ArgShowMCInst)); 296 297 llvm::MachineFunctionPass* funcPass = 298 getTarget().get()->createAsmPrinter(getTM(), *AsmStreamer.get()); 299 300 if (funcPass == 0) 301 return true; 302 // If successful, createAsmPrinter took ownership of AsmStreamer 303 AsmStreamer.take(); 304 pPM.add(funcPass); 305 return false; 306} 307 308bool mcld::LLVMTargetMachine::addAssemblerPasses(PassManagerBase &pPM, 309 formatted_raw_ostream &Out, 310 const std::string& pOutputFilename, 311 llvm::MCContext *&Context) 312{ 313 // MCCodeEmitter 314 const MCInstrInfo &MII = *getTM().getInstrInfo(); 315 const MCRegisterInfo &MRI = *getTM().getRegisterInfo(); 316 const MCSubtargetInfo &STI = getTM().getSubtarget<MCSubtargetInfo>(); 317 MCCodeEmitter* MCE = 318 getTarget().get()->createMCCodeEmitter(MII, MRI, STI, *Context); 319 320 // MCAsmBackend 321 MCAsmBackend* MAB = getTarget().get()->createMCAsmBackend(m_Triple); 322 if (MCE == 0 || MAB == 0) 323 return true; 324 325 // now, we have MCCodeEmitter and MCAsmBackend, we can create AsmStreamer. 326 OwningPtr<MCStreamer> AsmStreamer(getTarget().get()->createMCObjectStreamer( 327 m_Triple, 328 *Context, 329 *MAB, 330 Out, 331 MCE, 332 getTM().hasMCRelaxAll(), 333 getTM().hasMCNoExecStack())); 334 AsmStreamer.get()->InitSections(); 335 MachineFunctionPass *funcPass = getTarget().get()->createAsmPrinter(getTM(), 336 *AsmStreamer.get()); 337 if (funcPass == 0) 338 return true; 339 // If successful, createAsmPrinter took ownership of AsmStreamer 340 AsmStreamer.take(); 341 pPM.add(funcPass); 342 return false; 343} 344 345bool mcld::LLVMTargetMachine::addLinkerPasses(PassManagerBase &pPM, 346 SectLinkerOption *pLinkerOpt, 347 const std::string &pOutputFilename, 348 MCLDFile::Type pOutputLinkType, 349 llvm::MCContext *&Context) 350{ 351 TargetLDBackend* ldBackend = getTarget().createLDBackend(m_Triple); 352 if (0 == ldBackend) 353 return true; 354 355 // set up output's SOName 356 if (pOutputLinkType == MCLDFile::DynObj && 357 pLinkerOpt->info().output().name().empty()) { 358 // if the output is a shared object, and the option -soname was not 359 // enable, set soname as the output file name. 360 pLinkerOpt->info().output().setSOName(pOutputFilename); 361 } 362 363 pLinkerOpt->info().output().setPath(sys::fs::RealPath(pOutputFilename)); 364 pLinkerOpt->info().output().setType(pOutputLinkType); 365 366 MachineFunctionPass* funcPass = getTarget().createSectLinker(m_Triple, 367 *pLinkerOpt, 368 *ldBackend); 369 if (0 == funcPass) 370 return true; 371 372 pPM.add(funcPass); 373 return false; 374} 375 376