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/Target/TargetMachine.h>
     10 
     11 #include <mcld/Module.h>
     12 #include <mcld/LinkerConfig.h>
     13 #include <mcld/CodeGen/MCLinker.h>
     14 #include <mcld/Support/raw_mem_ostream.h>
     15 #include <mcld/Support/TargetRegistry.h>
     16 #include <mcld/Support/ToolOutputFile.h>
     17 #include <mcld/Support/MemoryArea.h>
     18 #include <mcld/Target/TargetLDBackend.h>
     19 
     20 #include <llvm/ADT/OwningPtr.h>
     21 #include <llvm/Analysis/Passes.h>
     22 #include <llvm/Analysis/Verifier.h>
     23 #include <llvm/Assembly/PrintModulePass.h>
     24 #include <llvm/CodeGen/AsmPrinter.h>
     25 #include <llvm/CodeGen/MachineFunctionAnalysis.h>
     26 #include <llvm/CodeGen/MachineModuleInfo.h>
     27 #include <llvm/CodeGen/GCStrategy.h>
     28 #include <llvm/CodeGen/Passes.h>
     29 #include <llvm/IR/DataLayout.h>
     30 #include <llvm/MC/MCAsmInfo.h>
     31 #include <llvm/MC/MCStreamer.h>
     32 #include <llvm/MC/MCInstrInfo.h>
     33 #include <llvm/MC/MCSubtargetInfo.h>
     34 #include <llvm/MC/MCObjectStreamer.h>
     35 #include <llvm/MC/MCAssembler.h>
     36 #include <llvm/MC/MCObjectWriter.h>
     37 #include <llvm/MC/MCContext.h>
     38 #include <llvm/PassManager.h>
     39 #include <llvm/Support/CommandLine.h>
     40 #include <llvm/Support/Debug.h>
     41 #include <llvm/Support/TargetRegistry.h>
     42 #include <llvm/Support/FormattedStream.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 //===----------------------------------------------------------------------===//
     59 // Enable or disable FastISel. Both options are needed, because
     60 // FastISel is enabled by default with -fast, and we wish to be
     61 // able to enable or disable fast-isel independently from -O0.
     62 
     63 static cl::opt<cl::boolOrDefault>
     64 ArgEnableFastISelOption("lfast-isel", cl::Hidden,
     65   cl::desc("Enable the \"fast\" instruction selector"));
     66 
     67 static cl::opt<bool>
     68 ArgShowMCEncoding("lshow-mc-encoding",
     69                 cl::Hidden,
     70                 cl::desc("Show encoding in .s output"));
     71 
     72 static cl::opt<bool>
     73 ArgShowMCInst("lshow-mc-inst",
     74               cl::Hidden,
     75               cl::desc("Show instruction structure in .s output"));
     76 
     77 static cl::opt<cl::boolOrDefault>
     78 ArgAsmVerbose("fverbose-asm",
     79               cl::desc("Put extra commentary information in the \
     80                        generated assembly code to make it more readable."),
     81               cl::init(cl::BOU_UNSET));
     82 
     83 static bool getVerboseAsm() {
     84   switch (ArgAsmVerbose) {
     85   default:
     86   case cl::BOU_UNSET: return TargetMachine::getAsmVerbosityDefault();
     87   case cl::BOU_TRUE:  return true;
     88   case cl::BOU_FALSE: return false;
     89   }
     90 }
     91 
     92 
     93 //===---------------------------------------------------------------------===//
     94 /// MCLDTargetMachine
     95 //===----------------------------------------------------------------------===//
     96 mcld::MCLDTargetMachine::MCLDTargetMachine(llvm::TargetMachine &pTM,
     97                                            const mcld::Target& pTarget,
     98                                            const std::string& pTriple)
     99   : m_TM(pTM), m_pTarget(&pTarget), m_Triple(pTriple) {
    100 }
    101 
    102 mcld::MCLDTargetMachine::~MCLDTargetMachine() {
    103   m_pTarget = 0;
    104 }
    105 
    106 const mcld::Target& mcld::MCLDTargetMachine::getTarget() const
    107 {
    108   return *m_pTarget;
    109 }
    110 
    111 /// Turn exception handling constructs into something the code generators can
    112 /// handle.
    113 static void addPassesToHandleExceptions(llvm::TargetMachine *TM,
    114                                         PassManagerBase &PM) {
    115   switch (TM->getMCAsmInfo()->getExceptionHandlingType()) {
    116   case llvm::ExceptionHandling::SjLj:
    117     // SjLj piggy-backs on dwarf for this bit. The cleanups done apply to both
    118     // Dwarf EH prepare needs to be run after SjLj prepare. Otherwise,
    119     // catch info can get misplaced when a selector ends up more than one block
    120     // removed from the parent invoke(s). This could happen when a landing
    121     // pad is shared by multiple invokes and is also a target of a normal
    122     // edge from elsewhere.
    123     PM.add(createSjLjEHPreparePass(TM->getTargetLowering()));
    124     // FALLTHROUGH
    125   case llvm::ExceptionHandling::DwarfCFI:
    126   case llvm::ExceptionHandling::ARM:
    127   case llvm::ExceptionHandling::Win64:
    128     PM.add(createDwarfEHPass(TM->getTargetLowering()));
    129     break;
    130   case llvm::ExceptionHandling::None:
    131     PM.add(createLowerInvokePass(TM->getTargetLowering()));
    132 
    133     // The lower invoke pass may create unreachable code. Remove it.
    134     PM.add(createUnreachableBlockEliminationPass());
    135     break;
    136   }
    137 }
    138 
    139 
    140 static llvm::MCContext *addPassesToGenerateCode(llvm::LLVMTargetMachine *TM,
    141                                                 PassManagerBase &PM,
    142                                                 bool DisableVerify)
    143 {
    144   // Targets may override createPassConfig to provide a target-specific sublass.
    145   TargetPassConfig *PassConfig = TM->createPassConfig(PM);
    146 
    147   // Set PassConfig options provided by TargetMachine.
    148   PassConfig->setDisableVerify(DisableVerify);
    149 
    150   PM.add(PassConfig);
    151 
    152   PassConfig->addIRPasses();
    153 
    154   addPassesToHandleExceptions(TM, PM);
    155 
    156   PassConfig->addISelPrepare();
    157 
    158   // Install a MachineModuleInfo class, which is an immutable pass that holds
    159   // all the per-module stuff we're generating, including MCContext.
    160   MachineModuleInfo *MMI =
    161     new MachineModuleInfo(*TM->getMCAsmInfo(), *TM->getRegisterInfo(),
    162                           &TM->getTargetLowering()->getObjFileLowering());
    163   PM.add(MMI);
    164   MCContext *Context = &MMI->getContext(); // Return the MCContext by-ref.
    165 
    166   // Set up a MachineFunction for the rest of CodeGen to work on.
    167   PM.add(new MachineFunctionAnalysis(*TM));
    168 
    169   // Enable FastISel with -fast, but allow that to be overridden.
    170   if (ArgEnableFastISelOption == cl::BOU_TRUE ||
    171       (TM->getOptLevel() == CodeGenOpt::None &&
    172        ArgEnableFastISelOption != cl::BOU_FALSE))
    173     TM->setFastISel(true);
    174 
    175   // Ask the target for an isel.
    176   if (PassConfig->addInstSelector())
    177     return NULL;
    178 
    179   PassConfig->addMachinePasses();
    180 
    181   PassConfig->setInitialized();
    182 
    183   return Context;
    184 
    185 }
    186 
    187 bool mcld::MCLDTargetMachine::addPassesToEmitFile(PassManagerBase &pPM,
    188                                              mcld::ToolOutputFile& pOutput,
    189                                              mcld::CodeGenFileType pFileType,
    190                                              CodeGenOpt::Level pOptLvl,
    191                                              mcld::Module& pModule,
    192                                              LinkerConfig& pConfig,
    193                                              bool pDisableVerify)
    194 {
    195 
    196   llvm::MCContext* Context =
    197           addPassesToGenerateCode(static_cast<llvm::LLVMTargetMachine*>(&m_TM),
    198                                   pPM, pDisableVerify);
    199   if (!Context)
    200     return true;
    201 
    202   switch(pFileType) {
    203   default:
    204   case mcld::CGFT_NULLFile:
    205     assert(0 && "fatal: file type is not set!");
    206     break;
    207   case CGFT_ASMFile: {
    208     assert(Context != 0 && "Failed to get MCContext");
    209 
    210     if (getTM().hasMCSaveTempLabels())
    211       Context->setAllowTemporaryLabels(false);
    212 
    213     if (addCompilerPasses(pPM,
    214                           pOutput.formatted_os(),
    215                           Context))
    216       return true;
    217     break;
    218   }
    219   case CGFT_OBJFile: {
    220     assert(Context != 0 && "Failed to get MCContext");
    221 
    222     if (getTM().hasMCSaveTempLabels())
    223       Context->setAllowTemporaryLabels(false);
    224     if (addAssemblerPasses(pPM,
    225                            pOutput.mem_os(),
    226                            Context))
    227       return true;
    228     break;
    229   }
    230   case CGFT_EXEFile: {
    231     pConfig.setCodeGenType(LinkerConfig::Exec);
    232     if (addLinkerPasses(pPM,
    233                         pConfig,
    234                         pModule,
    235                         pOutput.memory(),
    236                         Context))
    237       return true;
    238     break;
    239   }
    240   case CGFT_BINARY: {
    241     pConfig.setCodeGenType(LinkerConfig::Binary);
    242     if (addLinkerPasses(pPM,
    243                         pConfig,
    244                         pModule,
    245                         pOutput.memory(),
    246                         Context))
    247       return true;
    248     break;
    249   }
    250   case CGFT_DSOFile: {
    251     pConfig.setCodeGenType(LinkerConfig::DynObj);
    252     if (addLinkerPasses(pPM,
    253                         pConfig,
    254                         pModule,
    255                         pOutput.memory(),
    256                         Context))
    257       return true;
    258     break;
    259   }
    260   case CGFT_PARTIAL: {
    261     pConfig.setCodeGenType(LinkerConfig::Object);
    262     if (addLinkerPasses(pPM,
    263                         pConfig,
    264                         pModule,
    265                         pOutput.memory(),
    266                         Context))
    267       return true;
    268     break;
    269   }
    270   } // switch
    271   return false;
    272 }
    273 
    274 bool mcld::MCLDTargetMachine::addCompilerPasses(PassManagerBase &pPM,
    275                                                 llvm::formatted_raw_ostream &pOutput,
    276                                                 llvm::MCContext *&Context)
    277 {
    278   const MCAsmInfo &MAI = *getTM().getMCAsmInfo();
    279   const MCInstrInfo &MII = *getTM().getInstrInfo();
    280   const MCRegisterInfo &MRI = *getTM().getRegisterInfo();
    281   const MCSubtargetInfo &STI = getTM().getSubtarget<MCSubtargetInfo>();
    282 
    283   MCInstPrinter *InstPrinter =
    284     getTarget().get()->createMCInstPrinter(MAI.getAssemblerDialect(), MAI,
    285                                            MII,
    286                                            Context->getRegisterInfo(), STI);
    287 
    288   MCCodeEmitter* MCE = 0;
    289   MCAsmBackend *MAB = 0;
    290   if (ArgShowMCEncoding) {
    291     MCE = getTarget().get()->createMCCodeEmitter(MII, MRI, STI, *Context);
    292     MAB = getTarget().get()->createMCAsmBackend(m_Triple,
    293                                                 getTM().getTargetCPU());
    294   }
    295 
    296 
    297   // now, we have MCCodeEmitter and MCAsmBackend, we can create AsmStreamer.
    298   OwningPtr<MCStreamer> AsmStreamer(
    299     getTarget().get()->createAsmStreamer(*Context, pOutput,
    300                                          getVerboseAsm(),
    301                                          getTM().hasMCUseLoc(),
    302                                          getTM().hasMCUseCFI(),
    303                                          getTM().hasMCUseDwarfDirectory(),
    304                                          InstPrinter,
    305                                          MCE, MAB,
    306                                          ArgShowMCInst));
    307 
    308   llvm::MachineFunctionPass* funcPass =
    309     getTarget().get()->createAsmPrinter(getTM(), *AsmStreamer.get());
    310 
    311   if (funcPass == 0)
    312     return true;
    313   // If successful, createAsmPrinter took ownership of AsmStreamer
    314   AsmStreamer.take();
    315   pPM.add(funcPass);
    316   return false;
    317 }
    318 
    319 bool mcld::MCLDTargetMachine::addAssemblerPasses(PassManagerBase &pPM,
    320                                                  llvm::raw_ostream &pOutput,
    321                                                  llvm::MCContext *&Context)
    322 {
    323   // MCCodeEmitter
    324   const MCInstrInfo &MII = *getTM().getInstrInfo();
    325   const MCRegisterInfo &MRI = *getTM().getRegisterInfo();
    326   const MCSubtargetInfo &STI = getTM().getSubtarget<MCSubtargetInfo>();
    327   MCCodeEmitter* MCE =
    328     getTarget().get()->createMCCodeEmitter(MII, MRI, STI, *Context);
    329 
    330   // MCAsmBackend
    331   MCAsmBackend* MAB =
    332     getTarget().get()->createMCAsmBackend(m_Triple,getTM().getTargetCPU());
    333   if (MCE == 0 || MAB == 0)
    334     return true;
    335 
    336   // now, we have MCCodeEmitter and MCAsmBackend, we can create AsmStreamer.
    337   OwningPtr<MCStreamer> AsmStreamer(getTarget().get()->createMCObjectStreamer(
    338                                                               m_Triple,
    339                                                               *Context,
    340                                                               *MAB,
    341                                                               pOutput,
    342                                                               MCE,
    343                                                               getTM().hasMCRelaxAll(),
    344                                                               getTM().hasMCNoExecStack()));
    345   AsmStreamer.get()->InitSections();
    346   MachineFunctionPass *funcPass = getTarget().get()->createAsmPrinter(getTM(),
    347                                                                       *AsmStreamer.get());
    348   if (funcPass == 0)
    349     return true;
    350   // If successful, createAsmPrinter took ownership of AsmStreamer
    351   AsmStreamer.take();
    352   pPM.add(funcPass);
    353   return false;
    354 }
    355 
    356 bool mcld::MCLDTargetMachine::addLinkerPasses(PassManagerBase &pPM,
    357                                               LinkerConfig& pConfig,
    358                                               mcld::Module& pModule,
    359                                               mcld::MemoryArea& pOutput,
    360                                               llvm::MCContext *&Context)
    361 {
    362   if (NULL == pOutput.handler())
    363     return true;
    364 
    365   // set up output's SOName
    366   if (pConfig.options().soname().empty()) {
    367     // if the output is a shared object, and the option -soname was not
    368     // enable, set soname as the output file name. soname must be UTF-8 string.
    369     pModule.setName(pOutput.handler()->path().filename().native());
    370   }
    371   else {
    372     pModule.setName(pConfig.options().soname());
    373   }
    374 
    375   MachineFunctionPass* funcPass = getTarget().createMCLinker(m_Triple,
    376                                                              pConfig,
    377                                                              pModule,
    378                                                              pOutput);
    379   if (NULL == funcPass)
    380     return true;
    381 
    382   pPM.add(funcPass);
    383   return false;
    384 }
    385 
    386