Home | History | Annotate | Download | only in CodeGen
      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