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/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 
     53 using namespace mcld;
     54 using 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 
     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 mcld::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 
    100 mcld::LLVMTargetMachine::~LLVMTargetMachine() {
    101   m_pTarget = 0;
    102 }
    103 
    104 const 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.
    111 static 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 
    138 static 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 
    185 bool 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 
    266 bool 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 
    309 bool 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 
    343 bool 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