Home | History | Annotate | Download | only in CodeGen
      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 
     52 using namespace mcld;
     53 using 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 
     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 //===----------------------------------------------------------------------===//
     95 mcld::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 
    101 mcld::LLVMTargetMachine::~LLVMTargetMachine() {
    102   m_pTarget = 0;
    103 }
    104 
    105 const 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.
    112 static 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 
    139 static 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 
    186 bool 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 
    263 bool 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 
    308 bool 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 
    345 bool 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